SKILL.md
Linearis CLI Reference
Verified against Linearis v2026.4.9 (2026-05-31). ⚠️ READ vs WRITE. Linear READS → the local replica by direct SQL, or
linearreadticket <ID>. Never shelllinearis issues readfor a routine read — it 429s the shared fleet quota. WRITES →linearis. Read [Gotchas](#gotchas--traps) before scripting.
Reading Linear
Single source of the Linear read rule — other skills point here, they don't restate it.
- Cloud detection, every session — reuse the existing helpers, never write new ones:
``bash source "${CLAUDEPLUGINROOT:?}/scripts/lib/linear-read-replica.sh" replicafresh; rf=$? # 0 = writer heartbeat <5min AND seeded source "${CLAUDEPLUGINROOT:?}/scripts/lib/plugin-dirs.sh" marker="$(plugindirsrepoconfig_path)" # "" if no .catalyst/config.json found ` Either failing → no cloud mirror: say so loudly (never silent) and fall back to direct linearis/API reads — the non-fleet path (protects the 2500/hr quota), wrong to recommend on the fleet. Same pattern: steward's references/cloud-detection.md`.
- Cloud mode confirmed → query the replica and TRUST it. Don't re-verify against live Linear.
- Row missing / not fresh → an ALARM, not a silent reroute. Loud fallback, file a ticket.
The only reads you should shell directly are through the helper — it is the freshness gate, not a convenience wrapper. Never run a bare sqlite3 query against the replica yourself: it skips the $rf/$marker checks above and can return stale data (or an empty DB) with no fallback.
json=$(linear_read_ticket ENG-123) || return 1 # freshness-gate → SQL → loud fallback, ONE call
title=$(printf '%s' "$json" | jq -r '.title // empty')
Raw SQL syntax (only after the helper's gate already ran), schema discovery, apply-drift caveat, deprecated wrapper: [references/reading-linear-detail.md](references/reading-linear-detail.md).
Core Operations
Reads → direct SQL via the gated helper above; writes always linearis — run linearis usage / linearis <domain> usage for authoritative, current flag syntax. linearreadticket covers a single ticket only — a scope-wide list/search still goes through linearis (no bulk-query replica form yet; see [Reading Linear](references/reading-linear-detail.md#still-needs-linearis)).
linearis issues search "auth bug" --team ENG --status "Todo"
linearis issues update ENG-123 --status "In Progress" --labels "bug" --label-mode add
⛔ Agent comments →
linear-reply.mjs, neverissues discuss/reply— those post AS THE HUMAN (personal token; ask-resolution gate reads that as the human deciding, CTL-1567).
direnv exec . node "$CLAUDE_PLUGIN_ROOT/scripts/linear-reply.mjs" ENG-123 --as <AGENT> --body-file <path> --top
# --body-file <path> for anything longer than a one-line body; --body REFUSES a path (CTL-2204)
issues discussions <id> (read-only) is safe. Full CRUD, comment-thread commands, common mistakes, other domains: [references/core-operations.md](references/core-operations.md).
Workflow: Status Transitions
Single source of the Linear
stateMaptable —linear,create-plan,implement-plan,create-pr,research-codebasepoint here; none restates it.
| Workflow Phase | Default State | Config Key |
|---|---|---|
| New tickets | Backlog | stateMap.backlog |
| Acknowledged | Todo | stateMap.todo |
| Research / Planning started | In Progress | stateMap.research / .planning |
| Implementation | In Progress | stateMap.inProgress |
| Verify / Review phase | In Progress | stateMap.verifying / .reviewing |
| PR created | In Review | stateMap.inReview |
| Completed / Canceled | Done / Canceled | stateMap.done / .canceled |
Names come from .catalyst/config.json's linear.stateMap (null skips a transition). UUID calls + the team-key allowlist cache (linear-team-keys.json): [references/status-transitions.md](references/status-transitions.md).
Gotchas & Traps
issues listhides Done (shows Canceled) —--status "Done", orissues read <ID>for one.linearisconsumes stdin in a loop — append</dev/null.- No
--jsonflag — JSON is the default; pipe tojq. --statusis server-side and fails empty on a typo — not an error; also deprecated--query(useissues search).--status/--cyclerequire--team;--milestonerequires--project; names collide across projects/teams.project-milestonesfails silently to the help dump — the domain ismilestones.status/stateare zsh read-only vars (st/s/lstate);auth statusis the diagnostic entry point when calls return nothing.
Cookbook, one topic per file: grooming/triage/stale sweeps — [references/backlog-grooming.md](references/backlog-grooming.md); milestone create/rename/audit — [references/milestones.md](references/milestones.md); labels + the cross-team same-name trap — [references/labels.md](references/labels.md); cycle review — [references/cycles.md](references/cycles.md).