Linear (linear-cli)
Linear is driven by nesszer linear-cli (Rust; binary linear-cli, installed to ~/.cargo/bin, which is not on a
non-interactive PATH). This file indexes the non-obvious parts; for everything else use linear-cli <cmd> --help,
linear-cli common, or linear-cli agent. Auth: linear-cli auth oauth (browser) or LINEAR_API_KEY; check with
linear-cli auth status. The issue lifecycle itself is automated by the skills (/start, /spec, /finish, …).
Start here
~/.claude/scripts/linear-context.sh PL-13 # description, parent chain, deps, standalone AND anchored comments
~/.claude/scripts/linear-deps-graph.sh PL-13 | --team PL # dependency graph as {nodes, edges}
linear-cli issues get PL-13 -o json --no-cache # the bare issue object (.identifier, .state.name, .labels.nodes[])
Body text (a comment, a description) goes through linear-post.sh / linear-stdin.sh from a tmp/ file, never
through <, cat | or a heredoc — standards/linear-workflow.md § Passing File
Content to Linear CLI owns that. Filing an issue follows standards/linear-filing.md;
label meanings are standards/issue-spec.md; terminal states and claims are
linear-workflow.md.
Gotchas
Numbers are stable — other skills cite them. The line is the reminder; the named file is the rule.
- Anchored (inline) comments are invisible to
comments listandissues get; read the digest →references/comments.md - No dependency commands or flags — graph via
linear-deps-graph.sh, filter with jq →references/relations.md issues createhas no--parent—parentIdin--data, orlinear-create-child.sh, which verifies the link →references/create.md- Unassign =
issues assign <ID>with the user omitted →references/states.md - Workflow states =
statuses list -t <TEAM>; provisioning is/linear-setup, never hand-rolled →references/states.md api query/api mutatereturn the raw envelope — jq paths start.data.; a wrong path'slengthis0at exit 0 →references/json.md- Labels are typed (
-t issue), can be team-scoped, and-lREPLACES — add withlinear-add-label.sh→references/labels.md issues updatecan report success without writing — useissues assign,linear-set-state.sh,linear-claim.sh; read back--no-cache→references/states.mdcomments listneeds-o json(the table is empty) and the body path is.comments.nodes[].body→references/comments.md-r blocked-by400s — alwaysrelations add <BLOCKER> <BLOCKED> -r blocks→references/relations.mdArgument Validation Error= a mangled identifier reached the API, usually zsh not word-splitting$var→references/paging.mdpriority:0(none) ranks LAST, and dedicated commands have nopriorityLabel— print a label, neverP<n>→references/json.md- Result shape varies by command —
search issues/issues listare a bare array,issues geta bare object,relations listhas no.nodes→references/json.md search issuesmatches a contiguous phrase — single tokens only, the file basename first; a multi-word miss exits 0 →references/create.mdrelations add A B -r duplicatecloses A (stateDuplicate); re-adding the right way restores it to Backlog →references/relations.md- Checked task boxes read back as
- [X]— match case-insensitively →references/create.md - A label write is verified through its consumer, not
issues get(reads flap); exit 2 = unconfirmed; one write per issue at a time →references/labels.md comments create -b -posts a literal-— uselinear-post.sh commentorissues comment --body -→references/comments.md- Rows carry
stateas{name}only — filter terminal states by name, never.state.type→references/states.md - An issue id in a body stays plain text — emit the issue URL, or better a
relatedrelation →references/comments.md issues create: title is positional,-lonce per label, ALWAYS--state(the default lands in Triage) →references/create.mdgrep blocksonrelations listdropsblocked byrows — read the table whole →references/relations.mdstatuses listis cached — pass--no-cachein every state resolution →references/states.md- In auto mode a write inside shell control flow is classifier-denied — one Linear write per Bash call →
references/paging.md issues listreturns 50 rows by default,--count-onlyincluded — pass--allon pool-sized reads →references/paging.md- A rate-limited answer is on STDERR with empty stdout — never
2>/dev/null; grep forRATELIMITEDand wait →references/paging.md
Command map
linear-cli issues get <ID> [-o json] [--no-cache] # --comments adds STANDALONE comments only (#1)
linear-cli issues list --team <KEY> [--all | --limit N] [--state X] [--assignee me] [-l <label>] [-o json] # 50 rows by default (#25)
linear-cli issues create "<title>" --team <KEY> --state X [-l <label>]... [-d -] # title positional, -l repeated, -d - reads stdin (#21)
linear-cli issues update <ID> [--state X] [--priority N] [-l <label>]... [--data -] # -l SETS the whole set (#7); verify writes (#8)
linear-cli issues assign <ID> [me|<user>] # omit the user to unassign (#4)
linear-cli issues comment <ID> --body - # comment body via stdin (#18)
linear-cli comments list <ID> -o json # standalone only (#1); -o json required (#9)
linear-cli relations list <ID> [-o json] # .relations[] AND .inverseRelations[] (#13, #22)
linear-cli relations add <BLOCKER> <BLOCKED> -r blocks|related|duplicate # the first argument is the subject (#10, #15)
linear-cli relations remove <RELATION-UUID> # the relation id from relations list -o json, not issue keys
linear-cli relations parent <CHILD> <PARENT> # set a parent after create (#3)
linear-cli search issues "<token>" [-o json] # workspace-wide, no --team; contiguous match (#14)
linear-cli statuses list -t <KEY> --no-cache # (#5, #23)
linear-cli labels list -t issue [-o json] # -t is the label TYPE (#7)
linear-cli labels create "<name>" -t issue [-c <hex>] # workspace-level only (#7)
linear-cli labels delete <LABEL-UUID> -t issue -f # takes the label id, not the name
linear-cli api query '<graphql>' | jq '.data…' # escape hatch (#6)
linear-cli uploads fetch "<uploads.linear.app URL>" -f <file> # authenticated download
Output flags: -o json|ndjson, -q, --id-only, --compact, --fields <a,b> (an unknown field is dropped silently).
Helper scripts
All under ~/.claude/scripts/. Each header carries the usage line, exit codes and contract; read it before calling.
| Script | Does |
|---|---|
| linear-context.sh | Markdown digest of an issue including anchored comments (#1). |
| linear-deps-graph.sh | Dependency graph as {nodes, edges} for one issue or a whole team (#2). |
| linear-create-child.sh | Create, link the parent, verify the link; refuses Planned and an unrouted label slot without the leading flags (#3, #21). |
| linear-post.sh | Post a comment or replace a description from a file (#18). |
| linear-stdin.sh | Pipe a file to any linear-cli command's stdin flag. |
| linear-add-label.sh | Add one label without clobbering the rest; heals near-miss names, never mints (#7, #17). |
| linear-remove-label.sh | Remove one label, preserving the rest (#7, #17). |
| linear-set-state.sh | Verified state transition for one or many issues: update → --no-cache read-back → raw-mutation fallback (#8). |
| linear-claim.sh | Assignee-and-state claim with a verdict on the first stdout line (CLAIMED / NOT-CLAIMED / UNCONFIRMED) (#8). |
| linear-file-improvement.sh | File a /reflect improvement issue (specified+reflection, or reflection+keeper uncertified). |
| mark-ready-for-release.sh | Move to Ready For Release and unassign, verified; then closes an epic parent whose every child is terminal (#8). |
| epic-graph.sh | An epic's working set as JSON — members, blockers, terminal nodes, edges, and the boundary report. |
References
- references/comments.md — read before reading or writing comments or any body text (#1, #9, #18, #20)
- references/relations.md — read before reading or writing dependencies, duplicates or parents (#2, #10, #15, #22)
- references/labels.md — read before any label read or write (#7, #17)
- references/states.md — read before writing a state or assignee, or filtering on state (#4, #5, #8, #19, #23)
- references/create.md — read before
issues create, a dedup search, or a description rewrite (#3, #14, #16, #21) - references/paging.md — read before a pool-sized read or a loop, and when a call returns nothing (#11, #24, #25, #26)
- references/json.md — read before writing a
jqfilter over any linear-cli output (#6, #12, #13)