linmux 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.
Files changed (118) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +240 -0
  3. package/bin/run.js +4 -0
  4. package/dist/commands/comment/create.js +94 -0
  5. package/dist/commands/comment/delete.js +74 -0
  6. package/dist/commands/comment/list.js +84 -0
  7. package/dist/commands/comment/update.js +80 -0
  8. package/dist/commands/cycle/current.js +78 -0
  9. package/dist/commands/cycle/list.js +84 -0
  10. package/dist/commands/cycle/move.js +91 -0
  11. package/dist/commands/describe.js +65 -0
  12. package/dist/commands/graphql/index.js +92 -0
  13. package/dist/commands/install-skill.js +54 -0
  14. package/dist/commands/issue/archive.js +75 -0
  15. package/dist/commands/issue/create.js +115 -0
  16. package/dist/commands/issue/get.js +84 -0
  17. package/dist/commands/issue/list.js +93 -0
  18. package/dist/commands/issue/purge.js +81 -0
  19. package/dist/commands/issue/search.js +109 -0
  20. package/dist/commands/issue/transition.js +91 -0
  21. package/dist/commands/issue/trash.js +75 -0
  22. package/dist/commands/issue/update.js +126 -0
  23. package/dist/commands/label/create.js +91 -0
  24. package/dist/commands/label/list.js +76 -0
  25. package/dist/commands/list-tools.js +47 -0
  26. package/dist/commands/me.js +71 -0
  27. package/dist/commands/project/create.js +101 -0
  28. package/dist/commands/project/get.js +83 -0
  29. package/dist/commands/project/list.js +75 -0
  30. package/dist/commands/project/update-status.js +99 -0
  31. package/dist/commands/project/update.js +99 -0
  32. package/dist/commands/raw/batch.js +85 -0
  33. package/dist/commands/raw/index.js +72 -0
  34. package/dist/commands/schema.js +69 -0
  35. package/dist/commands/state/list.js +77 -0
  36. package/dist/commands/team/get.js +73 -0
  37. package/dist/commands/team/list.js +73 -0
  38. package/dist/commands/whoami.js +71 -0
  39. package/dist/commands/workspace/add.js +97 -0
  40. package/dist/commands/workspace/list.js +47 -0
  41. package/dist/commands/workspace/remove.js +63 -0
  42. package/dist/commands/workspace/replace-token.js +89 -0
  43. package/dist/commands/workspace/use.js +54 -0
  44. package/dist/core/client/factory.js +28 -0
  45. package/dist/core/client/index.js +2 -0
  46. package/dist/core/config/index.js +4 -0
  47. package/dist/core/config/paths.js +30 -0
  48. package/dist/core/config/schema.js +36 -0
  49. package/dist/core/config/store.js +149 -0
  50. package/dist/core/errors/error.js +142 -0
  51. package/dist/core/errors/exit-codes.js +70 -0
  52. package/dist/core/output/envelope.js +53 -0
  53. package/dist/core/output/format.js +42 -0
  54. package/dist/core/output/index.js +3 -0
  55. package/dist/core/pagination/flags.js +29 -0
  56. package/dist/core/pagination/index.js +2 -0
  57. package/dist/core/projection/presets.js +116 -0
  58. package/dist/core/projection/project.js +282 -0
  59. package/dist/core/redact/redact.js +45 -0
  60. package/dist/core/resolvers/cycle.js +60 -0
  61. package/dist/core/resolvers/index.js +7 -0
  62. package/dist/core/resolvers/label.js +54 -0
  63. package/dist/core/resolvers/project-status.js +42 -0
  64. package/dist/core/resolvers/project.js +43 -0
  65. package/dist/core/resolvers/state.js +46 -0
  66. package/dist/core/resolvers/team.js +50 -0
  67. package/dist/core/transport/fetch-interceptor.js +109 -0
  68. package/dist/core/transport/index.js +3 -0
  69. package/dist/core/transport/rate-limit.js +167 -0
  70. package/dist/core/workspace/resolver.js +70 -0
  71. package/dist/core/workspace/write-guard.js +43 -0
  72. package/dist/generated/graphql.js +89428 -0
  73. package/dist/generated/operations.js +3013 -0
  74. package/dist/lib/comment-create-runtime.js +96 -0
  75. package/dist/lib/comment-delete-runtime.js +46 -0
  76. package/dist/lib/comment-list-runtime.js +182 -0
  77. package/dist/lib/comment-update-runtime.js +93 -0
  78. package/dist/lib/cycle-current-runtime.js +90 -0
  79. package/dist/lib/cycle-list-runtime.js +151 -0
  80. package/dist/lib/cycle-move-runtime.js +142 -0
  81. package/dist/lib/describe-runtime.js +180 -0
  82. package/dist/lib/filter-heuristics.js +59 -0
  83. package/dist/lib/graphql-runtime.js +202 -0
  84. package/dist/lib/include-fragments.js +73 -0
  85. package/dist/lib/install-skill-runtime.js +228 -0
  86. package/dist/lib/introspection-registry.js +488 -0
  87. package/dist/lib/issue-archive-runtime.js +89 -0
  88. package/dist/lib/issue-create-runtime.js +175 -0
  89. package/dist/lib/issue-get-runtime.js +153 -0
  90. package/dist/lib/issue-list-runtime.js +164 -0
  91. package/dist/lib/issue-purge-runtime.js +89 -0
  92. package/dist/lib/issue-search-runtime.js +114 -0
  93. package/dist/lib/issue-transition-runtime.js +131 -0
  94. package/dist/lib/issue-trash-runtime.js +84 -0
  95. package/dist/lib/issue-update-runtime.js +164 -0
  96. package/dist/lib/label-create-runtime.js +113 -0
  97. package/dist/lib/label-list-runtime.js +97 -0
  98. package/dist/lib/levenshtein.js +42 -0
  99. package/dist/lib/list-tools-runtime.js +38 -0
  100. package/dist/lib/me-runtime.js +55 -0
  101. package/dist/lib/project-create-runtime.js +103 -0
  102. package/dist/lib/project-get-runtime.js +134 -0
  103. package/dist/lib/project-list-runtime.js +84 -0
  104. package/dist/lib/project-update-runtime.js +110 -0
  105. package/dist/lib/project-update-status-runtime.js +91 -0
  106. package/dist/lib/raw-batch-runtime.js +229 -0
  107. package/dist/lib/raw-runtime.js +171 -0
  108. package/dist/lib/schema-loader.js +41 -0
  109. package/dist/lib/schema-runtime.js +65 -0
  110. package/dist/lib/state-list-runtime.js +93 -0
  111. package/dist/lib/team-get-runtime.js +55 -0
  112. package/dist/lib/team-list-runtime.js +52 -0
  113. package/dist/lib/workspace-runtime.js +112 -0
  114. package/dist/operations/_registry.zod.js +5337 -0
  115. package/oclif.manifest.json +3631 -0
  116. package/package.json +99 -0
  117. package/schema.graphql +30772 -0
  118. package/skills/linmux/SKILL.md +186 -0
