Skip to content

vt-d-statusline-spec-phase

Spec/phase-aware statusline for Claude Code — renders the active SPEC-NNN, its workflow phase, context usage and session cost on one line, degrading to a generic display when no spec is active. Use this when you steer several worktrees at once and want to see at a glance which spec and phase the current session is on. The toolkit ships the script only; you opt in from your own ~/.claude/settings.json.

Plugin: vt-product-dev
Category: Other
Command: /vt-d-statusline-spec-phase


Statusline: spec + phase

Renders one line for the session you are in:

SPEC-167 · planned · 61% ctx · $4.70

and, when no spec can be resolved — on main, outside a worktree, or in a repo with no specs/ directory — the generic form, with no invented id:

Opus 5 · my-project

Opting in

The toolkit does not install this for you, by design. It ships the script and nothing else. Add the entry to your own ~/.claude/settings.json:

"statusLine": {
  "type": "command",
  "command": "~/.claude/skills/vt-d-statusline-spec-phase/scripts/statusline.sh"
}

Remove that block to opt out. Nothing else changes; the toolkit never wrote it and never updates it.

What you are agreeing to. A statusLine command executes on every assistant message, as you, with no permission prompt and no hook inspection — it is not a Bash tool call. The path above is a symlink into the toolkit checkout, and the script sources its sibling spec-phase.sh with no integrity check. So enabling this means treating that checkout as trusted code: anyone who can write there — a merged PR, or an agent running with edits auto-approved — gets per-message execution as you. That is inherent to statusLine, not specific to this script, but it is worth knowing before you paste. Point it at your primary checkout, never a feature worktree: a removed worktree leaves a dead symlink and every render fails.

Why it is not shipped

Two independent reasons, either of which would be sufficient:

  1. SEC-4 removed the shipped statusLine key from configs/user-global/settings.json on the grounds that a statusline is personal preference, not a toolkit standard — colleagues should not inherit a display they never chose. See configs/security/SECURITY-CONFIG.md, "Retired exception (SEC-4)", which prescribes exactly the personal-config route above.
  2. It would not work anyway for the people most likely to want it. scripts/lib/merge_settings.py is marker-based and user-wins: a top-level key you already own is preserved verbatim. Anyone who had already set their own statusLine would never receive the toolkit's, and the opt-in would fail silently for them.

The same section of SECURITY-CONFIG.md also requires pinning any third-party statusline to an exact version. That constraint does not apply here — this script has no third-party dependency at all, runs no package runner, and makes no network call.

What it renders

Segment Source
SPEC-NNN .active-spec if present, else parsed from the payload's worktree.branch (AD-1)
phase the spec's committed state.yaml (AD-2) — see the table below
NN% ctx context_window.used_percentage from the payload
$N.NN cost.total_cost_usd from the payload

Phase labels

Phase comes from the committed state.yaml, never from gate-file presence: .review-gate.md and .test-gate.md are gitignored and none exist under specs/, so a gate-file reading would report "not built" for every spec ever built.

state.yaml says Label
status: completed done
status: rejected / parked rejected / parked
finalize_gate: reached finalize
review_gate: reached review
build_gate: reached build
plan_gate: reached planned
shape_gate: reached shaped
status: in_progress, no gate active
anything else spec

A terminal status outranks every gate, and a gate whose own status is PENDING is a placeholder rather than a gate reached — both learned from real spec data, where a rejected spec carrying four PENDING placeholders would otherwise have displayed as nearly finished.

Phases 0 (0-start) and 1 (1-bootstrap) are project-level, not spec-level. No per-spec artifact records them, so they are not derivable and are not rendered.

Behaviour and limits

  • One line, ANSI colour, no OSC-8 hyperlinks. Honours NO_COLOR.
  • Never fails a prompt. Malformed, empty or unexpected input degrades to the generic line and exits 0.
  • Single session only. It shows the session it runs in. Claude Code exposes no cross-session registry, so a multi-worktree view is not possible from a statusline — that was investigated and dropped (SPEC-167, FR-4). For a cross-task view use /vt-p-domain-dashboard, or git worktree list.
  • Hot path. Measured at ~87 ms per render against Claude Code's 300 ms debounce, almost entirely interpreter startup. It makes exactly one python3 call and never shells out to git — the branch arrives in the payload. Both constraints are enforced by tests/spec-167/test_statusline.bats, not merely documented here.

Scripts

Script Role
scripts/statusline.sh entrypoint — reads the payload on stdin, renders the line
scripts/spec-phase.sh sourceable helper — spec_phase <dir> and spec_id_from_branch <branch>

spec-phase.sh is usable on its own:

Both paths below are relative to the repo root — mixing roots is why an earlier version of this example ran from nowhere:

bash plugins/vt-product-dev/skills/statusline-spec-phase/scripts/spec-phase.sh \
  specs/167-parallel-multitask-working-model   # -> planned

Next actions

After reading this skill, the useful next steps are:

  • Enable it — paste the statusLine block above into your own ~/.claude/settings.json, then start a new Claude Code session. The line appears on the first render; there is nothing to restart or reload beyond the session itself. Deploy ~/.claude from the primary checkout rather than from a worktree, or removing that worktree dead-links the script and every render fails.
  • Check what it derives for any spec without enabling anything, by calling the helper directly: bash scripts/spec-phase.sh specs/167-parallel-multitask-working-model prints one phase label.
  • Read the parallel-work guardrails if the reason you want this is steering several worktrees at once — docs/solutions/patterns/v025-multi-worktree-workflow.md covers the procedure, the 4–6 ceiling, and the four hazards this repo has already paid for.
  • Use /vt-p-domain-dashboard instead if what you actually need is a view across several specs or projects. This skill is single-session by design and cannot see other worktrees.
  • Disable it by deleting the statusLine block from your own settings. The toolkit never wrote it and never updates it, so nothing else has to be undone.
  • docs/solutions/patterns/v025-multi-worktree-workflow.md — running several worktrees, and the hazards that come with it
  • configs/security/SECURITY-CONFIG.md — the SEC-4 retired exception this skill honours