/speckit.linear.status
Summary
Per-spec drift inspector — disk vs Linear, every spec in the consumer
repo, never mutates Linear.
Inspect, do not mutate. For each specs/NNN-feature/ in the consumer
repo, surface the disk-side facts, the Linear-side facts, the drift
between them, and the write-authority / drift posture for that spec.
(Under Constitution Principle IV v2.0.0 — drift-aware, spec 003 — the
relevant signal is backward-drift, not the legacy FR-025 branch-gate;
see the Authority status field below.)
Direction: read-only. Talks to Linear ONLY via graphql::query;
issues zero issueCreate / issueUpdate / commentCreate / any other
mutation. Even from an authoritative worktree, this command MUST NOT
write — it is an inspect tool, full stop.
Authority: not gated. Runs from any worktree, on any branch
(detached HEAD included). Reports the per-spec drift posture so the
operator knows whether a subsequent /speckit.linear.push from the
current worktree would write cleanly or hit a backward-drift warning
(Principle IV v2.0.0 / spec 003). Current Linear state is always
surfaced (FR-026 / FR-060).
Layer: out-of-band inspect command, not part of Layer D's write
cycle. Safe to run during a deploy, during a CI build, during a merge.
The deterministic work happens in src/status.sh; this command is the
AI-agent entry point that runs the shell and surfaces its output. The
formal API contract is contracts/command-shapes.md (speckit.linear.status
slice). Operators reading this file are looking at the markdown the AI
agent reads — the same operations are available via
bash src/status.sh directly. For the operator-facing end-to-end
walkthrough see
quickstart.md.
Usage
| Argument |
Default |
Meaning |
spec |
(none — implies --all) |
Feature number (e.g. 003). Inspect only this spec. |
json |
false |
Emit a machine-readable JSON array on stdout, one object per spec. Default is the coloured human table. |
no-color |
false |
Force monochrome output. Also honoured via the NO_COLOR env variable. |
Exactly one of spec or "all specs" is in effect. When spec is not
passed, the report walks every specs/NNN-*/ directory in the consumer
repo. json and no-color are orthogonal to spec.
CLI shape
speckit.linear.status [--spec NNN | --all] [--json | --human] [--no-color]
Default: --all --human.
Algorithm (what the AI agent executes)
Verify prerequisites. Refuse to proceed if any of these fail.
- Bash 4 or newer is on
PATH. macOS ships bash 3.2 by default; the
operator must brew install bash and ensure
/opt/homebrew/bin/bash (Apple Silicon) or /usr/local/bin/bash
(Intel) is earlier on PATH than /bin/bash.
- The consumer repo's config is present at
.specify/extensions/linear/linear-config.yml. If absent,
surface "run /spec-kit-linear-install first" and exit 2; do NOT
attempt to run the inspector.
jq, curl, and git are installed.
Compose the invocation. Translate the user-facing arguments
into src/status.sh flags:
spec=NNN → --spec NNN
- no
spec → --all
json=true → --json
no-color=true → --no-color
Execute the inspector. Shell out:
bash src/status.sh <flags>
The script:
- Loads + validates
linear-config.yml (src/config.sh). Halts
with exit 2 on missing / malformed UUIDs (FR-022).
- Enumerates the requested specs in numeric order.
- For each spec, gathers:
- Disk-side facts — feature number, short name, lifecycle
phase (per
parser::lifecycle_phase), current branch (per
git_helpers::current_branch), worktree(s) hosting that
branch (per git_helpers::list_worktrees), last-touched
timestamp (per git_helpers::last_touched), task-phase
completion ratio computed from tasks.md checklists.
- Linear-side facts — spec Issue's workflow state,
phase:*
label, sub-issue completion counts, last activity timestamp.
Queried via graphql::query using the speckit-spec:NNN label
scoped to the configured Project UUID (FR-004b).
- Drift signals — bullet list of mismatches: lifecycle phase
differs, branch differs from the memory block, last-touched is
older than Linear's last activity (FR-026 "Linear knows
something disk doesn't"), task checklist count differs.
- Drift status — the backward-drift posture per Principle IV
v2.0.0 (spec 003): reports whether writing this spec from the
current worktree would be a clean forward write or trigger a
backward-drift warning (Linear ahead of disk). This is a
NON-GATING display hint — the FR-025 branch-gate is removed
(FR-051); reconcile writes from any worktree and only SURFACES
drift, never refuses (FR-060). The legacy
git_helpers::is_authoritative_for_spec flag is retained ONLY as
an informational "is this the canonical feature-branch worktree?"
cue, never a write decision.
- Canonical-right-now worktree — when more than one worktree
has
specs/NNN-feature/ checked out, the report names the
worktree holding the MOST RECENT commit touching the spec dir
(per git_helpers::worktrees_touching_spec, FR-058/FR-059). The
ranking uses spec-dir git-commit time, NEVER branch name or
mtime, so the pointer agrees with the drift signal. The
single-worktree case omits this field. See
recency-comparison.md
for the recency-key contract.
- Renders the per-spec report on stdout (JSON array or human
table) and the structured summary on stderr.
Render the report. Two output shapes:
--human (default) — coloured table on stdout:
NNN NAME DISK PHASE DISK TASKS AUTH LINEAR ID LINEAR STATE DRIFT
001 multi-phase tasking 0/3 Yes ACM-12 Tasking (tasking) —
002 multi-phase tasking 0/3 No ACM-14 Implementing (impl…) lifecycle phase: disk=tasking linear=implementing
AUTH cell is green (Yes) / yellow (No). DRIFT cell is green
(—) / red (any signal). Honours NO_COLOR and --no-color.
--json — JSON array on stdout, one object per spec:
[
{
"feature_number": "002",
"short_name": "multi-phase",
"disk": {
"lifecycle_phase": "tasking",
"current_branch": "002-multi-phase",
"worktree": "/path/to/wt",
"worktree_count": 1,
"last_touched": "2026-05-28T12:00:00Z",
"task_phase_completion": "0/3"
},
"authority": "Yes",
"linear": {
"present": true,
"fetch_failed": false,
"identifier": "ACM-12",
"title": "002-multi-phase",
"state_name": "Tasking",
"state_type": "started",
"phase_label": "tasking",
"sub_issue_completion": "0/3",
"last_activity": "2026-05-28T11:50:00Z"
},
"drift": []
}
]
Handle the exit code.
0 — success (possibly with warnings). The report is authoritative.
1 — partial failure. At least one spec's Linear-side fetch
failed; the disk-side row still appears with linear.fetch_failed: true.
Recommend re-running once network connectivity is restored.
2 — workspace config error (missing/malformed linear-config.yml).
The script halted before any query. Surface the remediation the
script printed (typically: run /spec-kit-linear-install).
3 — transport failure. Linear was unreachable; the disk-side
report still emits, but every Linear cell is empty.
When this command fires
- Operator-driven —
/speckit.linear.status from the AI agent
chat. Primary path for "what's the state of this repo?" inspections,
multi-repo coordination, and pre-push drift checks.
- Never auto-fired. This is NOT wired into any
after_* hook or
any git hook by /spec-kit-linear-install — running it on every
lifecycle command would add latency to every spec edit without
changing observable state. Operator-invoked only.
Output channel discipline
stdout carries the per-spec report (JSON array or human table).
This is the contract: pipe it to jq or column confidently.
stderr carries:
- per-step log lines (the spec being inspected, the Linear query
being issued)
- the final structured
summary::emit block (always)
- No filesystem writes (Principle I). No Linear writes (Principle I +
FR-026). The inspector reads disk + Linear and prints; everything
else is operator action.
Failure surface
Each failure mode is surfaced as a named warning in the summary
(Principle VIII):
spec NNN: spec.md missing or empty; phase unknown — partial
inspection continues; the spec appears with disk.lifecycle_phase: "unknown".
spec NNN: Linear query failed; surfacing disk-side facts only —
per-spec transport blip. The disk-side row still appears with
linear.fetch_failed: true. Exit code promotes to 1.
no spec directory matched --spec NNN — operator typo; report empty.
no specs/NNN-*/ directories found — repo has no specs yet; report
empty with this warning so the operator knows the empty output is
intentional rather than a bug.
Related commands
/speckit.linear.push — write path. Reconciles filesystem state
into Linear. Use /speckit.linear.status first to see what WOULD
change.
/speckit.linear.pull — read-only inspect of Linear's current
view (no disk-side comparison).
/speckit.linear.seed — one-shot workspace setup. Run once per
Linear workspace before the first push.
/speckit.linear.install — per-repo install ceremony. Run once
per consumer repo before the first push.
See contracts/command-shapes.md for the formal contract on each
and
quickstart.md
for the end-to-end operator walkthrough.
FRs surfaced
This command implements (in whole or in part):
- FR-022 — config-load halt with operator-actionable remediation.
- FR-023 — structured
summary::emit block on stderr.
- FR-025 — per-spec write-authority status surfaced in the report (the v1.0.0 branch-gate is SUPERSEDED by Constitution Principle IV v2.0.0 / spec 003 drift-aware signal, FR-051..FR-060).
- FR-026 / FR-060 — read-only inspection; current Linear state and drift surfaced without any write attempt.
- FR-058 / FR-059 — the canonical-right-now worktree pointer (most-recent spec-dir commit across worktrees, ranked by git-commit time) surfaced when >1 worktree touches the spec.
- FR-004b —
speckit-spec:NNN label is the lookup key for the Linear-side fetch.
1---2name: speckit-linear-status3description: Per-spec drift report — disk vs Linear (READ-ONLY; never mutates Linear)4---56# `/speckit.linear.status`78## Summary910Per-spec drift inspector — disk vs Linear, every spec in the consumer11repo, never mutates Linear.1213Inspect, do not mutate. For each `specs/NNN-feature/` in the consumer14repo, surface the disk-side facts, the Linear-side facts, the drift15between them, and the write-authority / drift posture for that spec.16(Under Constitution Principle IV v2.0.0 — drift-aware, spec 003 — the17relevant signal is backward-drift, not the legacy FR-025 branch-gate;18see the Authority status field below.)1920**Direction**: read-only. Talks to Linear ONLY via `graphql::query`;21issues zero `issueCreate` / `issueUpdate` / `commentCreate` / any other22mutation. Even from an authoritative worktree, this command MUST NOT23write — it is an inspect tool, full stop.24**Authority**: not gated. Runs from any worktree, on any branch25(detached HEAD included). Reports the per-spec drift posture so the26operator knows whether a subsequent `/speckit.linear.push` from the27current worktree would write cleanly or hit a backward-drift warning28(Principle IV v2.0.0 / spec 003). Current Linear state is always29surfaced (FR-026 / FR-060).30**Layer**: out-of-band inspect command, not part of Layer D's write31cycle. Safe to run during a deploy, during a CI build, during a merge.3233The deterministic work happens in `src/status.sh`; this command is the34AI-agent entry point that runs the shell and surfaces its output. The35formal API contract is `contracts/command-shapes.md` (`speckit.linear.status`36slice). Operators reading this file are looking at the markdown the AI37agent reads — the same operations are available via38`bash src/status.sh` directly. For the operator-facing end-to-end39walkthrough see40[`quickstart.md`](../specs/001-spec-kit-linear-bridge/quickstart.md).4142## Usage4344| Argument | Default | Meaning |45|---|---|---|46| `spec` | (none — implies `--all`) | Feature number (e.g. `003`). Inspect only this spec. |47| `json` | false | Emit a machine-readable JSON array on stdout, one object per spec. Default is the coloured human table. |48| `no-color` | false | Force monochrome output. Also honoured via the `NO_COLOR` env variable. |4950Exactly one of `spec` or "all specs" is in effect. When `spec` is not51passed, the report walks every `specs/NNN-*/` directory in the consumer52repo. `json` and `no-color` are orthogonal to `spec`.5354### CLI shape5556```text57speckit.linear.status [--spec NNN | --all] [--json | --human] [--no-color]58```5960Default: `--all --human`.6162## Algorithm (what the AI agent executes)63641. **Verify prerequisites.** Refuse to proceed if any of these fail.65 - Bash 4 or newer is on `PATH`. macOS ships bash 3.2 by default; the66 operator must `brew install bash` and ensure67 `/opt/homebrew/bin/bash` (Apple Silicon) or `/usr/local/bin/bash`68 (Intel) is earlier on `PATH` than `/bin/bash`.69 - The consumer repo's config is present at70 `.specify/extensions/linear/linear-config.yml`. If absent,71 surface "run `/spec-kit-linear-install` first" and exit 2; do NOT72 attempt to run the inspector.73 - `jq`, `curl`, and `git` are installed.74752. **Compose the invocation.** Translate the user-facing arguments76 into `src/status.sh` flags:77 - `spec=NNN` → `--spec NNN`78 - no `spec` → `--all`79 - `json=true` → `--json`80 - `no-color=true` → `--no-color`81823. **Execute the inspector.** Shell out:8384 ```bash85 bash src/status.sh <flags>86 ```8788 The script:89 - Loads + validates `linear-config.yml` (`src/config.sh`). Halts90 with exit 2 on missing / malformed UUIDs (FR-022).91 - Enumerates the requested specs in numeric order.92 - For each spec, gathers:93 - **Disk-side facts** — feature number, short name, lifecycle94 phase (per `parser::lifecycle_phase`), current branch (per95 `git_helpers::current_branch`), worktree(s) hosting that96 branch (per `git_helpers::list_worktrees`), last-touched97 timestamp (per `git_helpers::last_touched`), task-phase98 completion ratio computed from `tasks.md` checklists.99 - **Linear-side facts** — spec Issue's workflow state, `phase:*`100 label, sub-issue completion counts, last activity timestamp.101 Queried via `graphql::query` using the `speckit-spec:NNN` label102 scoped to the configured Project UUID (FR-004b).103 - **Drift signals** — bullet list of mismatches: lifecycle phase104 differs, branch differs from the memory block, last-touched is105 older than Linear's last activity (FR-026 "Linear knows106 something disk doesn't"), task checklist count differs.107 - **Drift status** — the backward-drift posture per Principle IV108 v2.0.0 (spec 003): reports whether writing this spec from the109 current worktree would be a clean forward write or trigger a110 backward-drift warning (Linear ahead of disk). This is a111 NON-GATING display hint — the FR-025 branch-gate is removed112 (FR-051); reconcile writes from any worktree and only SURFACES113 drift, never refuses (FR-060). The legacy114 `git_helpers::is_authoritative_for_spec` flag is retained ONLY as115 an informational "is this the canonical feature-branch worktree?"116 cue, never a write decision.117 - **Canonical-right-now worktree** — when more than one worktree118 has `specs/NNN-feature/` checked out, the report names the119 worktree holding the MOST RECENT commit touching the spec dir120 (per `git_helpers::worktrees_touching_spec`, FR-058/FR-059). The121 ranking uses spec-dir git-commit time, NEVER branch name or122 mtime, so the pointer agrees with the drift signal. The123 single-worktree case omits this field. See124 [`recency-comparison.md`](../specs/003-drift-aware-authority/contracts/recency-comparison.md)125 for the recency-key contract.126 - Renders the per-spec report on stdout (JSON array or human127 table) and the structured summary on stderr.1281294. **Render the report.** Two output shapes:130131 - `--human` (default) — coloured table on stdout:132133 ```text134 NNN NAME DISK PHASE DISK TASKS AUTH LINEAR ID LINEAR STATE DRIFT135 001 multi-phase tasking 0/3 Yes ACM-12 Tasking (tasking) —136 002 multi-phase tasking 0/3 No ACM-14 Implementing (impl…) lifecycle phase: disk=tasking linear=implementing137 ```138139 `AUTH` cell is green (Yes) / yellow (No). `DRIFT` cell is green140 (`—`) / red (any signal). Honours `NO_COLOR` and `--no-color`.141142 - `--json` — JSON array on stdout, one object per spec:143144 ```json145 [146 {147 "feature_number": "002",148 "short_name": "multi-phase",149 "disk": {150 "lifecycle_phase": "tasking",151 "current_branch": "002-multi-phase",152 "worktree": "/path/to/wt",153 "worktree_count": 1,154 "last_touched": "2026-05-28T12:00:00Z",155 "task_phase_completion": "0/3"156 },157 "authority": "Yes",158 "linear": {159 "present": true,160 "fetch_failed": false,161 "identifier": "ACM-12",162 "title": "002-multi-phase",163 "state_name": "Tasking",164 "state_type": "started",165 "phase_label": "tasking",166 "sub_issue_completion": "0/3",167 "last_activity": "2026-05-28T11:50:00Z"168 },169 "drift": []170 }171 ]172 ```1731745. **Handle the exit code.**175 - `0` — success (possibly with warnings). The report is authoritative.176 - `1` — partial failure. At least one spec's Linear-side fetch177 failed; the disk-side row still appears with `linear.fetch_failed: true`.178 Recommend re-running once network connectivity is restored.179 - `2` — workspace config error (missing/malformed `linear-config.yml`).180 The script halted before any query. Surface the remediation the181 script printed (typically: run `/spec-kit-linear-install`).182 - `3` — transport failure. Linear was unreachable; the disk-side183 report still emits, but every Linear cell is empty.184185## When this command fires186187- **Operator-driven** — `/speckit.linear.status` from the AI agent188 chat. Primary path for "what's the state of this repo?" inspections,189 multi-repo coordination, and pre-push drift checks.190- **Never auto-fired.** This is NOT wired into any `after_*` hook or191 any git hook by `/spec-kit-linear-install` — running it on every192 lifecycle command would add latency to every spec edit without193 changing observable state. Operator-invoked only.194195## Output channel discipline196197- `stdout` carries the per-spec report (JSON array or human table).198 This is the contract: pipe it to `jq` or `column` confidently.199- `stderr` carries:200 - per-step log lines (the spec being inspected, the Linear query201 being issued)202 - the final structured `summary::emit` block (always)203- No filesystem writes (Principle I). No Linear writes (Principle I +204 FR-026). The inspector reads disk + Linear and prints; everything205 else is operator action.206207## Failure surface208209Each failure mode is surfaced as a named warning in the summary210(Principle VIII):211212- `spec NNN: spec.md missing or empty; phase unknown` — partial213 inspection continues; the spec appears with `disk.lifecycle_phase: "unknown"`.214- `spec NNN: Linear query failed; surfacing disk-side facts only` —215 per-spec transport blip. The disk-side row still appears with216 `linear.fetch_failed: true`. Exit code promotes to 1.217- `no spec directory matched --spec NNN` — operator typo; report empty.218- `no specs/NNN-*/ directories found` — repo has no specs yet; report219 empty with this warning so the operator knows the empty output is220 intentional rather than a bug.221222## Related commands223224- `/speckit.linear.push` — write path. Reconciles filesystem state225 into Linear. Use `/speckit.linear.status` first to see what WOULD226 change.227- `/speckit.linear.pull` — read-only inspect of Linear's current228 view (no disk-side comparison).229- `/speckit.linear.seed` — one-shot workspace setup. Run once per230 Linear workspace before the first push.231- `/speckit.linear.install` — per-repo install ceremony. Run once232 per consumer repo before the first push.233234See `contracts/command-shapes.md` for the formal contract on each235and236[`quickstart.md`](../specs/001-spec-kit-linear-bridge/quickstart.md)237for the end-to-end operator walkthrough.238239## FRs surfaced240241This command implements (in whole or in part):242243- **FR-022** — config-load halt with operator-actionable remediation.244- **FR-023** — structured `summary::emit` block on stderr.245- **FR-025** — per-spec write-authority status surfaced in the report (the v1.0.0 branch-gate is SUPERSEDED by Constitution Principle IV v2.0.0 / spec 003 drift-aware signal, FR-051..FR-060).246- **FR-026 / FR-060** — read-only inspection; current Linear state and drift surfaced without any write attempt.247- **FR-058 / FR-059** — the canonical-right-now worktree pointer (most-recent spec-dir commit across worktrees, ranked by git-commit time) surfaced when >1 worktree touches the spec.248- **FR-004b** — `speckit-spec:NNN` label is the lookup key for the Linear-side fetch.