@@ -0,0 +1,186 @@
1
+ ---
2
+ name: linmux
3
+ description: Operate Linear across all your workspaces from any agent that can shell out — the full GraphQL surface (~500 ops), multiple workspaces in one session, and stable versioned JSON. Use when the user asks about Linear issues, projects, cycles, comments, teams, labels, or workflow states, or wants to query/mutate Linear via CLI — especially when more than one Linear workspace is in play.
4
+ compatibility: Requires Node 22+ and a Linear API key (LINEAR_API_KEY env var or `linmux workspace add`).
5
+ metadata:
6
+ version: "0.1.0"
7
+ homepage: "https://github.com/ChuckMayo/linear-multi-workspace-cli"
8
+ ---
9
+
10
+ # linmux
11
+
12
+ One CLI that drives **every** Linear operation across **all** your workspaces — the full GraphQL surface (~500 ops), multiple workspaces in a single session, JSON by default for agents.
13
+
14
+ Pinned version: `0.1.0`. Always invoke as `npx -y linmux@0.1.0 <command>`. Never the floating dist-tag — agents must pin so a registry update doesn't silently change the contract mid-session.
15
+
16
+ ## When to invoke
17
+
18
+ Invoke `linmux` when the user wants to read or write Linear data and you can shell out. It shines when more than one Linear workspace is in play — each command resolves its workspace independently, so a single session can touch several. Trigger phrases include:
19
+
20
+ - "create / update / archive / list / search / get an issue"
21
+ - "add a comment", "find issues in <team>", "what's in cycle <n>"
22
+ - "create / update a project", "set project status"
23
+ - "list teams / labels / workflow states / cycles"
24
+ - "who am I" / "what workspace am I in" (use `me` or `whoami`)
25
+ - Anything spanning two workspaces ("compare my open issues in acme vs personal")
26
+ - Any GraphQL query a curated command doesn't cover — fall back to the raw layer
27
+
28
+ You do NOT need to ask the user for permission to call a read-only command (`*list*`, `*get*`, `*search*`, `me`, `whoami`, `describe`, `list-tools`, `schema`). For write commands (create/update/delete/archive/trash/transition/purge), confirm intent first unless the user has clearly asked for the write.
29
+
30
+ ## Auth setup
31
+
32
+ `linmux` reads its Linear API key from one of two sources, in this order:
33
+
34
+ 1. **Per-shell env var** (preferred for CI / one-shot invocations):
35
+ ```
36
+ export LINEAR_API_KEY=lin_api_...
37
+ npx -y linmux@0.1.0 me --json
38
+ ```
39
+
40
+ 2. **Persistent workspace registry** (preferred for interactive use, supports multiple workspaces):
41
+ ```
42
+ npx -y linmux@0.1.0 workspace add acme --token lin_api_...
43
+ npx -y linmux@0.1.0 workspace add personal --token lin_api_...
44
+ npx -y linmux@0.1.0 workspace use acme
45
+ npx -y linmux@0.1.0 me --json
46
+ ```
47
+
48
+ The workspace name is a positional argument (`workspace add <name> --token ...`). Every command accepts `--workspace <name>` to target a specific registered workspace without changing the active default — that is how one session drives several workspaces:
49
+
50
+ ```
51
+ npx -y linmux@0.1.0 issue list --workspace acme --team ENG --json
52
+ npx -y linmux@0.1.0 issue list --workspace personal --team SIDE --json
53
+ ```
54
+
55
+ Tokens are stored at `$XDG_CONFIG_HOME/linear-agent/config.json`, default `~/.config/linear-agent/config.json` (the directory name predates the `linmux` rename), written with mode 0600. Personal API keys only — no OAuth in v1.
56
+
57
+ If neither source is set, every command exits with `WORKSPACE_NOT_RESOLVED` (exit 10). Run `linmux workspace list` to see what's registered.
58
+
59
+ ## JSON-by-default contract
60
+
61
+ Every command emits a versioned envelope on stdout. **Pass `--json` for machine output** — pretty/human output is on by default but agents should always use `--json`.
62
+
63
+ Success envelope (locked key order):
64
+ ```json
65
+ {
66
+ "$apiVersion": "1",
67
+ "ok": true,
68
+ "data": { /* command-specific payload */ },
69
+ "meta": { "command": "issue list", "workspace": "acme" }
70
+ }
71
+ ```
72
+
73
+ Failure envelope:
74
+ ```json
75
+ {
76
+ "$apiVersion": "1",
77
+ "ok": false,
78
+ "error": {
79
+ "code": "VALIDATION_FAILED",
80
+ "message": "Title is required",
81
+ "transient": false,
82
+ "details": { "field": "title" }
83
+ },
84
+ "meta": { "command": "issue create" }
85
+ }
86
+ ```
87
+
88
+ `ok: true` ⇒ exit 0. `ok: false` ⇒ exit > 0 (taxonomy below). The `data` payload shape is stable per command — pin tests against `data.*` paths, not human prose. The `meta.workspace` field tells you which workspace served the call — check it when working across several.
89
+
90
+ ## Curated commands quick-reference
91
+
92
+ Top-of-funnel commands (one line each). Run `npx -y linmux@0.1.0 describe <command>` for full flag schema, or `npx -y linmux@0.1.0 list-tools` for the full inventory.
93
+
94
+ | Command | Purpose |
95
+ |---------|---------|
96
+ | `me --json` | Fetch viewer + organization (auth probe). |
97
+ | `whoami --json` | Active workspace + user identity. |
98
+ | `issue list --team <slug> --json` | Page through issues in a team. |
99
+ | `issue get <id> --json` | Fetch one issue by identifier (e.g. `ENG-123`). |
100
+ | `issue search "<query>" --json` | Full-text search. |
101
+ | `issue create --team <slug> --title "..." [--description "..." --state <name> --assignee <email> --labels <l1,l2>] --json` | Create. |
102
+ | `issue update <id> [--title --description --state --assignee --labels] --json` | Patch fields. |
103
+ | `issue transition <id> --state <name> --json` | Move to a workflow state. |
104
+ | `issue archive <id> --json` / `issue trash <id> --json` / `issue purge <id> --json` | Lifecycle ops (require confirmation). |
105
+ | `comment create --issue <id> --body "..." --json` | Add a comment. |
106
+ | `comment list --issue <id> --json` | List comments on an issue. |
107
+ | `project list [--team <slug>] --json` | List projects (optionally team-scoped). |
108
+ | `project create --team <slug> --name "..." [--description ...] --json` | Create project. |
109
+ | `project update-status <id> --status <name> --json` | Update a project's status field. |
110
+ | `cycle list --team <slug> --json` | List cycles for a team. |
111
+ | `team list --json` / `label list --team <slug> --json` / `state list --team <slug> --json` | Read-only catalogs. |
112
+
113
+ Any command above accepts `--workspace <name>` to target a specific workspace. Every write command short-circuits to a `CONFIRMATION_REQUIRED` error if it looks destructive without `--yes`. Pass `--yes` only when the user has explicitly approved the write.
114
+
115
+ ## Raw GraphQL escape hatch
116
+
117
+ When a curated command doesn't expose a field you need, use the raw layer. Workflow:
118
+
119
+ 1. **Discover the operation:**
120
+ ```
121
+ npx -y linmux@0.1.0 describe IssueBatchCreate --json
122
+ ```
123
+ `describe` returns a Zod-derived schema with required + optional fields.
124
+
125
+ 2. **Invoke it via `raw`:**
126
+ ```
127
+ npx -y linmux@0.1.0 raw IssueBatchCreate \
128
+ --vars '{"input":{"issues":[{"teamId":"...","title":"..."}]}}' \
129
+ --json
130
+ ```
131
+ Output is the SAME envelope shape as curated commands.
132
+
133
+ 3. **Or run an arbitrary GraphQL query string:**
134
+ ```
135
+ npx -y linmux@0.1.0 graphql \
136
+ --query 'query { viewer { id } }' \
137
+ --json
138
+ ```
139
+
140
+ The raw layer covers Linear's full GraphQL surface (~500+ operations) — this is the part the official Linear MCP doesn't reach. Use it when the user asks for something a curated command doesn't expose; otherwise prefer the curated command for cleaner UX and snapshot-stable output.
141
+
142
+ ## Common error envelopes
143
+
144
+ The five most-likely failure codes you'll see:
145
+
146
+ | Code | Exit | Meaning |
147
+ |------|------|---------|
148
+ | `WORKSPACE_NOT_RESOLVED` | 10 | No `LINEAR_API_KEY` and no active workspace. Tell the user to run `linmux workspace add` or set `LINEAR_API_KEY`. |
149
+ | `AUTH_INVALID` | 11 | Token is malformed or has been revoked. Tell the user to regenerate at <https://linear.app/settings/api>. |
150
+ | `VALIDATION_FAILED` | 12 | A required field is missing or malformed. Inspect `error.details.field`. |
151
+ | `RATELIMITED` | 14 | Linear's rate limit is hit (3M points/hr authenticated). `error.transient: true` — back off and retry. |
152
+ | `NETWORK_ERROR` | 15 | Transport-level failure (DNS, TLS, timeout). `error.transient: true` — retry once before surfacing to the user. |
153
+
154
+ The table above covers the five most-frequent codes. Other codes follow the same envelope shape — inspect `error.code` to identify the failure and `error.transient` to decide whether to retry (codes 14 and 15 set `transient: true`).
155
+
156
+ ### Token & Retry Knobs
157
+
158
+ Three flags help shave bytes or control retries in high-volume agent sessions.
159
+
160
+ - `--no-meta`: drop the `meta` block from success envelopes (failure envelopes unchanged for debuggability). Saves ~150–250 bytes per call.
161
+
162
+ ```
163
+ npx -y linmux@0.1.0 issue list --json --no-meta
164
+ ```
165
+
166
+ - `--quiet`: implies `--no-meta` AND suppresses pretty-mode banners. Useful for human pipelines and CI scripts that just want the data.
167
+
168
+ ```
169
+ npx -y linmux@0.1.0 me --json --quiet
170
+ ```
171
+
172
+ - `--retry N`: add N additional retries on top of the per-error-type defaults (3 for rate-limit, 3 for network). Only retries `transient: true` errors; auth and validation errors fail immediately regardless. Each retry attempt is logged to stderr unless `--quiet` is set.
173
+
174
+ ```
175
+ npx -y linmux@0.1.0 issue list --json --retry 2
176
+ ```
177
+
178
+ ## Self-discovery (introspection)
179
+
180
+ The CLI ships with three introspection commands that let an agent learn the surface without external docs:
181
+
182
+ - `npx -y linmux@0.1.0 list-tools --json` — every command (curated + raw) with its one-line description.
183
+ - `npx -y linmux@0.1.0 describe <command-or-operation> --json` — flag schema, JSON output schema, examples.
184
+ - `npx -y linmux@0.1.0 schema --json` — the full Linear GraphQL schema (cached) for arbitrary queries.
185
+
186
+ Always prefer `describe` over reading source. The `describe` output is generated from the same Zod schemas that drive command parsing, so it's the canonical contract for what a command accepts and returns.