linear-sdk-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +20 -0
- package/.claude-plugin/plugin.json +9 -0
- package/CHANGELOG.md +807 -0
- package/COVERAGE.md +495 -0
- package/LICENSE +21 -0
- package/MIGRATING.md +220 -0
- package/README.md +524 -0
- package/package.json +87 -0
- package/skills/linear-sdk-cli/SKILL.md +534 -0
- package/skills/linear-sdk-cli/references/api.md +27 -0
- package/skills/linear-sdk-cli/references/attachment.md +82 -0
- package/skills/linear-sdk-cli/references/auth.md +174 -0
- package/skills/linear-sdk-cli/references/commands.md +37 -0
- package/skills/linear-sdk-cli/references/comment.md +154 -0
- package/skills/linear-sdk-cli/references/completion.md +17 -0
- package/skills/linear-sdk-cli/references/config.md +99 -0
- package/skills/linear-sdk-cli/references/cycle.md +131 -0
- package/skills/linear-sdk-cli/references/document.md +180 -0
- package/skills/linear-sdk-cli/references/favorite.md +78 -0
- package/skills/linear-sdk-cli/references/initiative-update.md +67 -0
- package/skills/linear-sdk-cli/references/initiative.md +256 -0
- package/skills/linear-sdk-cli/references/issue.md +928 -0
- package/skills/linear-sdk-cli/references/label.md +112 -0
- package/skills/linear-sdk-cli/references/milestone.md +139 -0
- package/skills/linear-sdk-cli/references/notification.md +123 -0
- package/skills/linear-sdk-cli/references/open.md +29 -0
- package/skills/linear-sdk-cli/references/organization.md +99 -0
- package/skills/linear-sdk-cli/references/project-update.md +67 -0
- package/skills/linear-sdk-cli/references/project.md +234 -0
- package/skills/linear-sdk-cli/references/roadmap.md +150 -0
- package/skills/linear-sdk-cli/references/schema.md +21 -0
- package/skills/linear-sdk-cli/references/state.md +61 -0
- package/skills/linear-sdk-cli/references/team.md +227 -0
- package/skills/linear-sdk-cli/references/user.md +103 -0
- package/skills/linear-sdk-cli/references/webhook.md +151 -0
- package/skills/linear-sdk-cli/references/whoami.md +26 -0
- package/skills/linear-sdk-cli/scripts/generate-docs.ts +339 -0
- package/src/bin/linear.ts +97 -0
- package/src/cli.ts +232 -0
- package/src/client.ts +172 -0
- package/src/commands/agent-session.ts +121 -0
- package/src/commands/api.ts +317 -0
- package/src/commands/attach.ts +90 -0
- package/src/commands/attachment.ts +74 -0
- package/src/commands/comment.ts +225 -0
- package/src/commands/completion.ts +69 -0
- package/src/commands/cycle.ts +125 -0
- package/src/commands/discover.ts +170 -0
- package/src/commands/document.ts +211 -0
- package/src/commands/favorite.ts +72 -0
- package/src/commands/initiative-update.ts +47 -0
- package/src/commands/initiative.ts +261 -0
- package/src/commands/issue.ts +1263 -0
- package/src/commands/label.ts +119 -0
- package/src/commands/meta.ts +534 -0
- package/src/commands/milestone.ts +163 -0
- package/src/commands/notification.ts +110 -0
- package/src/commands/open.ts +84 -0
- package/src/commands/organization.ts +79 -0
- package/src/commands/project-update.ts +47 -0
- package/src/commands/project.ts +339 -0
- package/src/commands/roadmap.ts +131 -0
- package/src/commands/state.ts +58 -0
- package/src/commands/team.ts +243 -0
- package/src/commands/user.ts +107 -0
- package/src/commands/webhook.ts +156 -0
- package/src/config.ts +1236 -0
- package/src/context.ts +117 -0
- package/src/git.ts +174 -0
- package/src/index.ts +10 -0
- package/src/lib/action.ts +26 -0
- package/src/lib/body.ts +172 -0
- package/src/lib/errors.ts +195 -0
- package/src/lib/introspect.ts +150 -0
- package/src/lib/keyring.ts +270 -0
- package/src/lib/mutation.ts +53 -0
- package/src/lib/open.ts +32 -0
- package/src/lib/options.ts +640 -0
- package/src/lib/output-shapes.ts +562 -0
- package/src/lib/pagination.ts +145 -0
- package/src/lib/prompt.ts +91 -0
- package/src/lib/resolve.ts +596 -0
- package/src/lib/shape.ts +273 -0
- package/src/lib/status-update.ts +91 -0
- package/src/lib/upload.ts +329 -0
- package/src/output/color.ts +52 -0
- package/src/output/format.ts +238 -0
- package/src/output/markdown.ts +133 -0
- package/src/output/pager.ts +131 -0
- package/src/output/sanitize.ts +76 -0
- package/src/output/table.ts +198 -0
- package/src/services/agent-session.ts +289 -0
- package/src/services/attachment.ts +198 -0
- package/src/services/comment.ts +262 -0
- package/src/services/cycle.ts +224 -0
- package/src/services/document.ts +357 -0
- package/src/services/favorite.ts +147 -0
- package/src/services/initiative-update.ts +59 -0
- package/src/services/initiative.ts +449 -0
- package/src/services/issue.ts +1153 -0
- package/src/services/label.ts +193 -0
- package/src/services/milestone.ts +262 -0
- package/src/services/notification.ts +190 -0
- package/src/services/organization.ts +144 -0
- package/src/services/project-update.ts +36 -0
- package/src/services/project.ts +494 -0
- package/src/services/roadmap.ts +177 -0
- package/src/services/state.ts +127 -0
- package/src/services/team.ts +386 -0
- package/src/services/user.ts +137 -0
- package/src/services/webhook.ts +203 -0
package/MIGRATING.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Migrating from `schpet/linear-cli`
|
|
2
|
+
|
|
3
|
+
_Verified against **schpet/linear-cli v2.5.0** (`5af8286`, 2026-08-11) — the Deno original, not a
|
|
4
|
+
fork. If you are on the `@zhendalf/linear-cli` Bun port, everything here applies too; that fork
|
|
5
|
+
tracks the original._
|
|
6
|
+
|
|
7
|
+
The short version: **install, run `linear auth status`, keep typing what you typed.** Your
|
|
8
|
+
credentials are found where schpet left them, your `.linear.toml` is read from the same places, and
|
|
9
|
+
schpet's spellings are accepted as aliases. Where the two CLIs genuinely differ, the difference is
|
|
10
|
+
loud — a usage error, never a quietly different result.
|
|
11
|
+
|
|
12
|
+
## 1. Install (and the `linear` name)
|
|
13
|
+
|
|
14
|
+
Both CLIs install a binary called `linear`. If schpet's is on your `PATH`, ours will shadow it — or
|
|
15
|
+
be shadowed — depending on order; `linear --version` says which you got (`0.x` ours, `2.x` theirs)
|
|
16
|
+
and `which -a linear` lists both. We keep the `linear` name on purpose: it is what every doc,
|
|
17
|
+
script and agent skill types, and there is no second name that both projects would agree on. Two
|
|
18
|
+
things make it safe anyway:
|
|
19
|
+
|
|
20
|
+
- We also install **`lin`**, a shorter alias that cannot collide with anything of theirs. If you
|
|
21
|
+
want zero risk of running the wrong tool, use `lin` for the first week — every command in this
|
|
22
|
+
guide works with `lin` in place of `linear`.
|
|
23
|
+
- To keep theirs reachable during the transition, rename it to `linear-schpet` the way it was
|
|
24
|
+
installed, and let ours have `linear`:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
deno install -A --reload -f -g -n linear-schpet jsr:@schpet/linear-cli && deno uninstall -g linear # deno
|
|
28
|
+
brew unlink schpet/tap/linear && ln -s "$(brew --prefix)/opt/linear/bin/linear" ~/.local/bin/linear-schpet # homebrew
|
|
29
|
+
mv "$(command -v linear)" "$(dirname "$(command -v linear)")/linear-schpet" # npm/bun -g
|
|
30
|
+
# Until the first npm release: clone and run from source (see README).
|
|
31
|
+
linear --version # ours: 0.x
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
A project-pinned `@schpet/linear-cli` (`bunx linear` inside that repo) never collides with a
|
|
35
|
+
global install of ours.
|
|
36
|
+
|
|
37
|
+
## 2. Credentials — nothing to re-enter
|
|
38
|
+
|
|
39
|
+
schpet 2.5 stores your API key in the **system keyring** (macOS Keychain or Linux `secret-tool`;
|
|
40
|
+
service `linear-cli`, account = workspace slug) and keeps the workspace list in
|
|
41
|
+
`~/.config/linear/credentials.toml`. We use the same keyring service and account, and we read that
|
|
42
|
+
list file for slugs and its `default` (never for keys), so:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
linear auth status # Authenticated: true, Source: keychain, Workspace: <your slug>
|
|
46
|
+
linear auth list # …lists it, Storage: keychain
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If it does not — no keyring on this platform, or you used schpet's plaintext mode (`slug =
|
|
50
|
+
"lin_api_…"` inline in `credentials.toml`, which we deliberately do not read) — `linear auth login`
|
|
51
|
+
prompts (masked) and stores the key in the keyring; `--plaintext` keeps it in our `0600`
|
|
52
|
+
`config.toml` instead. `auth migrate` moves plaintext credentials from that file into the keyring,
|
|
53
|
+
same command name as theirs. Because the keyring entry is shared, `auth logout` here removes it for
|
|
54
|
+
schpet too (and drops the slug from its list file, so neither tool reports a workspace whose key is
|
|
55
|
+
gone). The API key is **never** read from a project `.linear.toml`.
|
|
56
|
+
|
|
57
|
+
## 3. Config — same files, same keys
|
|
58
|
+
|
|
59
|
+
We look in every place schpet does, in its order. Walking up from the working directory, each
|
|
60
|
+
directory is checked for `linear.toml`, then `.linear.toml`, then `.config/linear.toml` (schpet
|
|
61
|
+
checks cwd and the git root; we check every directory between, which agrees with it wherever it
|
|
62
|
+
would find something). Below that, our `~/.config/linear/config.toml`, then schpet's global
|
|
63
|
+
`~/.config/linear/linear.toml` — read for `team_id`, `workspace`, `issue_sort`; **not** for
|
|
64
|
+
`api_key`, which schpet allows there and we never take from any file but our own. `linear config`
|
|
65
|
+
prints each value with the file it came from, so nothing is a mystery:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
Team: TES (project: /repo/.config/linear.toml)
|
|
69
|
+
Sort: priority (global: /Users/you/.config/linear/linear.toml)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Two key differences to know: `issue_sort = "manual"` (schpet's board order) has no equivalent here
|
|
73
|
+
and is a usage error naming the file — change it to `priority` or drop the line. The `vcs` setting
|
|
74
|
+
is ignored; this CLI supports Git and does not claim partial jj support. Schpet's
|
|
75
|
+
`issue_create_*`, `download_images`, `hyperlink_format`, `attachment_dir` keys are ignored (no
|
|
76
|
+
such features yet). `linear config init` writes a `.linear.toml`; `linear config set <key>
|
|
77
|
+
<value>` edits one key.
|
|
78
|
+
|
|
79
|
+
## 4. Commands — same words, or an alias
|
|
80
|
+
|
|
81
|
+
| schpet | here | notes |
|
|
82
|
+
| -------------------------------------------------------------------------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
83
|
+
| `issue list` | **`issue mine`** | ⚠️ their `list` is an alias of `mine` (you, unstarted). Our `list` is the whole team. See §6. |
|
|
84
|
+
| `issue query` | `issue list` | alias, same command |
|
|
85
|
+
| `issue mine` | `issue mine` | same defaults: yours, unstarted; `--all-states` widens |
|
|
86
|
+
| `issue comment add\|list\|update\|delete` | same, or top-level `comment …` | one implementation |
|
|
87
|
+
| `issue comment <id> "<body>"` | same | |
|
|
88
|
+
| `issue attach <file>` | `issue attach <issue> <file...>` | same posture: private by default, `--public` for raster images only; ours takes several files and has `--json` |
|
|
89
|
+
| `issue link <url>` | `attachment create --url` | |
|
|
90
|
+
| `issue comment add --attach <file>` | same, or `comment add --attach` | repeatable; images render inline |
|
|
91
|
+
| `auth whoami` | `whoami` (also `auth whoami`) | |
|
|
92
|
+
| `auth migrate` | `auth migrate` | |
|
|
93
|
+
| `config` (writes toml) | `config init` / `config set` | |
|
|
94
|
+
| `team states` / `team members` / `user list` | same | `--all` there means "inactive too"; here it is pagination — use `--include-disabled` (see §6) |
|
|
95
|
+
| `issue start` | same | moves the issue to the first `started` state, as there; `--no-move` to only branch |
|
|
96
|
+
| `issue describe` | same | byte-identical output: `ID Title`, then `Linear-issue:` / `Linear-issue-url:` trailers |
|
|
97
|
+
| `issue pull-request` | same | title `ID Title` as there; body is the two `Linear-issue` trailers (theirs: the URL alone) — the issue description is not copied into GitHub |
|
|
98
|
+
| `project create -t A -t B` | same, or `--teams A,B` | collects both, as there (see §6) |
|
|
99
|
+
| `document create\|list\|update --project\|--issue\|--initiative\|--team\|--cycle\|--release` | same | `update` re-points, as there; `--team` is the global flag (with `--cycle` it scopes the lookup) |
|
|
100
|
+
| `initiative add-project` / `remove-project` / `unarchive` | same | |
|
|
101
|
+
| `project delete` / `team delete` | same, confirmation-gated | |
|
|
102
|
+
| `schema` / `api` | same | ours adds `--operation`, `--vars-file`, and refuses to `--paginate` a mutation |
|
|
103
|
+
|
|
104
|
+
Everything with no row is spelled identically.
|
|
105
|
+
|
|
106
|
+
## 5. Flags — theirs are accepted
|
|
107
|
+
|
|
108
|
+
| schpet | here (canonical) | where |
|
|
109
|
+
| --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | ---------------------------------------------------------------------- |
|
|
110
|
+
| `-j, --json` | same | every command |
|
|
111
|
+
| `-w, --web` | same | every `view` |
|
|
112
|
+
| `--due-date` | `--due` | issue create/update |
|
|
113
|
+
| `--target-date`, `--start-date` | `--target`, `--start` | project / milestone / initiative |
|
|
114
|
+
| `--search` | `--query` | issue list / mine |
|
|
115
|
+
| `--status` | `--state` | project list |
|
|
116
|
+
| `--limit 0` | `--all` | every list |
|
|
117
|
+
| `--assignee self` | `me` / `@me` | anywhere |
|
|
118
|
+
| `--cycle active` | `current` | anywhere; `now`/`next`/`previous`/`+1` also work |
|
|
119
|
+
| `-U/--unassigned`, `--created-after`, `--updated-after`, `--project-label`, `--milestone`, `--search-comments`, repeatable `--team`/`--state` | same | issue queries |
|
|
120
|
+
| `--add-label`, `--remove-label`, `--unassign`, `--clear-cycle` | same | issue update |
|
|
121
|
+
| `--no-use-default-template` | `--no-default-template` | issue create — the team default is applied unless you say so, as there |
|
|
122
|
+
| `--start`, `--parent` (child joins the parent's project) | same | issue create |
|
|
123
|
+
|
|
124
|
+
Passing both spellings at once (`--due` _and_ `--due-date`) is a usage error, not a coin flip.
|
|
125
|
+
|
|
126
|
+
**Short flags are the one place we did not follow.** schpet 2.5's own tree assigns `-a` four
|
|
127
|
+
meanings (`--app`, `--all`, `--assignee`, `--attach`), `-f` four, `-y` three, `-t` two (`--title`
|
|
128
|
+
and `--team`). There is no consistent target to copy. Ours holds **one meaning per letter across
|
|
129
|
+
all 141 commands**, so `-t` is always `--team`, `-p` always `--project`, `-P` always `--priority`,
|
|
130
|
+
`-f` always `--fields`, `-n` always `--limit`. Every collision fails loudly — `-p 2` says "No
|
|
131
|
+
project matching '2'", not "set priority 2" — and the two that _used_ not to are loud now: `-f`
|
|
132
|
+
and `-n` are refused on any command that prints no table (`project create -f desc.md` says
|
|
133
|
+
"--fields does not apply … use --description-file <path>"; `project create -n 'My Project'` says
|
|
134
|
+
"--limit does not apply … the name is --name"), instead of creating the project without either.
|
|
135
|
+
|
|
136
|
+
## 6. What would silently differ — and how we made it loud (or the same)
|
|
137
|
+
|
|
138
|
+
These are the spots where the same command line could _succeed on both and mean different things_.
|
|
139
|
+
Every one is now either identical, or says so on stderr, or is a usage error. Know them.
|
|
140
|
+
|
|
141
|
+
1. **`issue list`** — theirs shows _your unstarted_ issues; ours shows the _team's_ issues.
|
|
142
|
+
We did not alias `list` to `mine`: a command named "list" that hides your colleagues' work and
|
|
143
|
+
your own in-progress work is the sharpest transition hazard there is. Type `issue mine` for the
|
|
144
|
+
old behavior.
|
|
145
|
+
2. **Repeated `--label`** narrows (AND) in both CLIs now — same as schpet.
|
|
146
|
+
3. **`--sort priority`** groups by workflow state in both — but we sort state **ascending** so active
|
|
147
|
+
work is on top. schpet hardcodes descending, which the API answers with Backlog _above_ In
|
|
148
|
+
Progress; a Low-priority backlog item outranks an Urgent in-progress one there. We diverge on
|
|
149
|
+
purpose.
|
|
150
|
+
4. **`user list --all` / `team members --all`** — theirs: include _inactive_ members. Ours: `--all`
|
|
151
|
+
is the global "fetch every page" on all 141 commands, and deactivated users are
|
|
152
|
+
`--include-disabled`. We kept the one meaning; the command prints a warning on stderr (even
|
|
153
|
+
under `--quiet`) that deactivated users are still excluded and names `--include-disabled`, and
|
|
154
|
+
`--help` says so up front. Not adopted: making `--all` mean "and deactivated" on two commands
|
|
155
|
+
would give one global two meanings.
|
|
156
|
+
5. **`-f <file>` on `project create/update`, `document create/update`** — theirs: `--description-file` /
|
|
157
|
+
`--content-file`. Ours: `-f` is `--fields`, and it used to be _dropped_ on those commands, so
|
|
158
|
+
`project create --name X -f desc.md` created the project with no description and exited 0.
|
|
159
|
+
`--fields`, `--limit` and `--all` are now usage errors on every command that prints no table or
|
|
160
|
+
detail block, and the message names `--description-file` / `--content-file` where they exist.
|
|
161
|
+
Not adopted: a local `-f = --description-file` on four commands would be one letter meaning two
|
|
162
|
+
things (§5), and would still be `--fields` in `--help`.
|
|
163
|
+
6. **`project create --team A --team B`** — theirs collects both; ours took the last one and created
|
|
164
|
+
the project in B alone. `--team` on `project create` is now the same repeatable list as
|
|
165
|
+
`--teams`; both spellings at once is a usage error. (`project update --team` stays refused,
|
|
166
|
+
pointing at `--teams`, because that list _replaces_ the project's teams.)
|
|
167
|
+
7. **`issue start`** — theirs always moves the issue to the first `started` state after branching;
|
|
168
|
+
ours only did with `--move`, so the transplanted command left the issue in Backlog without a
|
|
169
|
+
word. Adopted: moving is the default (that is what "start" means, and what an agent that says
|
|
170
|
+
"start" expects), `--no-move` opts out, `--move` is still accepted. Both the checkout and the
|
|
171
|
+
state change are reported.
|
|
172
|
+
8. **`issue describe`** — theirs prints `ID Title`, a blank line, then `Linear-issue: Fixes ID` and
|
|
173
|
+
`Linear-issue-url: URL`; ours printed `Title` and a bare `Fixes ID`. Piped into `git commit -m`
|
|
174
|
+
that was a different commit. Adopted, byte for byte: proper trailers are what `git
|
|
175
|
+
interpret-trailers` and jj read back, and Linear reads the magic word right before the id
|
|
176
|
+
either way (linear.app/docs/github). `-r/--references` still swaps in `References`.
|
|
177
|
+
9. **`issue pull-request`** — theirs titles the PR `ID Title` and sends the issue URL as the body;
|
|
178
|
+
ours titled it `Title` and pasted the issue _description_ into the body. Title adopted (a custom
|
|
179
|
+
`--title` is prefixed too). Body: the same two trailers `describe` prints — the URL as there,
|
|
180
|
+
plus the magic word so the link (and auto-close) does not depend on the branch name — and the
|
|
181
|
+
description stays in Linear rather than in a GitHub PR body.
|
|
182
|
+
10. **`issue list`/`mine`/`search`, `project list` with no team configured** — theirs error
|
|
183
|
+
("No default team…"); ours list the whole workspace, on purpose (`--all-teams` explicitly). So a
|
|
184
|
+
migrating user cannot mistake that for a team's list, the command prints one stderr note ("No
|
|
185
|
+
default team configured; listing every team's…"); `--quiet` silences it.
|
|
186
|
+
11. **`--cycle +1`** — active cycle plus one on both (it was cycle _#1_ here once).
|
|
187
|
+
12. **`document list --team X`** — filters to the team's documents on both.
|
|
188
|
+
|
|
189
|
+
Loud already, listed so you are not surprised:
|
|
190
|
+
|
|
191
|
+
| you type (schpet habit) | here | what happens |
|
|
192
|
+
| ------------------------------------------------------------ | ------------------------------------------ | --------------------------------------------------------------------------------------------- |
|
|
193
|
+
| `issue update TES-1 -t 'New title'` (`-t` = `--title` there) | `--title` | `-t` is `--team`: "No team matching 'New title'", exit 3 — unless a team is really named that |
|
|
194
|
+
| `project create -n 'My Project'` (`-n` = `--name` there) | `--name` | `-n` is `--limit`: refused on `create`, and the message says so |
|
|
195
|
+
| `issue comment delete <id>` in a script | same, `--yes` | destructive actions off-TTY need `--yes` (exit 2), there it just deletes |
|
|
196
|
+
| `--assignee <partial name>` (fuzzy there) | `me`, an email, an exact display/full name | "No user matching", exit 3 |
|
|
197
|
+
| `issue view 123` (bare number, team from config there) | `TES-123` | rejected, exit 2 |
|
|
198
|
+
| `linear config` (writes a toml there) | prints; `config init` / `config set` write | |
|
|
199
|
+
| `project update <p> -t A` (replaces the teams there) | `--teams A` | `--team` refused with the reason; `--teams` replaces, as there |
|
|
200
|
+
| `--all` on `user list` | see 4 above | pagination + a warning |
|
|
201
|
+
|
|
202
|
+
## 7. Deliberate non-features
|
|
203
|
+
|
|
204
|
+
`issue commits`, `team autolinks`, and jj support are not curated commands. Bulk archive/delete
|
|
205
|
+
supports `--bulk`, `--bulk-file`, and `--bulk-stdin`; Markdown rendering and paging are built in.
|
|
206
|
+
Each is tracked; the raw `linear api` reaches all of the API surface in the meantime. If you type
|
|
207
|
+
one of these out of habit, the CLI says where the equivalent lives rather than just rejecting it:
|
|
208
|
+
`linear issue link x` answers "Use 'linear attachment create <issue> --url <url>'", and `issue
|
|
209
|
+
commits` points at `git log`. (`issue attach` is here as of TES-602 — see §4.)
|
|
210
|
+
|
|
211
|
+
## 8. What you gain
|
|
212
|
+
|
|
213
|
+
- **One JSON shape everywhere.** Lists are a bare array, single results a bare object, errors
|
|
214
|
+
`{"error":{"message","code"}}` on stderr with distinct exit codes (0–6). schpet wraps in
|
|
215
|
+
`{nodes,pageInfo}` and several of its commands have no `--json` at all.
|
|
216
|
+
- **Discovery for agents:** `linear commands --json` (full command tree) and `linear schema`.
|
|
217
|
+
- **Broader surface:** notifications, webhooks, favorites, organization, cycle create/update,
|
|
218
|
+
comment resolve/reply, label hierarchy, `issue archive/unarchive`, `issue subscribe`.
|
|
219
|
+
- **Every mutation checks `success`**; every resolver scans past the first page and names the
|
|
220
|
+
candidates on a miss; `--json` implies non-interactive; a declined confirmation exits 6.
|