Imported from akshatdalton/skills (
today/SKILL.md). Install upstream withnpx skills add akshatdalton/skills --skill today. Copyright stays with the author.
For all per-ticket state mutations, see shared progress policy.
Today โ Engineering Command Center (v0.2 โ vault-backed)
Polymorphic skill. One entry point for all daily-planning + dashboard interactions. Routes by sub-mode argument.
Source of truth (v0.4, .raw/work operational store):
- Tickets live in
<claude-obsidian>/.raw/work/<project>/<ticket>/progress.mdfrontmatter โ this store is THE board. (<claude-obsidian>=~/opensource/claude-obsidian, orโฆ-testuntil the rename.) The/trackskill is the per-ticket writer;/todayis the reader/board. - Today vs Backlog lives in each ticket's
progress.mdfrontmatter under abucket: today | backlogfield (defaultbacklog). Edited viaprogress_fm.py bucket set. - The Obsidian board at
<claude-obsidian>/.raw/work/Tasks.md(it lives with the tickets it projects) is a projection you can edit by dragging cards.~/.claude/skills/today/scripts/kanban.pysyncs both ways: readback at the start of every /today, render at the end. - Needs-your-input items live in each ticket's
progress.mdfrontmatter under aneeds_input:field. No separate file.
Sub-modes
| Invocation | Mode | What it does |
|---|---|---|
/today |
render | Default. Show dashboard: Needs Your Input โ , Today's ordered list, Tomorrow, all P0/P1/P2. |
/today list |
list | Compact table view. Columns: priority ยท ticket ยท stage ยท repo ยท PR ยท initiative. |
/today plan |
plan | Interactive: set each ticket's bucket (today vs backlog). Asks where each unplanned ticket fits. |
/today next |
next | Start the โ
task via /ship-task. |
/today ingest <dump> |
ingest | Parse a meeting/discussion dump โ propose candidate tickets (via /create-jira-ticket-with-reference), decisions (into vault learnings.md), and priority placements. |
/today retro |
retro | Sprint wrap-up report (lazy-loaded; see retro.md in skill dir). |
/today oncall [page|triage|sheet] โฆ |
oncall | On-call command center for the TM/Career Hub primary rotation: live PagerDuty incidents, due-date-ordered triage tickets, follow-ups, incident-diagnosis playbook (lazy-loaded; see oncall.md). triage is now a thin alias for the standalone /rca skill, where RCA discipline lives. |
/today meetings |
meetings | List auto-recorded meeting transcripts awaiting a summary. |
/today meeting <slug|latest> |
meeting | Summarize a recorded meeting โ write summary.md + surface TL;DR / action items / decisions; offer to ingest items. |
Pre-entry: refresh state (foundation hook)
On every invocation:
Step 0 โ Fold in Obsidian board edits (Kanban readback)
Before reading the store, pull any card drags from the Obsidian Kanban board (<claude-obsidian>/.raw/work/Tasks.md) back into ticket frontmatter, so the in-memory board reflects them:
python3 ~/.claude/skills/today/scripts/kanban.py readback
This writes state / bucket changes into each affected progress.md (split-by-field rule: your drag wins for today/backlog placement, automation wins for PR-driven stage). Unknown/draft cards are left untouched. No-op if Tasks.md doesn't exist yet.
Step 1 โ Build the in-memory board by walking vault (frontmatter ONLY)
Critical efficiency rule: /today only needs YAML frontmatter from each progress.md (~15 lines). The body is hundreds of lines per ticket and is brain-recall's territory, not /today's. NEVER use the Read tool to load progress.md files โ that wastes context on body content you don't need.
Use a single Bash call that extracts frontmatter from ALL active progress files in one shot:
BASE=~/opensource/claude-obsidian; [ -d "$BASE" ] || BASE=~/opensource/claude-obsidian-test
for f in "$BASE"/.raw/work/*/*/progress.md; do # <project>/<ticket>/progress.md (active; skips archive/)
[ -f "$f" ] || continue
echo "=== $f ==="
awk '/^---$/{c++; if(c==2)exit; next} c==1{print}' "$f"
done
The glob is project- and id-agnostic (vscode/wipdp/magnetx/claude-code/โฆ and ENG-/CS-/slug tickets alike). For /today list --include-archived, also walk "$BASE"/.raw/work/archive/*/*/progress.md in the same loop.
The output is a single block of === <path> === headers followed by frontmatter blocks. Parse this in-memory.
For each ticket, extract:
ticket,title,project(vscode|wipdp),branch,pr,pr_state,state,priority,bucket(today|backlog; default backlog),initiative,created,last-touchedneeds_inputblock if present ({reason, action, added_at})session_ids(informational; not surfaced in dashboard)
This in-memory list IS the board. No board.json read. No per-file Read calls.
Step 2 โ Derive Today / Backlog from bucket
No today.json read. Each in-memory ticket already carries bucket (today | backlog, default backlog) from Step 1. Today = bucket == today; Backlog = bucket == backlog. bucket persists in frontmatter (set by your Obsidian drags via Step 0, or by plan mode), so there is no daily date/carry-forward to manage.
Step 3 โ Refresh PR state in parallel (gh CLI, NOT GitHub MCP)
Repo โ GH mapping (use these exact prefixes; do not guess org names):
vscode โ GH_HOST=github.com gh ... --repo EightfoldAI/vscode
wipdp โ GH_HOST=github.com gh ... --repo EightfoldAI/wipdp
For each in-memory ticket with pr set, fire all PR fetches as separate Bash tool calls in the same response (parallel):
GH_HOST=github.com gh pr view <N> --repo EightfoldAI/<repo> --json state,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,headRefOid,mergedAt
For each PR's headRefOid, also fetch the commit status channel in parallel (catches external CI like NPM Test, Playwright, CI Test Suite):
GH_HOST=github.com gh api repos/EightfoldAI/<repo>/commits/<sha>/status --jq '.state'
GH_HOST=github.com gh api repos/EightfoldAI/<repo>/commits/<sha>/check-runs --jq '[.check_runs[]|.conclusion]'
Reconcile both channels โ task is ci-failing if EITHER has a failure. Apply auto-stage-transitions:
- merged โ state
merged,pr_state: MERGED(renders in the Done lane; brain-ingest archives it off the board on merge) - approved + both channels green + 0 unresolved โ
ready-to-merge+ addneeds_input: {reason: ready-to-merge, action: "merge it"} - any channel reports
failureโci+ addneeds_input: {reason: ci-failing, action: "fix CI on PR #N"} - else โ keep
in-review
Step 4 โ Refresh stale Jira state in parallel
For each task WITHOUT a PR (stage todo/in-progress) OR with last-touched > 1h old โ batch-call mcp__claude_ai_Atlassian__getJiraIssue in parallel to refresh title, status, sprint, priority, assignee. This is the only place Atlassian MCP is used; GitHub data always comes from gh. Before the first Atlassian call, run ToolSearch select:mcp__claude_ai_Atlassian__getJiraIssue to load the schema โ it is deferred and not callable without this step.
Step 5 โ Write changes back to vault (frontmatter only, surgical edits)
For each ticket whose state changed in steps 3-4, rewrite ONLY the YAML frontmatter of its progress.md โ never touch the body. Update: state, pr_state, priority, last-touched: <today>, and add/remove needs_input block.
How to write efficiently (avoid loading the body):
- Use
Edittool with a precise old-string โ new-string replacement targeting only the frontmatter line(s) that changed (e.g., replacingstate: in-reviewwithstate: merged). Edit doesn't require Reading the whole file first. - For multi-field updates, use a small Bash +
sedone-liner targeting only the YAML region (lines between the first two---markers). - Do NOT use the
Readtool on progress.md as a precursor to writing โ you already have the frontmatter in memory from Step 1.
Vault write rule: /today is permitted to update progress.md frontmatter (machine-managed metadata). The body of progress.md remains brain-ingest's territory (per CLAUDE.md). This separation means /today can keep state fresh without bumping into brain-ingest's session-distillation responsibility.
Step 6 โ Tooling rule
gh CLI for GitHub, Atlassian MCP for Jira, never the other way.
Step 7 โ Watcher-status check (per task with PR + CI failing)
/loop and /pr-watcher die when the user closes Claude Code, so a "watcher running" status is only meaningful in a live session. For each task where CI is failing, check watcher_session_id in progress.md frontmatter (set by /ship-task on entry):
- If absent โ render
โ no watcher session recorded - If present โ render
โ resume with: claude -r <watcher_session_id>(this session has the implementation context โ reattaching is faster than starting fresh)
User can either claude -r <id> to reattach or run /ship-task <TICKET> from the current session. Never auto-schedule /loop, CronCreate, or /pr-watcher from /today.
Step 8 โ Render the Obsidian board (Kanban render)
After all vault writes (steps 3โ5), regenerate the board so Obsidian reflects the fresh state:
python3 ~/.claude/skills/today/scripts/kanban.py render
Lanes are Backlog | To Do | In Progress | In Review | Done (lane = function of state + bucket). Card order within each lane and the %% kanban:settings %% block are preserved across renders.
Step 9 โ BRIEFING gather + stitch (new in v0.4)
The โ BRIEFING block above the existing dashboard is what makes /today an HQ instead of just an engineering board. Six parallel source agents fan out, each returns a structured JSON envelope, brain-recall correlates each item to active vault state, and the result renders above NEEDS YOUR INPUT.
Dispatch โ single-message parallel via superpowers:dispatching-parallel-agents:
Invoke six general-purpose subagents in ONE response (six tool calls in one message โ true parallel). Each subagent's prompt is the corresponding spec file's content, with the cursor JSON's last_run_ts and current now substituted in.
| Subagent | Spec file | Cursor file |
|---|---|---|
| 1 | ~/.claude/skills/today/sources/gcal.md |
~/.claude/skills/today/state/sources/gcal.json |
| 2 | ~/.claude/skills/today/sources/meetily.md |
~/.claude/skills/today/state/sources/meetily.json |
| 3 | ~/.claude/skills/today/sources/gmail.md |
~/.claude/skills/today/state/sources/gmail.json |
| 4 | ~/.claude/skills/today/sources/slack.md |
~/.claude/skills/today/state/sources/slack.json |
| 5 | ~/.claude/skills/today/sources/github-review.md |
~/.claude/skills/today/state/sources/github-review.json |
| 6 | ~/.claude/skills/today/sources/jira-new.md |
~/.claude/skills/today/state/sources/jira-new.json |
Each subagent returns a JSON envelope per the contract in its spec file:
{
"source": "<name>",
"fetched_at": "<ISO8601>",
"cursor_advance": "<ISO8601>",
"items": [
{"source_id":"...","ts":"...","title":"...","action":"...","project_hint":"vscode|wipdp|null","urgency":"now|today|fyi"}
],
"fyi_count": <int>,
"errors": []
}
Latency budget for the whole step: under 30s. Surface a timing footer in the BRIEFING during v0.4 stabilization; remove once stable.
Stitch step โ correlate to active tickets/initiatives:
For each item across all six sources, when project_hint is set OR the title contains an ENG-\d+ pattern, run a quick correlation:
- Match against active progress.md frontmatter (use
~/.claude/scripts/progress_fm.py list) - If the item references a known ticket, attach
correlated_ticket: ENG-XXXXXand surface inline as(โ ENG-XXXXX)in the render - If the item references a known initiative (via project's initiative dir), attach
correlated_initiative: <slug>and surface as(โ initiative: <slug>)
This is what makes the BRIEFING feel connected to the rest of the board instead of being a separate inbox.
Cursor advance โ only after successful render:
After Step 10 (BRIEFING render) completes successfully, write each subagent's cursor_advance value back to its cursor file:
import json, pathlib
for r in results: # list of subagent JSON envelopes
if r.get("errors"):
continue # don't advance cursor on error
cf = pathlib.Path.home() / ".claude/skills/today/state/sources" / f"{r['source']}.json"
cur = json.loads(cf.read_text())
cur["last_run_ts"] = r["cursor_advance"]
cur["fetched_count"] = len(r["items"])
cf.write_text(json.dumps(cur, indent=2))
If /today crashes mid-render, cursors stay at their previous value โ the next run re-shows the items.
Step 9.5 โ Wiki hot-cache read (v2 brain; inline, NO subagent)
Also read the LAST line of ~/.claude/brain-ingest-queue/status.jsonl (if it exists): the most recent background brain-ingest run. If its ts is within the last 24h, render one footer line: ๐ง Last bg ingest: <project> <status> ($<cost>, <relative time>) โ and if status is error, add โ check <log path>. This replaces the old desktop notifications as the visibility channel.
Read the TOP session block only (first ## <date> โ ... block, ~150 words) of ~/opensource/claude-obsidian-test/wiki/hot.md. Zero-latency, no agent. Two uses:
- Render one footer line in the BRIEFING:
๐ Wiki: <one-line gist of the top block> โ [[Page A]] ยท [[Page B]](the 2-3 most actionable wikilinks from that block). Skip the line entirely if the vault is missing or the top block is older than 7 days (stale context is worse than none). - Correlate: if a BRIEFING item's topic matches a wikilink in the block (e.g. an oncall page arriving while
[[On-call Triage Pattern]]is hot), append(๐ wiki has context)to that item โ it tells Akshat a/brain-recall --v2 <topic>will be warm.
When Akshat picks a task (/today next or names a ticket), suggest /brain-recall <ticket> --v2 as the kickoff if the wiki has matching pages (quick check: cd ~/opensource/claude-obsidian-test && python3 scripts/bm25-index.py query "<ticket topic>" โ only when a topic is known; never block the render on it).
Step 10 โ Render the โ BRIEFING block
Render the BRIEFING above the existing dashboard. Block layout (omit any sub-block where items[] is empty and fyi_count == 0; otherwise collapse to a single line like (no new since HH:MM)):
โ
BRIEFING (<n total action items across sources>)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐
MEETINGS TODAY (<n>) [from gcal]
09:30 Sprint review ยท @prabh + @samyak [join (meetily armed)]
14:00 1:1 with @manager [join]
๐ MEETILY โ PROPOSED (<n>) [from meetily; need user confirm]
[2026-05-30-design-review]
โ propose ticket: "Add OWASP scan to wipdp CI"
โ save decision: "Q3 focus = source-integration-polish" (โ initiative: rag-for-tm)
๐ฌ SLACK โ action (<n>, since <last_run_ts>) [from slack]
#eng-vscode @prabh: "review the diff before EOD?" (โ ENG-191517)
#wipdp-pod @samyak: "RAG eval still failing โ owner?"
๐ง GMAIL โ action (<n of M unread since <ts>) [from gmail]
@legal-team: Re: data retention v3 โ needs sign-off
(<noise_count> noise filtered)
๐ GITHUB REVIEW QUEUE (<n>) [from github-review]
vscode#105800 @prabh agent-builder: add streaming 3d old
wipdp#4521 @samyak rag-eval-pipeline: fix flaky test 1d old
๐ JIRA โ new assignments (<n> since <ts>) [from jira-new]
ENG-194001 P1 vscode todo (assigned by @lead)
The existing dashboard renders BELOW the BRIEFING, unchanged. PICK block adds [confirm meetily] when proposed items are pending.
Step 11 โ Tooling rule reminder
Source agents use the tools listed in their spec. The /today main thread:
- gh CLI for the dashboard's existing PR refresh (Step 3) โ unchanged
- Atlassian MCP for the dashboard's existing Jira refresh (Step 4) โ unchanged
- progress_fm.py for any frontmatter writes โ see shared progress policy
- NEVER
slack_send_*/slack_schedule_*anywhere in this skill tree โ per[[feedback-slack-send-requires-caps-yes]]
Mode: render (default)
Output format:
WORK HQ โ <date>
โ
NEEDS YOUR INPUT (<n>)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ENG-191942 merge-conflict โ rebase PR #70 onto main (CONFLICTING)
ENG-191692 judgment-call โ review @samyak's naming comment
ENG-184901 group-3-design โ decide index naming convention
TODAY (<n>) โ bucket == today
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
1. P0 ENG-191517 in-review vscode#105712 [agent-builder]
2. P0 ENG-191692 todo wipdp [agent-builder]
3. P1 ENG-185432 in-progress vscode [-]
BACKLOG (<n>) โ bucket == backlog
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
P0 ENG-193205 new wipdp [source-integration-polish]
P1 ENG-184567 todo vscode [-]
MEETINGS โ needs summary (<n>) โ auto-recorder; omit this block if none pending
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
2026-06-01-tm-india-retro 30m [meet 2026-06-01-tm-india-retro]
PICK
[N] start task#N [next] start โ
[plan] re-plan day [list] table view
[ingest <text>] consume dump [add ENG-N today|backlog]
[meet <slug>] summarize meeting
โ
= highest-priority item with needs_input set in frontmatter. If none, โ
goes to the first in-progress ticket in TODAY.
Mode: list (table)
Compact table for scanning:
WORK HQ โ <date>
ORDER PRI TICKET STAGE REPO PR INITIATIVE
โโโโโ โโโ โโโโโโโโโโโ โโโโโโโโโโโโโ โโโโโโโ โโโโโโโโ โโโโโโโโโโโโโโ
[T1] P0 ENG-191517 in-review vscode #105712 agent-builder
[T2] P0 ENG-191692 todo wipdp - agent-builder
[T3] P1 ENG-185432 in-progress vscode - -
โโโโโ โโโ โโโโโโโโโโโ โโโโโโโโโโโโโ โโโโโโโ โโโโโโโโ โโโโโโโโโโโโโโ
[B1] P1 ENG-184567 todo vscode - - (backlog)
NEEDS YOUR INPUT
ENG-191942 merge-conflict โ rebase PR #70 onto main (CONFLICTING)
T# = today position, B# = backlog position. Add --include-archived to also walk progress/archive/ for full history.
Mode: plan
Interactive scope-setting โ sets each ticket's bucket. (You can also just drag cards between Backlog and the working lanes in Obsidian; the next /today readback folds it in.) Steps:
- List todo-ish tickets (
state โ {new, planning, todo, in-progress, in-review, ci, testing, ready-to-merge}), grouped by currentbucket. - Ask which to pull into today vs push to backlog. Accept a free-form list: "Today: ENG-191517, ENG-191692. Backlog: ENG-184567."
- Apply by editing each ticket's
bucket:frontmatter field directly (small inline Edit โ no CLI helper). - Run
python3 ~/.claude/skills/today/scripts/kanban.py render, then render the dashboard.
Also clears needs_input blocks from progress.md frontmatter for any items the user marks resolved during planning (small inline edit).
Mode: next
- Compute โ
(highest-priority ticket with
needs_inputblock; if none, first in-progress withbucket == today; if none, first todo withbucket == today). - Surface: "Starting <TICKET_ID>: [state=]. Routing via /ship-task."
cdto the right repo if needed (based on the ticket'sprojectfrontmatter field).git checkoutthe branch if it exists (frombranchfrontmatter).- Invoke
Skill(skill="ship-task", args="<TICKET_ID>"). (ship-task arms/trackas its step 4.6 โ operational tracking goes live for the picked ticket automatically.)
Mode: ingest
Consume meeting notes, discussion summaries, brain dumps. Steps:
- Extract:
- Candidate tickets (action items, "we should do X") โ propose
/create-jira-ticket-with-referencefor each, infer initiative if discussion is about an existing one. The skill writes the new ticket'sprogress.mddirectly to vault. - Decisions ("we agreed to use Y") โ append to the relevant initiative section in
~/opensource/vault/wiki/projects/<repo>/learnings.md(find/create## Initiative: <slug>section). Skip if no clear initiative โ surface to the user instead. - Learnings ("we discovered Z") โ same destination as decisions.
- Candidate tickets (action items, "we should do X") โ propose
- Show extracted items in a table; ask the user to confirm/edit each before creating tickets.
- After ticket creation, ask where each new one fits โ today or backlog (delegates to plan mode for placement). New tickets default to backlog.
Note on inbox: the legacy
vault/wiki/inbox/and~/.claude/work_hq/inbox/paths have been retired in v0. Dumps land directly into vault learnings.md initiative sections + new ticket progress files. No separate inbox queue.
Mode: retro
Read ~/.claude/skills/today/retro.md for full instructions (lazy-loaded โ only when /today retro is invoked).
Mode: oncall
Read ~/.claude/skills/today/oncall.md for full instructions (lazy-loaded โ only when /today oncall โฆ is invoked). Drives the TM/Career Hub primary on-call rotation: live PagerDuty incidents (service P0IHZZS, schedule PBWVBGY), due-date-ordered triage tickets, daily follow-ups, the incident-diagnosis DB playbook, and the per-sprint tracking sheet. Sub-args: page <id> (run diagnosis, never auto-ack), triage <TICKET> (thin alias for /rca <TICKET> โ RCA discipline lives in the standalone /rca skill; adds the TM on call PR label if /ship-task is taken), sheet (log statuses). When aws is unauthed, surface the AWS console link instead of failing.
Meeting transcripts (auto-recorder integration)
The headless meetily-rec recorder (calendar-armed via launchd; see
~/opensource/meetily/frontend/src-tauri/headless/README.md) drops one transcript per meeting at
~/opensource/vault/raw/meetings/<date>-<slug>/transcript.md (+ metadata.json). /today is where you
turn those raw transcripts into summaries + action items on demand โ the recorder captures &
transcribes locally; Claude does the thinking.
Scan (cheap โ run during render, after Step 8): a transcript with no summary.md is pending:
for d in ~/opensource/vault/raw/meetings/*/; do
[ -f "$d/transcript.md" ] && [ ! -f "$d/summary.md" ] && echo "PENDING $(basename "$d")"
done
Show pending ones in the render's MEETINGS block (duration from metadata.json) and add
[meet <slug>] to PICK. If none pending, omit the block entirely.
Mode: meetings
List raw/meetings/*/ (newest first): summary status (โ summarized / โ pending), date, duration, and
the [meet <slug>] action. Read-only.
Mode: meeting <slug | latest>
- Resolve
latest= newestraw/meetings/*/dir. Read itstranscript.md+metadata.json. - Summarize โ don't paraphrase; extract:
- TL;DR (2โ3 sentences)
- Key points (the discussion)
- Action items (owner + task where stated)
- Decisions ("we agreed to โฆ") Note: transcripts have no speaker labels yet โ attribute only where the words make it clear.
- Write
raw/meetings/<slug>/summary.md(frontmatter:meeting,date,source: today-summary) and surface it inline. Writingsummary.mdis what clears it from the pending list. - Offer to route items (ask first, same confirm-first rule as ingest): action items โ candidate
tickets via
/create-jira-ticket-with-reference; decisions/learnings โ the relevant initiative'slearnings.md. This hands off to ingest mode with the summary as the dump.
Reactive integration (other skills push to /today via vault writes)
/today does not poll โ other skills write directly to vault progress.md files:
| Skill | Effect on /today |
|---|---|
/create-jira-ticket-with-reference |
Creates progress/<ticket>/progress.md with needs_input: {reason: new-ticket-priority, action: place in today/backlog plan} so plan mode prompts placement |
/brain-ingest <ticket> |
Updates progress.md frontmatter (state, pr, pr_state, session_ids, last-touched). On merge: archives the ticket dir โ /today no longer surfaces it. |
/ship-task (loop self-terminate) |
Updates progress.md frontmatter needs_input with stop reason; surfaces in โ
|
/work-on-jira-task (start) |
sets state=in-progress (via brain-ingest at session end if user fires it) |
/submit-pr |
sets state=in-review, pr=N (via brain-ingest at session end) |
/get-pr-ready-to-merge |
updates state, pr_state (via brain-ingest at session end) |
| Merged externally | next /today invocation auto-detects via gh refresh in step 3 |
Storage layout (v0.4 โ work_hq retired)
<claude-obsidian>/.raw/work/ โ single source of truth for tickets (the /track store)
โโโ vscode/
โ โโโ ENG-XXXXX/
โ โโโ progress.md # frontmatter = board entry; body = task narrative (/track writes)
โ โโโ plan.md # 4-part plan (/track / /work-on-jira-task / /think)
โโโ wipdp/ ENG-YYYYY/{progress.md, plan.md} (same shape; also magnetx/, claude-code/, โฆ)
โโโ archive/<project>/<ticket>/{progress.md, plan.md}
โโโ Tasks.md # Obsidian Kanban projection (kanban.py)
~/.claude/scripts/progress_fm.py โ CLI helper for progress.md frontmatter + section mutations
~/.claude/skills/today/scripts/kanban.py โ Obsidian Kanban sync (readback / render)
~/.claude/skills/get-pr-ready-to-merge/scripts/fetch_ci_log.sh โ CI log fetcher (used by /get-pr-ready-to-merge)
For ticket frontmatter mutations (state, bucket, needs_input, etc.), use progress_fm.py set <TICKET> --field โฆ / progress_fm.py bucket set <TICKET> --to today / progress_fm.py needs-input add|clear. bucket: today|backlog controls Today vs Backlog placement.
kanban.py cheatsheet:
python3 ~/.claude/skills/today/scripts/kanban.py readback # fold Obsidian drags -> vault frontmatter (run at /today start)
python3 ~/.claude/skills/today/scripts/kanban.py render # vault -> Tasks.md (run at /today end)
python3 ~/.claude/skills/today/scripts/kanban.py sync # readback then render
Workflow ending
โโโโโ /today โโโโโ
mode : <render|list|plan|next|ingest>
needs_input: <n>
today : <n> tasks (or: <ticket-id> started via /ship-task)
backlog : <n> tasks
โโโโโโโโโโโโโโโโโโโโ
โโโโโ artifacts โโโโโ
Store : <claude-obsidian>/.raw/work/*/*/progress.md
Board : <claude-obsidian>/.raw/work/Tasks.md (Obsidian Kanban)
โโโโโโโโโโโโโโโโโโโโโ
Data Contract
Reads
<claude-obsidian>/.raw/work/*/*/progress.mdโ all active tickets (frontmatter is the board entry); read via~/.claude/scripts/progress_fm.py listor inline awk<claude-obsidian>/.raw/work/Tasks.mdโ the Obsidian Kanban board; read back at /today start viakanban.py(drags fold intobucket/state)- (Optional,
--include-archived):<claude-obsidian>/.raw/work/archive/*/*/progress.md ~/opensource/vault/raw/meetings/*/{transcript.md, metadata.json, summary.md}โ meetily-rec output + auto-summaries (transcript withoutsummary.md= pending for the meetily source agent)~/.claude/skills/today/state/sources/<source>.jsonโ six per-source cursor files for the BRIEFING block (Step 9)~/.claude/skills/today/sources/<source>.mdโ six source-agent spec files (passed as subagent prompts in Step 9)
Writes
vault/wiki/projects/<repo>/progress/<ticket>/progress.mdโ frontmatter via~/.claude/scripts/progress_fm.py(see shared progress policy); body is brain-ingest's responsibility<claude-obsidian>/.raw/work/Tasks.mdโ regenerated at /today end viakanban.py render~/opensource/vault/wiki/projects/<repo>/learnings.mdโ on/today ingestwhen initiative is known (append to "Initiative: " section as decisions/learnings)~/opensource/vault/raw/meetings/<slug>/summary.mdโ auto-written by the meetily source agent in Step 9 OR on/today meeting <slug>(the on-demand path; presence clears it from pending)~/.claude/skills/today/state/sources/<source>.jsonโ cursor advance written after successful BRIEFING render (Step 9)
Local (skill-only)
~/.claude/skills/today/scripts/kanban.py+.kanban_state.jsonโ Obsidian sync (moved from~/.claude/work_hq/in v0.4)- render templates, color codes (skill folder, not data)
Live external (not stored)
ghPR data โ fetched in parallel for stage transitions- Atlassian MCP โ for stale Jira ticket refresh
- Source agents (Step 9) fetch live data per their specs; the main thread never persists message bodies, just the cursor + BRIEFING render
Deprecated reads (do NOT use)
~/.claude/work_hq/**โ DELETED in v0.4. Per-ticket state is in vault progress.md (read via progress_fm.py); operational state for /today is understate/sources/.~/opensource/vault/wiki/hot.mdโ archived; do not read or write~/opensource/vault/wiki/log.mdโ archived; do not write~/opensource/vault/wiki/projects/<repo>/initiatives/<slug>/{decisions,learnings}.mdโ absorbed intolearnings.md"## Initiative: " sections; the legacy paths are in_archive/