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,228 @@
1
+ import { LinearAgentError } from "../core/errors/error.js";
2
+ import * as fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { homedir } from "node:os";
6
+ //#region src/lib/install-skill-runtime.ts
7
+ /**
8
+ * `install-skill` runtime — Phase 5 PLAN 05-02 Task 2, DST-06.
9
+ *
10
+ * Pure async function: copies the bundled `skills/linmux/SKILL.md` from
11
+ * the package install path to `~/.claude/skills/linmux/SKILL.md`. No
12
+ * network calls, no workspace resolution.
13
+ *
14
+ * Source resolution: walks two levels up from this file's directory (via
15
+ * `import.meta.url`) and into `skills/linmux/SKILL.md`. Works in BOTH
16
+ * source-checkout layouts (`src/lib/install-skill-runtime.ts` → `../../skills/...`)
17
+ * AND published-tarball layouts (`dist/lib/install-skill-runtime.js` →
18
+ * `../../skills/...`). The `skills/` dir sits at the package root in both.
19
+ *
20
+ * Target resolution: `path.join(os.homedir(), '.claude', 'skills', 'linmux', 'SKILL.md')`
21
+ * — uniform across macOS, Linux, and Windows. Claude Code uses `os.homedir()`
22
+ * everywhere; no `%APPDATA%` branching, no `~` shell expansion.
23
+ *
24
+ * Live-change-detection mitigation (RESEARCH §4 / Pitfall P12): If THIS
25
+ * process created `~/.claude/skills/` (or one of its ancestors) during the
26
+ * mkdir-p step, the envelope includes a `hint` field telling the user to
27
+ * restart Claude Code. We derive that signal from the return value of
28
+ * `mkdirSync({ recursive: true })` — which returns the first directory it
29
+ * actually created — instead of an existsSync check that races with
30
+ * concurrent installs and produces misleading hints.
31
+ *
32
+ * Frontmatter parsing: We parse `metadata.version` from a YAML-ish frontmatter
33
+ * block ourselves rather than depending on `js-yaml`. Rationale: js-yaml is
34
+ * only a transitive dev dep (via @graphql-codegen/cli) and would not be in the
35
+ * published tarball's `node_modules`. Hand-parsing the small subset we need
36
+ * (a string scalar at `metadata.version`) keeps the runtime self-contained
37
+ * and the cold-start budget tight.
38
+ *
39
+ * Error taxonomy (per RESEARCH §11 Option A — both map to EXIT_CODES.GENERIC):
40
+ * - INSTALL_SKILL_BUNDLE_NOT_FOUND: source missing, frontmatter unparseable,
41
+ * or `metadata.version` absent. `details.expected_path` always present;
42
+ * `details.reason` set to 'frontmatter_invalid' or 'version_missing' when
43
+ * applicable.
44
+ * - INSTALL_SKILL_WRITE_FAILED: mkdir or writeFile threw an underlying fs
45
+ * error (EACCES, ENOSPC, etc.). `details.target` and `details.errno`
46
+ * surface the exact failure.
47
+ *
48
+ * Two-export pattern (S1) is satisfied by this module + `src/commands/install-skill.ts`.
49
+ */
50
+ const HERE = path.dirname(fileURLToPath(import.meta.url));
51
+ const DEFAULT_SOURCE = path.resolve(HERE, "..", "..", "skills", "linmux", "SKILL.md");
52
+ const HINT_PARENT_CREATED = "Restart Claude Code if your session predates ~/.claude/skills/.";
53
+ async function installSkillRuntime(input) {
54
+ const sourcePath = input?.sourcePathOverride ?? DEFAULT_SOURCE;
55
+ const home = (input?.homedirOverride ?? homedir)();
56
+ const fsx = input?.fsOverride ?? {
57
+ readFileSync: fs.readFileSync,
58
+ writeFileSync: fs.writeFileSync,
59
+ mkdirSync: fs.mkdirSync,
60
+ existsSync: fs.existsSync,
61
+ statSync: fs.statSync
62
+ };
63
+ const targetDir = path.join(home, ".claude", "skills", "linmux");
64
+ const target = path.join(targetDir, "SKILL.md");
65
+ const parentSkillsDir = path.join(home, ".claude", "skills");
66
+ let contents;
67
+ try {
68
+ contents = fsx.readFileSync(sourcePath, "utf8");
69
+ } catch (err) {
70
+ const errno = err?.code ?? "UNKNOWN";
71
+ throw new LinearAgentError({
72
+ code: "INSTALL_SKILL_BUNDLE_NOT_FOUND",
73
+ message: `Could not locate bundled SKILL.md at ${sourcePath}. This usually means linmux was run from a source checkout without a build, or the published tarball is corrupt.`,
74
+ transient: false,
75
+ details: {
76
+ expected_path: sourcePath,
77
+ resolved_install_path: HERE,
78
+ errno
79
+ }
80
+ });
81
+ }
82
+ const version = extractMetadataVersion(contents, sourcePath);
83
+ const overwritten = fsx.existsSync(target);
84
+ let parentSkillsCreatedNow = false;
85
+ try {
86
+ const created = fsx.mkdirSync(targetDir, { recursive: true });
87
+ if (typeof created === "string") {
88
+ const createdResolved = path.resolve(created);
89
+ const parentResolved = path.resolve(parentSkillsDir);
90
+ parentSkillsCreatedNow = createdResolved === parentResolved || parentResolved.startsWith(`${createdResolved}${path.sep}`);
91
+ }
92
+ } catch (err) {
93
+ const errno = err?.code ?? "UNKNOWN";
94
+ throw new LinearAgentError({
95
+ code: "INSTALL_SKILL_WRITE_FAILED",
96
+ message: `Could not write SKILL.md to ${target}. Check directory permissions.`,
97
+ transient: false,
98
+ details: {
99
+ target,
100
+ errno
101
+ }
102
+ });
103
+ }
104
+ let unchanged = false;
105
+ if (overwritten) {
106
+ let existing;
107
+ try {
108
+ existing = fsx.readFileSync(target, "utf8");
109
+ } catch {
110
+ existing = void 0;
111
+ }
112
+ if (existing === contents) unchanged = true;
113
+ }
114
+ if (!unchanged) try {
115
+ fsx.writeFileSync(target, contents, "utf8");
116
+ } catch (err) {
117
+ const errno = err?.code ?? "UNKNOWN";
118
+ throw new LinearAgentError({
119
+ code: "INSTALL_SKILL_WRITE_FAILED",
120
+ message: `Could not write SKILL.md to ${target}. Check directory permissions.`,
121
+ transient: false,
122
+ details: {
123
+ target,
124
+ errno
125
+ }
126
+ });
127
+ }
128
+ const data = {
129
+ source: sourcePath,
130
+ target,
131
+ bytes_written: unchanged ? 0 : Buffer.byteLength(contents, "utf8"),
132
+ version,
133
+ overwritten
134
+ };
135
+ if (unchanged) data.unchanged = true;
136
+ if (parentSkillsCreatedNow) data.hint = HINT_PARENT_CREATED;
137
+ return {
138
+ data,
139
+ meta: {}
140
+ };
141
+ }
142
+ /**
143
+ * Extract the `metadata.version` field from a SKILL.md's YAML frontmatter.
144
+ *
145
+ * We hand-parse rather than pull in js-yaml because js-yaml is a transitive
146
+ * dev dep only (via @graphql-codegen/cli) and would not be present in the
147
+ * published tarball. Our SKILL.md is authored in-repo, so the frontmatter
148
+ * shape is fully under our control:
149
+ *
150
+ * ---
151
+ * name: linmux
152
+ * description: ...
153
+ * metadata:
154
+ * version: "0.1.0"
155
+ * ---
156
+ *
157
+ * This parser handles:
158
+ * - quoted (single OR double) and unquoted version strings
159
+ * - any indentation level under `metadata:` (we look for the first
160
+ * `version:` line that follows a `metadata:` line)
161
+ *
162
+ * Failure modes (both surface as INSTALL_SKILL_BUNDLE_NOT_FOUND):
163
+ * - No frontmatter markers at all → reason='frontmatter_invalid'
164
+ * - Frontmatter present but no `metadata.version` → reason='version_missing'
165
+ */
166
+ function extractMetadataVersion(contents, sourcePath) {
167
+ const lines = contents.replace(/^/, "").split(/\r?\n/);
168
+ if (lines[0]?.trim() !== "---") throw new LinearAgentError({
169
+ code: "INSTALL_SKILL_BUNDLE_NOT_FOUND",
170
+ message: `Could not parse YAML frontmatter from ${sourcePath} — missing leading '---' marker.`,
171
+ transient: false,
172
+ details: {
173
+ expected_path: sourcePath,
174
+ reason: "frontmatter_invalid"
175
+ }
176
+ });
177
+ let endIdx = -1;
178
+ for (let i = 1; i < lines.length; i++) if (lines[i]?.trim() === "---") {
179
+ endIdx = i;
180
+ break;
181
+ }
182
+ if (endIdx === -1) throw new LinearAgentError({
183
+ code: "INSTALL_SKILL_BUNDLE_NOT_FOUND",
184
+ message: `Could not parse YAML frontmatter from ${sourcePath} — missing closing '---' marker.`,
185
+ transient: false,
186
+ details: {
187
+ expected_path: sourcePath,
188
+ reason: "frontmatter_invalid"
189
+ }
190
+ });
191
+ const frontmatter = lines.slice(1, endIdx);
192
+ let inMetadata = false;
193
+ let metadataIndent = -1;
194
+ let version;
195
+ for (const line of frontmatter) {
196
+ if (/^metadata\s*:\s*$/.test(line)) {
197
+ inMetadata = true;
198
+ metadataIndent = line.length - line.trimStart().length;
199
+ continue;
200
+ }
201
+ if (inMetadata) {
202
+ if (line.trim() === "" || line.trim().startsWith("#")) continue;
203
+ if (line.length - line.trimStart().length <= metadataIndent) {
204
+ inMetadata = false;
205
+ break;
206
+ }
207
+ const m = line.match(/^\s*version\s*:\s*(.+?)\s*$/);
208
+ if (m?.[1]) {
209
+ let raw = m[1];
210
+ if (raw.startsWith("\"") && raw.endsWith("\"") || raw.startsWith("'") && raw.endsWith("'")) raw = raw.slice(1, -1);
211
+ version = raw;
212
+ break;
213
+ }
214
+ }
215
+ }
216
+ if (!version) throw new LinearAgentError({
217
+ code: "INSTALL_SKILL_BUNDLE_NOT_FOUND",
218
+ message: `Bundled SKILL.md at ${sourcePath} has no metadata.version field in its frontmatter.`,
219
+ transient: false,
220
+ details: {
221
+ expected_path: sourcePath,
222
+ reason: "version_missing"
223
+ }
224
+ });
225
+ return version;
226
+ }
227
+ //#endregion
228
+ export { installSkillRuntime };
@@ -0,0 +1,488 @@
1
+ import { OPERATION_REGISTRY } from "../generated/operations.js";
2
+ import { z } from "zod";
3
+ //#region src/lib/introspection-registry.ts
4
+ /**
5
+ * Introspection registry — Phase 4 PLAN 04-01 spine.
6
+ *
7
+ * Exports:
8
+ * - `CURATED_REGISTRY` — hand-curated list of all 36 curated commands,
9
+ * sorted alphabetically by id. Snapshot-pinned in CI (INT-04).
10
+ * - `CuratedEntry`, `CommandExample`, `RawCommandEntry` — interfaces
11
+ * - `getRawRegistryView()` — flattened view over OPERATION_REGISTRY for raw introspection
12
+ *
13
+ * InputSchema stubs: all entries use `z.object({})` here. Phase 4 plan 04-03
14
+ * (describe-runtime.ts) replaces stubs with per-command `*InputSchema` exports.
15
+ * The stubs are acceptable because:
16
+ * 1. list-tools only uses `flags[]` names, not the schema object
17
+ * 2. introspection-registry.test.ts verifies structural integrity, not schema contents
18
+ * 3. describe-runtime.ts (04-03) wires real schemas via per-command exports
19
+ */
20
+ const CURATED_REGISTRY = [
21
+ {
22
+ id: "comment create",
23
+ summary: "Create a new comment on a Linear issue.",
24
+ flags: [
25
+ "workspace",
26
+ "allow-active-workspace-write",
27
+ "fields",
28
+ "issue",
29
+ "body",
30
+ "parent"
31
+ ],
32
+ raw_equivalent: "CommentCreate",
33
+ inputSchema: z.object({}),
34
+ examples: []
35
+ },
36
+ {
37
+ id: "comment delete",
38
+ summary: "Delete a comment from a Linear issue.",
39
+ flags: ["workspace", "allow-active-workspace-write"],
40
+ raw_equivalent: "CommentDelete",
41
+ inputSchema: z.object({}),
42
+ examples: []
43
+ },
44
+ {
45
+ id: "comment list",
46
+ summary: "List comments on a Linear issue, with optional related-entity hydration.",
47
+ flags: [
48
+ "workspace",
49
+ "fields",
50
+ "issue",
51
+ "include"
52
+ ],
53
+ raw_equivalent: "Comments",
54
+ inputSchema: z.object({}),
55
+ examples: []
56
+ },
57
+ {
58
+ id: "comment update",
59
+ summary: "Update the body of an existing Linear comment.",
60
+ flags: [
61
+ "workspace",
62
+ "allow-active-workspace-write",
63
+ "fields",
64
+ "body"
65
+ ],
66
+ raw_equivalent: "CommentUpdate",
67
+ inputSchema: z.object({}),
68
+ examples: []
69
+ },
70
+ {
71
+ id: "cycle current",
72
+ summary: "Retrieve the currently active cycle for a team.",
73
+ flags: [
74
+ "workspace",
75
+ "fields",
76
+ "team"
77
+ ],
78
+ inputSchema: z.object({}),
79
+ examples: []
80
+ },
81
+ {
82
+ id: "cycle list",
83
+ summary: "List all cycles for a team, with optional issue hydration.",
84
+ flags: [
85
+ "workspace",
86
+ "fields",
87
+ "team",
88
+ "include"
89
+ ],
90
+ raw_equivalent: "Cycles",
91
+ inputSchema: z.object({}),
92
+ examples: []
93
+ },
94
+ {
95
+ id: "cycle move",
96
+ summary: "Move an issue into a specific cycle number for a team.",
97
+ flags: [
98
+ "workspace",
99
+ "allow-active-workspace-write",
100
+ "fields",
101
+ "to"
102
+ ],
103
+ inputSchema: z.object({}),
104
+ examples: []
105
+ },
106
+ {
107
+ id: "describe",
108
+ summary: "Return input/output JSON Schema and examples for a curated or raw command.",
109
+ flags: ["pretty"],
110
+ inputSchema: z.object({}),
111
+ examples: []
112
+ },
113
+ {
114
+ id: "graphql",
115
+ summary: "Execute an arbitrary GraphQL query or mutation against Linear.",
116
+ flags: [
117
+ "workspace",
118
+ "allow-active-workspace-write",
119
+ "allow-mutations",
120
+ "query",
121
+ "vars"
122
+ ],
123
+ inputSchema: z.object({}),
124
+ examples: []
125
+ },
126
+ {
127
+ id: "install-skill",
128
+ summary: "Copy the bundled Claude Code skill to ~/.claude/skills/linmux/SKILL.md.",
129
+ flags: ["pretty"],
130
+ inputSchema: z.object({}),
131
+ examples: []
132
+ },
133
+ {
134
+ id: "issue archive",
135
+ summary: "Archive a Linear issue (soft-delete; issue remains searchable).",
136
+ flags: ["workspace", "allow-active-workspace-write"],
137
+ raw_equivalent: "IssueArchive",
138
+ inputSchema: z.object({}),
139
+ examples: []
140
+ },
141
+ {
142
+ id: "issue create",
143
+ summary: "Create a new Linear issue with optional title, description, assignee, team, and more.",
144
+ flags: [
145
+ "workspace",
146
+ "allow-active-workspace-write",
147
+ "fields",
148
+ "title",
149
+ "description",
150
+ "team",
151
+ "state",
152
+ "assignee",
153
+ "priority",
154
+ "labels",
155
+ "project",
156
+ "cycle",
157
+ "parent"
158
+ ],
159
+ raw_equivalent: "IssueCreate",
160
+ inputSchema: z.object({}),
161
+ examples: []
162
+ },
163
+ {
164
+ id: "issue get",
165
+ summary: "Fetch a single Linear issue by identifier or UUID.",
166
+ flags: [
167
+ "workspace",
168
+ "fields",
169
+ "include"
170
+ ],
171
+ raw_equivalent: "Issue",
172
+ inputSchema: z.object({}),
173
+ examples: []
174
+ },
175
+ {
176
+ id: "issue list",
177
+ summary: "List Linear issues with --fields, --limit, --cursor, and Phase 1 filters.",
178
+ flags: [
179
+ "workspace",
180
+ "fields",
181
+ "limit",
182
+ "cursor",
183
+ "state",
184
+ "assignee",
185
+ "team",
186
+ "include"
187
+ ],
188
+ raw_equivalent: "Issues",
189
+ inputSchema: z.object({}),
190
+ examples: []
191
+ },
192
+ {
193
+ id: "issue purge",
194
+ summary: "Permanently delete a Linear issue (irreversible; requires --yes confirmation).",
195
+ flags: [
196
+ "workspace",
197
+ "allow-active-workspace-write",
198
+ "yes"
199
+ ],
200
+ raw_equivalent: "IssueDelete",
201
+ inputSchema: z.object({}),
202
+ examples: []
203
+ },
204
+ {
205
+ id: "issue search",
206
+ summary: "Full-text search Linear issues with optional filters for state, team, assignee, label, project, and cycle.",
207
+ flags: [
208
+ "workspace",
209
+ "fields",
210
+ "state",
211
+ "assignee",
212
+ "team",
213
+ "label",
214
+ "project",
215
+ "cycle",
216
+ "no-snippet",
217
+ "include-archived"
218
+ ],
219
+ raw_equivalent: "IssueSearch",
220
+ inputSchema: z.object({}),
221
+ examples: []
222
+ },
223
+ {
224
+ id: "issue transition",
225
+ summary: "Transition a Linear issue to a new workflow state by name or ID.",
226
+ flags: [
227
+ "workspace",
228
+ "allow-active-workspace-write",
229
+ "fields"
230
+ ],
231
+ inputSchema: z.object({}),
232
+ examples: []
233
+ },
234
+ {
235
+ id: "issue trash",
236
+ summary: "Move a Linear issue to the trash (soft-delete; recoverable from UI).",
237
+ flags: ["workspace", "allow-active-workspace-write"],
238
+ inputSchema: z.object({}),
239
+ examples: []
240
+ },
241
+ {
242
+ id: "issue update",
243
+ summary: "Update fields on an existing Linear issue (title, description, assignee, state, etc.).",
244
+ flags: [
245
+ "workspace",
246
+ "allow-active-workspace-write",
247
+ "fields",
248
+ "title",
249
+ "description",
250
+ "state",
251
+ "assignee",
252
+ "priority",
253
+ "labels",
254
+ "project",
255
+ "cycle"
256
+ ],
257
+ raw_equivalent: "IssueUpdate",
258
+ inputSchema: z.object({}),
259
+ examples: []
260
+ },
261
+ {
262
+ id: "label create",
263
+ summary: "Create a new issue label in a Linear team.",
264
+ flags: [
265
+ "workspace",
266
+ "allow-active-workspace-write",
267
+ "fields",
268
+ "name",
269
+ "team",
270
+ "color",
271
+ "description"
272
+ ],
273
+ raw_equivalent: "IssueLabelCreate",
274
+ inputSchema: z.object({}),
275
+ examples: []
276
+ },
277
+ {
278
+ id: "label list",
279
+ summary: "List issue labels for a Linear team or the entire workspace.",
280
+ flags: [
281
+ "workspace",
282
+ "fields",
283
+ "team"
284
+ ],
285
+ raw_equivalent: "IssueLabels",
286
+ inputSchema: z.object({}),
287
+ examples: []
288
+ },
289
+ {
290
+ id: "list-tools",
291
+ summary: "Enumerate every curated and raw command with curated→raw mappings.",
292
+ flags: ["pretty"],
293
+ inputSchema: z.object({}),
294
+ examples: []
295
+ },
296
+ {
297
+ id: "me",
298
+ summary: "Return the authenticated user and organization details.",
299
+ flags: ["workspace", "fields"],
300
+ inputSchema: z.object({}),
301
+ examples: []
302
+ },
303
+ {
304
+ id: "project create",
305
+ summary: "Create a new Linear project with optional name, description, teams, state, and dates.",
306
+ flags: [
307
+ "workspace",
308
+ "allow-active-workspace-write",
309
+ "fields",
310
+ "name",
311
+ "teams",
312
+ "description",
313
+ "state",
314
+ "lead",
315
+ "start-date",
316
+ "target-date"
317
+ ],
318
+ raw_equivalent: "ProjectCreate",
319
+ inputSchema: z.object({}),
320
+ examples: []
321
+ },
322
+ {
323
+ id: "project get",
324
+ summary: "Fetch a single Linear project by ID or name.",
325
+ flags: [
326
+ "workspace",
327
+ "fields",
328
+ "include"
329
+ ],
330
+ raw_equivalent: "Project",
331
+ inputSchema: z.object({}),
332
+ examples: []
333
+ },
334
+ {
335
+ id: "project list",
336
+ summary: "List all Linear projects in the workspace.",
337
+ flags: ["workspace", "fields"],
338
+ raw_equivalent: "Projects",
339
+ inputSchema: z.object({}),
340
+ examples: []
341
+ },
342
+ {
343
+ id: "project update",
344
+ summary: "Update fields on an existing Linear project (name, description, state).",
345
+ flags: [
346
+ "workspace",
347
+ "allow-active-workspace-write",
348
+ "fields",
349
+ "name",
350
+ "description",
351
+ "state"
352
+ ],
353
+ raw_equivalent: "ProjectUpdate",
354
+ inputSchema: z.object({}),
355
+ examples: []
356
+ },
357
+ {
358
+ id: "project update-status",
359
+ summary: "Set a Linear project's current status (e.g. 'On Track' -> 'At Risk').",
360
+ flags: [
361
+ "workspace",
362
+ "allow-active-workspace-write",
363
+ "fields"
364
+ ],
365
+ raw_equivalent: "ProjectUpdate",
366
+ inputSchema: z.object({}),
367
+ examples: []
368
+ },
369
+ {
370
+ id: "raw",
371
+ summary: "Execute any operation from the full Linear GraphQL registry by PascalCase name.",
372
+ flags: [
373
+ "workspace",
374
+ "allow-active-workspace-write",
375
+ "allow-mutations",
376
+ "vars"
377
+ ],
378
+ inputSchema: z.object({}),
379
+ examples: []
380
+ },
381
+ {
382
+ id: "raw batch",
383
+ summary: "Execute a batch of raw Linear GraphQL operations from a plan file.",
384
+ flags: [
385
+ "workspace",
386
+ "allow-active-workspace-write",
387
+ "allow-mutations",
388
+ "plan",
389
+ "dry-run",
390
+ "yes"
391
+ ],
392
+ inputSchema: z.object({}),
393
+ examples: []
394
+ },
395
+ {
396
+ id: "schema",
397
+ summary: "Return the Linear GraphQL schema as compact SDL or introspection JSON.",
398
+ flags: [
399
+ "pretty",
400
+ "full",
401
+ "json"
402
+ ],
403
+ inputSchema: z.object({}),
404
+ examples: []
405
+ },
406
+ {
407
+ id: "state list",
408
+ summary: "List workflow states for a Linear team.",
409
+ flags: [
410
+ "workspace",
411
+ "fields",
412
+ "team"
413
+ ],
414
+ raw_equivalent: "WorkflowStates",
415
+ inputSchema: z.object({}),
416
+ examples: []
417
+ },
418
+ {
419
+ id: "team get",
420
+ summary: "Fetch details for a single Linear team by key, name, or ID.",
421
+ flags: ["workspace", "fields"],
422
+ raw_equivalent: "Team",
423
+ inputSchema: z.object({}),
424
+ examples: []
425
+ },
426
+ {
427
+ id: "team list",
428
+ summary: "List all Linear teams in the workspace.",
429
+ flags: ["workspace", "fields"],
430
+ raw_equivalent: "Teams",
431
+ inputSchema: z.object({}),
432
+ examples: []
433
+ },
434
+ {
435
+ id: "whoami",
436
+ summary: "Alias for `me` — return the authenticated user and organization details.",
437
+ flags: ["workspace", "fields"],
438
+ inputSchema: z.object({}),
439
+ examples: []
440
+ },
441
+ {
442
+ id: "workspace add",
443
+ summary: "Add a new Linear workspace to the local config with a personal API token.",
444
+ flags: ["token"],
445
+ inputSchema: z.object({}),
446
+ examples: []
447
+ },
448
+ {
449
+ id: "workspace list",
450
+ summary: "List all configured Linear workspaces in the local config.",
451
+ flags: [],
452
+ inputSchema: z.object({}),
453
+ examples: []
454
+ },
455
+ {
456
+ id: "workspace remove",
457
+ summary: "Remove a Linear workspace from the local config.",
458
+ flags: [],
459
+ inputSchema: z.object({}),
460
+ examples: []
461
+ },
462
+ {
463
+ id: "workspace replace-token",
464
+ summary: "Replace the API token for an existing workspace in the local config.",
465
+ flags: ["token"],
466
+ inputSchema: z.object({}),
467
+ examples: []
468
+ },
469
+ {
470
+ id: "workspace use",
471
+ summary: "Set the active default workspace used when no --workspace flag is provided.",
472
+ flags: [],
473
+ inputSchema: z.object({}),
474
+ examples: []
475
+ }
476
+ ];
477
+ /**
478
+ * Convenience view over OPERATION_REGISTRY for introspection commands.
479
+ * Returns all operations with their name and kind (query | mutation).
480
+ */
481
+ function getRawRegistryView() {
482
+ return Object.entries(OPERATION_REGISTRY).map(([name, entry]) => ({
483
+ name,
484
+ kind: entry.kind
485
+ }));
486
+ }
487
+ //#endregion
488
+ export { CURATED_REGISTRY, getRawRegistryView };