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.
- package/LICENSE +21 -0
- package/README.md +240 -0
- package/bin/run.js +4 -0
- package/dist/commands/comment/create.js +94 -0
- package/dist/commands/comment/delete.js +74 -0
- package/dist/commands/comment/list.js +84 -0
- package/dist/commands/comment/update.js +80 -0
- package/dist/commands/cycle/current.js +78 -0
- package/dist/commands/cycle/list.js +84 -0
- package/dist/commands/cycle/move.js +91 -0
- package/dist/commands/describe.js +65 -0
- package/dist/commands/graphql/index.js +92 -0
- package/dist/commands/install-skill.js +54 -0
- package/dist/commands/issue/archive.js +75 -0
- package/dist/commands/issue/create.js +115 -0
- package/dist/commands/issue/get.js +84 -0
- package/dist/commands/issue/list.js +93 -0
- package/dist/commands/issue/purge.js +81 -0
- package/dist/commands/issue/search.js +109 -0
- package/dist/commands/issue/transition.js +91 -0
- package/dist/commands/issue/trash.js +75 -0
- package/dist/commands/issue/update.js +126 -0
- package/dist/commands/label/create.js +91 -0
- package/dist/commands/label/list.js +76 -0
- package/dist/commands/list-tools.js +47 -0
- package/dist/commands/me.js +71 -0
- package/dist/commands/project/create.js +101 -0
- package/dist/commands/project/get.js +83 -0
- package/dist/commands/project/list.js +75 -0
- package/dist/commands/project/update-status.js +99 -0
- package/dist/commands/project/update.js +99 -0
- package/dist/commands/raw/batch.js +85 -0
- package/dist/commands/raw/index.js +72 -0
- package/dist/commands/schema.js +69 -0
- package/dist/commands/state/list.js +77 -0
- package/dist/commands/team/get.js +73 -0
- package/dist/commands/team/list.js +73 -0
- package/dist/commands/whoami.js +71 -0
- package/dist/commands/workspace/add.js +97 -0
- package/dist/commands/workspace/list.js +47 -0
- package/dist/commands/workspace/remove.js +63 -0
- package/dist/commands/workspace/replace-token.js +89 -0
- package/dist/commands/workspace/use.js +54 -0
- package/dist/core/client/factory.js +28 -0
- package/dist/core/client/index.js +2 -0
- package/dist/core/config/index.js +4 -0
- package/dist/core/config/paths.js +30 -0
- package/dist/core/config/schema.js +36 -0
- package/dist/core/config/store.js +149 -0
- package/dist/core/errors/error.js +142 -0
- package/dist/core/errors/exit-codes.js +70 -0
- package/dist/core/output/envelope.js +53 -0
- package/dist/core/output/format.js +42 -0
- package/dist/core/output/index.js +3 -0
- package/dist/core/pagination/flags.js +29 -0
- package/dist/core/pagination/index.js +2 -0
- package/dist/core/projection/presets.js +116 -0
- package/dist/core/projection/project.js +282 -0
- package/dist/core/redact/redact.js +45 -0
- package/dist/core/resolvers/cycle.js +60 -0
- package/dist/core/resolvers/index.js +7 -0
- package/dist/core/resolvers/label.js +54 -0
- package/dist/core/resolvers/project-status.js +42 -0
- package/dist/core/resolvers/project.js +43 -0
- package/dist/core/resolvers/state.js +46 -0
- package/dist/core/resolvers/team.js +50 -0
- package/dist/core/transport/fetch-interceptor.js +109 -0
- package/dist/core/transport/index.js +3 -0
- package/dist/core/transport/rate-limit.js +167 -0
- package/dist/core/workspace/resolver.js +70 -0
- package/dist/core/workspace/write-guard.js +43 -0
- package/dist/generated/graphql.js +89428 -0
- package/dist/generated/operations.js +3013 -0
- package/dist/lib/comment-create-runtime.js +96 -0
- package/dist/lib/comment-delete-runtime.js +46 -0
- package/dist/lib/comment-list-runtime.js +182 -0
- package/dist/lib/comment-update-runtime.js +93 -0
- package/dist/lib/cycle-current-runtime.js +90 -0
- package/dist/lib/cycle-list-runtime.js +151 -0
- package/dist/lib/cycle-move-runtime.js +142 -0
- package/dist/lib/describe-runtime.js +180 -0
- package/dist/lib/filter-heuristics.js +59 -0
- package/dist/lib/graphql-runtime.js +202 -0
- package/dist/lib/include-fragments.js +73 -0
- package/dist/lib/install-skill-runtime.js +228 -0
- package/dist/lib/introspection-registry.js +488 -0
- package/dist/lib/issue-archive-runtime.js +89 -0
- package/dist/lib/issue-create-runtime.js +175 -0
- package/dist/lib/issue-get-runtime.js +153 -0
- package/dist/lib/issue-list-runtime.js +164 -0
- package/dist/lib/issue-purge-runtime.js +89 -0
- package/dist/lib/issue-search-runtime.js +114 -0
- package/dist/lib/issue-transition-runtime.js +131 -0
- package/dist/lib/issue-trash-runtime.js +84 -0
- package/dist/lib/issue-update-runtime.js +164 -0
- package/dist/lib/label-create-runtime.js +113 -0
- package/dist/lib/label-list-runtime.js +97 -0
- package/dist/lib/levenshtein.js +42 -0
- package/dist/lib/list-tools-runtime.js +38 -0
- package/dist/lib/me-runtime.js +55 -0
- package/dist/lib/project-create-runtime.js +103 -0
- package/dist/lib/project-get-runtime.js +134 -0
- package/dist/lib/project-list-runtime.js +84 -0
- package/dist/lib/project-update-runtime.js +110 -0
- package/dist/lib/project-update-status-runtime.js +91 -0
- package/dist/lib/raw-batch-runtime.js +229 -0
- package/dist/lib/raw-runtime.js +171 -0
- package/dist/lib/schema-loader.js +41 -0
- package/dist/lib/schema-runtime.js +65 -0
- package/dist/lib/state-list-runtime.js +93 -0
- package/dist/lib/team-get-runtime.js +55 -0
- package/dist/lib/team-list-runtime.js +52 -0
- package/dist/lib/workspace-runtime.js +112 -0
- package/dist/operations/_registry.zod.js +5337 -0
- package/oclif.manifest.json +3631 -0
- package/package.json +99 -0
- package/schema.graphql +30772 -0
- 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 };
|