docks-kit 0.17.1 → 0.17.2

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 (83) hide show
  1. package/AGENTS.md +36 -32
  2. package/cli/docs/omp-models.md +88 -53
  3. package/cli/src/argv.ts +38 -469
  4. package/cli/src/argvSurface.ts +371 -0
  5. package/cli/src/argvValidate.ts +122 -0
  6. package/cli/src/commands/docs.ts +57 -42
  7. package/cli/src/commands/harnesses.ts +38 -45
  8. package/cli/src/commands/model.ts +48 -53
  9. package/cli/src/commands/models.ts +24 -26
  10. package/cli/src/commands/omp.ts +132 -112
  11. package/cli/src/commands/plugins.ts +20 -20
  12. package/cli/src/commands/skills.ts +22 -20
  13. package/cli/src/commands/status.ts +87 -80
  14. package/cli/src/commands/sync.ts +113 -87
  15. package/cli/src/commands/toolchain.ts +21 -21
  16. package/cli/src/commands/update.ts +139 -117
  17. package/cli/src/efforts.ts +35 -34
  18. package/cli/src/engine-native/DESIGN.md +30 -30
  19. package/cli/src/engine-native/bun.ts +77 -55
  20. package/cli/src/engine-native/claudeLsp.ts +154 -0
  21. package/cli/src/engine-native/claudeOptionalPlugins.ts +113 -0
  22. package/cli/src/engine-native/claudePluginPasses.ts +348 -0
  23. package/cli/src/engine-native/claudeRemovals.ts +195 -0
  24. package/cli/src/engine-native/claudeRetired.ts +4 -4
  25. package/cli/src/engine-native/claudeRuntime.ts +94 -68
  26. package/cli/src/engine-native/claudeSettings.ts +174 -0
  27. package/cli/src/engine-native/claudeSettingsModifiers.ts +50 -54
  28. package/cli/src/engine-native/claudeSync.ts +176 -456
  29. package/cli/src/engine-native/codexConfig.ts +158 -0
  30. package/cli/src/engine-native/codexHooks.ts +91 -0
  31. package/cli/src/engine-native/codexPlugins.ts +290 -0
  32. package/cli/src/engine-native/codexStatus.ts +24 -0
  33. package/cli/src/engine-native/codexSync.ts +110 -568
  34. package/cli/src/engine-native/codexToml.ts +140 -138
  35. package/cli/src/engine-native/deps.ts +144 -107
  36. package/cli/src/engine-native/engineCtx.ts +126 -0
  37. package/cli/src/engine-native/exec.ts +98 -87
  38. package/cli/src/engine-native/failures.ts +3 -3
  39. package/cli/src/engine-native/harnesses.ts +62 -72
  40. package/cli/src/engine-native/index.ts +34 -315
  41. package/cli/src/engine-native/jq.ts +25 -24
  42. package/cli/src/engine-native/logger.ts +98 -100
  43. package/cli/src/engine-native/models.ts +50 -45
  44. package/cli/src/engine-native/modes.ts +83 -80
  45. package/cli/src/engine-native/ompFileDeploy.ts +111 -0
  46. package/cli/src/engine-native/ompMarketplace.ts +136 -0
  47. package/cli/src/engine-native/ompOverlay.ts +67 -64
  48. package/cli/src/engine-native/ompPaths.ts +49 -38
  49. package/cli/src/engine-native/ompPlugins.ts +170 -0
  50. package/cli/src/engine-native/ompSync.ts +64 -408
  51. package/cli/src/engine-native/ompYaml.ts +43 -41
  52. package/cli/src/engine-native/os/darwin.ts +5 -5
  53. package/cli/src/engine-native/os/index.ts +15 -15
  54. package/cli/src/engine-native/os/linux.ts +5 -5
  55. package/cli/src/engine-native/os/posix.ts +28 -24
  56. package/cli/src/engine-native/os/targets.ts +17 -17
  57. package/cli/src/engine-native/os/types.ts +31 -31
  58. package/cli/src/engine-native/os/windows.ts +61 -61
  59. package/cli/src/engine-native/parseArgs.ts +122 -372
  60. package/cli/src/engine-native/parseHelp.ts +66 -0
  61. package/cli/src/engine-native/parseModifiers.ts +222 -0
  62. package/cli/src/engine-native/services.ts +34 -34
  63. package/cli/src/engine-native/settings.ts +15 -15
  64. package/cli/src/engine-native/sharedTypes.d.ts +46 -0
  65. package/cli/src/engine-native/skillsInstall.ts +105 -0
  66. package/cli/src/engine-native/skillsLinks.ts +203 -0
  67. package/cli/src/engine-native/skillsManifest.ts +16 -0
  68. package/cli/src/engine-native/skillsPrune.ts +108 -0
  69. package/cli/src/engine-native/skillsSync.ts +28 -362
  70. package/cli/src/engine-native/syncConcurrency.ts +55 -0
  71. package/cli/src/engine-native/syncDispatch.ts +141 -0
  72. package/cli/src/engine-native/toolchain.ts +65 -62
  73. package/cli/src/engine.ts +65 -57
  74. package/cli/src/generated/sotPayload.ts +7 -7
  75. package/cli/src/kitHome.ts +44 -40
  76. package/cli/src/main.ts +63 -56
  77. package/cli/src/manifests.ts +53 -54
  78. package/cli/src/md.d.ts +2 -2
  79. package/cli/src/payload.ts +9 -9
  80. package/cli/src/services.ts +21 -13
  81. package/cli/tsconfig.json +4 -1
  82. package/package.json +9 -2
  83. package/cli/src/engine-native/claudePlugins.ts +0 -510
@@ -1,63 +1,62 @@
1
- import { Command, Flag } from "effect/unstable/cli"
2
- import { Console, Effect } from "effect"
3
- import { existsSync, readFileSync } from "node:fs"
4
- import { bail, compiled } from "../engine"
5
- import { kitHome } from "../kitHome"
6
- import { p, spawnHost, which } from "../engine-native/exec"
7
- import { hostOs, type HostOs } from "../engine-native/os"
1
+ import { Command, Flag } from "effect/unstable/cli";
2
+ import { Console, Effect } from "effect";
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { bail, compiled } from "../engine";
5
+ import { kitHome } from "../kitHome";
6
+ import { p, spawnHost } from "../engine-native/exec";
7
+ import { hostOs, type HostOs } from "../engine-native/os";
8
8
 
9
9
  const noSync = Flag.Boolean("no-sync").pipe(
10
10
  Flag.withDescription("Update the kit only; skip the chained flag-less sync"),
11
- Flag.withDefault(false)
12
- )
13
-
11
+ Flag.withDefault(false),
12
+ );
14
13
 
15
14
  const git = (home: string, args: Array<string>): { ok: boolean; out: string } => {
16
- const res = spawnHost("git", ["-C", home, ...args])
17
- return { ok: res.error === undefined && res.status === 0, out: `${res.stdout ?? ""}${res.stderr ?? ""}`.trim() }
18
- }
15
+ const res = spawnHost("git", ["-C", home, ...args]);
16
+ return {
17
+ ok: res.error === undefined && res.status === 0,
18
+ out: `${res.stdout ?? ""}${res.stderr ?? ""}`.trim(),
19
+ };
20
+ };
19
21
 
20
22
  /** Spawn the freshly-updated code — the running process still has the old
21
23
  * version loaded, so the chained sync must be a new process. */
22
24
  const chainSync = (argv0: string, args: Array<string>): Effect.Effect<void> =>
23
25
  Effect.sync(() => {
24
- const res = spawnHost(argv0, args, { stdio: "inherit" })
25
- if (res.error !== undefined || res.status !== 0) process.exit(res.status ?? 1)
26
- })
26
+ const res = spawnHost(argv0, args, { stdio: "inherit" });
27
+ if (res.error !== undefined || res.status !== 0) process.exit(res.status ?? 1);
28
+ });
27
29
 
28
- export const updateSyncArgs = (home: string): Array<string> => [p(home, "cli/src/main.ts"), "sync"]
30
+ export const updateSyncArgs = (home: string): Array<string> => [p(home, "cli/src/main.ts"), "sync"];
29
31
 
30
32
  const readPackageVersion = (home: string): string => {
31
33
  try {
32
- const doc: unknown = JSON.parse(readFileSync(p(home, "package.json"), "utf8"))
33
- if (doc === null || typeof doc !== "object" || !("version" in doc)) return ""
34
- return typeof doc.version === "string" ? doc.version : ""
34
+ const doc: unknown = JSON.parse(readFileSync(p(home, "package.json"), "utf8"));
35
+ if (doc === null || typeof doc !== "object" || !("version" in doc)) return "";
36
+ return typeof doc.version === "string" ? doc.version : "";
35
37
  } catch {
36
- return ""
38
+ return "";
37
39
  }
38
- }
40
+ };
39
41
 
40
- export type PackageManager = "bun" | "npm"
42
+ export type PackageManager = "bun" | "npm";
41
43
 
42
44
  interface PackageRootCapture {
43
- readonly status: number | null
44
- readonly stdout: string
45
- readonly error?: Error
45
+ readonly status: number | null;
46
+ readonly stdout: string;
47
+ readonly error?: Error;
46
48
  }
47
49
 
48
- type CapturePackageRoot = (
49
- command: string,
50
- args: ReadonlyArray<string>
51
- ) => PackageRootCapture
50
+ type CapturePackageRoot = (command: string, args: ReadonlyArray<string>) => PackageRootCapture;
52
51
 
53
52
  const capturePackageRoot: CapturePackageRoot = (command, args) => {
54
- const res = spawnHost(command, args)
53
+ const res = spawnHost(command, args);
55
54
  return {
56
55
  status: res.status,
57
56
  stdout: res.stdout ?? "",
58
- ...(res.error === undefined ? {} : { error: res.error })
59
- }
60
- }
57
+ ...(res.error === undefined ? {} : { error: res.error }),
58
+ };
59
+ };
61
60
 
62
61
  /**
63
62
  * A Bun global home is `<root>/.bun/install/global/node_modules/<pkg>`. Windows
@@ -68,187 +67,210 @@ const capturePackageRoot: CapturePackageRoot = (command, args) => {
68
67
  export const packageManagerForHome = (
69
68
  home: string,
70
69
  environment: NodeJS.ProcessEnv = process.env,
71
- host: HostOs = hostOs()
70
+ host: HostOs = hostOs(),
72
71
  ): PackageManager => {
73
72
  const normalize = (value: string): string =>
74
- host.id === "windows" ? value.replaceAll("\\", "/") : value
75
- const normalizedHome = normalize(home)
73
+ host.id === "windows" ? value.replaceAll("\\", "/") : value;
74
+ const normalizedHome = normalize(home);
76
75
  const underEnvironmentRoot = (name: "BUN_INSTALL_GLOBAL_DIR" | "BUN_INSTALL"): boolean => {
77
- const root = environment[name]?.trim()
78
- if (root === undefined || root === "") return false
79
- const normalizedRoot = normalize(root)
80
- return normalizedHome === normalizedRoot || normalizedHome.startsWith(`${normalizedRoot}/`)
81
- }
76
+ const root = environment[name]?.trim();
77
+ if (root === undefined || root === "") return false;
78
+ const normalizedRoot = normalize(root);
79
+ return normalizedHome === normalizedRoot || normalizedHome.startsWith(`${normalizedRoot}/`);
80
+ };
82
81
  return normalizedHome.includes("/.bun/") ||
83
82
  underEnvironmentRoot("BUN_INSTALL_GLOBAL_DIR") ||
84
83
  underEnvironmentRoot("BUN_INSTALL")
85
84
  ? "bun"
86
- : "npm"
87
- }
85
+ : "npm";
86
+ };
88
87
 
89
88
  export type GlobalPackageHome =
90
89
  | { readonly ok: true; readonly home: string }
91
- | { readonly ok: false; readonly diagnostic: string }
90
+ | { readonly ok: false; readonly diagnostic: string };
92
91
 
93
92
  export const resolveGlobalPackageHome = (
94
93
  manager: PackageManager,
95
- capture: CapturePackageRoot = capturePackageRoot
94
+ capture: CapturePackageRoot = capturePackageRoot,
96
95
  ): GlobalPackageHome => {
97
- const commandArgs = manager === "bun" ? ["pm", "-g", "ls"] : ["root", "-g"]
98
- const result = capture(manager, commandArgs)
96
+ const commandArgs = manager === "bun" ? ["pm", "-g", "ls"] : ["root", "-g"];
97
+ const result = capture(manager, commandArgs);
99
98
  if (result.error !== undefined || result.status !== 0) {
100
99
  const detail =
101
100
  result.error !== undefined
102
101
  ? result.error.message
103
- : `exit ${result.status ?? "without status"}`
102
+ : `exit ${result.status ?? "without status"}`;
104
103
  return {
105
104
  ok: false,
106
- diagnostic: `${manager} ${commandArgs.join(" ")} failed: ${detail}`
107
- }
105
+ diagnostic: `${manager} ${commandArgs.join(" ")} failed: ${detail}`,
106
+ };
108
107
  }
109
108
 
110
109
  if (manager === "npm") {
111
- const root = result.stdout.trim()
110
+ const root = result.stdout.trim();
112
111
  return root === ""
113
112
  ? { ok: false, diagnostic: "npm root -g failed: empty output" }
114
- : { ok: true, home: p(root, "docks-kit") }
113
+ : { ok: true, home: p(root, "docks-kit") };
115
114
  }
116
115
 
117
116
  const globalHeader = result.stdout
118
117
  .split(/\r?\n/)
119
118
  .map((line) => line.trim())
120
- .find((line) => / node_modules(?: \(.*\))?$/.test(line))
119
+ .find((line) => / node_modules(?: \(.*\))?$/.test(line));
121
120
  const globalDir =
122
121
  globalHeader === undefined
123
122
  ? undefined
124
- : /^(.*) node_modules(?: \(.*\))?$/.exec(globalHeader)?.[1]
123
+ : /^(.*) node_modules(?: \(.*\))?$/.exec(globalHeader)?.[1];
125
124
  return globalDir === undefined || globalDir === ""
126
125
  ? { ok: false, diagnostic: "bun pm -g ls did not report its global package root" }
127
- : { ok: true, home: p(globalDir, "node_modules", "docks-kit") }
128
- }
126
+ : { ok: true, home: p(globalDir, "node_modules", "docks-kit") };
127
+ };
129
128
 
130
129
  export const packageUpdateResult = (
131
130
  before: string,
132
131
  after: string,
133
- samePackageRoot = true
132
+ samePackageRoot = true,
134
133
  ): { alreadyCurrent: boolean; message: string } => {
135
- if (before === "" || after === "") return { alreadyCurrent: false, message: "" }
134
+ if (before === "" || after === "") return { alreadyCurrent: false, message: "" };
136
135
  if (!samePackageRoot) {
137
136
  return {
138
137
  alreadyCurrent: false,
139
- message: `Installed ${after} in the selected global package root.`
140
- }
138
+ message: `Installed ${after} in the selected global package root.`,
139
+ };
141
140
  }
142
141
  if (before === after) {
143
- return { alreadyCurrent: true, message: `Already at the latest version (${after}).` }
142
+ return { alreadyCurrent: true, message: `Already at the latest version (${after}).` };
144
143
  }
145
- return { alreadyCurrent: false, message: `Updated ${before} -> ${after}.` }
146
- }
144
+ return { alreadyCurrent: false, message: `Updated ${before} -> ${after}.` };
145
+ };
147
146
 
148
147
  const updateCheckout = (home: string, skipSync: boolean) =>
149
148
  Effect.gen(function* () {
150
149
  if (spawnHost("git", ["--version"], { stdio: "ignore" }).status !== 0) {
151
- return yield* bail("git not found - cannot update the kit checkout")
150
+ return yield* bail("git not found - cannot update the kit checkout");
152
151
  }
153
- const dirty = git(home, ["status", "--porcelain"])
154
- if (!dirty.ok) return yield* bail(`git status failed in ${home}: ${dirty.out}`)
152
+ const dirty = git(home, ["status", "--porcelain"]);
153
+ if (!dirty.ok) return yield* bail(`git status failed in ${home}: ${dirty.out}`);
155
154
  if (dirty.out !== "") {
156
- return yield* bail(`kit checkout ${home} has local changes - commit or stash them, then re-run docks-kit update`)
155
+ return yield* bail(
156
+ `kit checkout ${home} has local changes - commit or stash them, then re-run docks-kit update`,
157
+ );
157
158
  }
158
- const upstream = git(home, ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"])
159
+ const upstream = git(home, ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"]);
159
160
  if (!upstream.ok) {
160
- return yield* bail("current branch has no upstream - set one (git branch --set-upstream-to) or update manually")
161
+ return yield* bail(
162
+ "current branch has no upstream - set one (git branch --set-upstream-to) or update manually",
163
+ );
161
164
  }
162
- const before = git(home, ["rev-parse", "HEAD"]).out
163
- const pull = git(home, ["pull", "--ff-only"])
164
- if (!pull.ok) return yield* bail(`git pull --ff-only failed (diverged history?):\n${pull.out}`)
165
- const after = git(home, ["rev-parse", "HEAD"]).out
165
+ const before = git(home, ["rev-parse", "HEAD"]).out;
166
+ const pull = git(home, ["pull", "--ff-only"]);
167
+ if (!pull.ok) return yield* bail(`git pull --ff-only failed (diverged history?):\n${pull.out}`);
168
+ const after = git(home, ["rev-parse", "HEAD"]).out;
166
169
 
167
170
  // A current kit still syncs: the plugin passes deliver marketplace and
168
171
  // plugin updates that move independently of the kit's own version.
169
- const changed = before !== after
172
+ const changed = before !== after;
170
173
  if (changed) {
171
- const count = git(home, ["rev-list", "--count", `${before}..${after}`]).out
172
- yield* Console.log(`Updated ${before.slice(0, 7)}..${after.slice(0, 7)} (${count} commit(s) from ${upstream.out}).`)
174
+ const count = git(home, ["rev-list", "--count", `${before}..${after}`]).out;
175
+ yield* Console.log(
176
+ `Updated ${before.slice(0, 7)}..${after.slice(0, 7)} (${count} commit(s) from ${upstream.out}).`,
177
+ );
173
178
 
174
- const touched = git(home, ["diff", "--name-only", before, after]).out.split("\n")
179
+ const touched = git(home, ["diff", "--name-only", before, after]).out.split("\n");
175
180
  if (touched.includes("bun.lock") || touched.includes("package.json")) {
176
- const res = spawnHost("bun", ["install", "--frozen-lockfile"], { cwd: home, stdio: "inherit" })
181
+ const res = spawnHost("bun", ["install", "--frozen-lockfile"], {
182
+ cwd: home,
183
+ stdio: "inherit",
184
+ });
177
185
  if (res.error !== undefined || res.status !== 0) {
178
- return yield* bail("dependencies changed but 'bun install --frozen-lockfile' failed - fix that, then run docks-kit sync", 1)
186
+ return yield* bail(
187
+ "dependencies changed but 'bun install --frozen-lockfile' failed - fix that, then run docks-kit sync",
188
+ 1,
189
+ );
179
190
  }
180
191
  }
181
192
  } else {
182
- yield* Console.log(`Already at the latest version (${after.slice(0, 7)}, upstream ${upstream.out}).`)
193
+ yield* Console.log(
194
+ `Already at the latest version (${after.slice(0, 7)}, upstream ${upstream.out}).`,
195
+ );
183
196
  }
184
197
 
185
198
  if (compiled) {
186
199
  return yield* Console.log(
187
200
  changed
188
201
  ? "This compiled binary still runs the previous version - the checkout launcher will use updated source next time. Run: ./docks-kit sync (rebuild with bash cli/build-binaries.sh to restore the binary fast path)."
189
- : "This compiled binary cannot chain the sync. Run: ./docks-kit sync"
190
- )
202
+ : "This compiled binary cannot chain the sync. Run: ./docks-kit sync",
203
+ );
191
204
  }
192
- if (skipSync) return yield* Console.log(changed ? "Kit updated. Run: docks-kit sync" : "Run: docks-kit sync")
193
- yield* Console.log(changed ? "Kit updated - running sync with the new version..." : "Syncing to deliver plugin and config updates...")
194
- return yield* chainSync(process.execPath, updateSyncArgs(home))
195
- })
205
+ if (skipSync)
206
+ return yield* Console.log(
207
+ changed ? "Kit updated. Run: docks-kit sync" : "Run: docks-kit sync",
208
+ );
209
+ yield* Console.log(
210
+ changed
211
+ ? "Kit updated - running sync with the new version..."
212
+ : "Syncing to deliver plugin and config updates...",
213
+ );
214
+ return yield* chainSync(process.execPath, updateSyncArgs(home));
215
+ });
196
216
 
197
217
  const updatePackage = (home: string, skipSync: boolean) =>
198
218
  Effect.gen(function* () {
199
- const manager = packageManagerForHome(home)
200
- const beforeVersion = readPackageVersion(home)
201
- const updateArgs = manager === "bun"
202
- ? ["add", "-g", "docks-kit@latest"]
203
- : ["install", "-g", "docks-kit@latest"]
204
- const res = spawnHost(manager, updateArgs, { stdio: "inherit" })
219
+ const manager = packageManagerForHome(home);
220
+ const beforeVersion = readPackageVersion(home);
221
+ const updateArgs =
222
+ manager === "bun" ? ["add", "-g", "docks-kit@latest"] : ["install", "-g", "docks-kit@latest"];
223
+ const res = spawnHost(manager, updateArgs, { stdio: "inherit" });
205
224
  if (res.error !== undefined || res.status !== 0) {
206
225
  return yield* bail(
207
226
  `global package update failed (${manager === "bun" ? "bun add -g" : "npm install -g"} docks-kit@latest)`,
208
- 1
209
- )
227
+ 1,
228
+ );
210
229
  }
211
230
 
212
- const updated = resolveGlobalPackageHome(manager)
231
+ const updated = resolveGlobalPackageHome(manager);
213
232
  if (!updated.ok) {
214
233
  return yield* bail(
215
234
  `global package update completed, but the updated package root could not be resolved: ${updated.diagnostic}`,
216
- 1
217
- )
235
+ 1,
236
+ );
218
237
  }
219
- const afterVersion = readPackageVersion(updated.home)
238
+ const afterVersion = readPackageVersion(updated.home);
220
239
  if (afterVersion === "") {
221
240
  return yield* bail(
222
241
  `global package update completed, but ${p(updated.home, "package.json")} has no readable version`,
223
- 1
224
- )
242
+ 1,
243
+ );
225
244
  }
226
- const result = packageUpdateResult(beforeVersion, afterVersion, home === updated.home)
227
- if (result.message !== "") yield* Console.log(result.message)
228
- if (skipSync) return yield* Console.log(result.alreadyCurrent ? "Run: docks-kit sync" : "Kit updated. Run: docks-kit sync")
245
+ const result = packageUpdateResult(beforeVersion, afterVersion, home === updated.home);
246
+ if (result.message !== "") yield* Console.log(result.message);
247
+ if (skipSync)
248
+ return yield* Console.log(
249
+ result.alreadyCurrent ? "Run: docks-kit sync" : "Kit updated. Run: docks-kit sync",
250
+ );
229
251
  yield* Console.log(
230
252
  result.alreadyCurrent
231
253
  ? "Syncing to deliver plugin and config updates..."
232
- : "Kit updated - running sync with the new version..."
233
- )
234
- return yield* chainSync(process.execPath, updateSyncArgs(updated.home))
235
- })
254
+ : "Kit updated - running sync with the new version...",
255
+ );
256
+ return yield* chainSync(process.execPath, updateSyncArgs(updated.home));
257
+ });
236
258
 
237
259
  export const updateCommand = Command.make("update", { noSync }, (config) =>
238
260
  Effect.gen(function* () {
239
- const home = kitHome()
261
+ const home = kitHome();
240
262
  if (existsSync(p(home, ".git"))) {
241
- return yield* updateCheckout(home, config.noSync)
263
+ return yield* updateCheckout(home, config.noSync);
242
264
  }
243
265
  if (home.includes("node_modules")) {
244
- return yield* updatePackage(home, config.noSync)
266
+ return yield* updatePackage(home, config.noSync);
245
267
  }
246
268
  return yield* bail(
247
- `kit home ${home} is neither a git checkout nor a global package install - update it the way it was installed (e.g. download the latest release binary)`
248
- )
249
- })
269
+ `kit home ${home} is neither a git checkout nor a global package install - update it the way it was installed (e.g. download the latest release binary)`,
270
+ );
271
+ }),
250
272
  ).pipe(
251
273
  Command.withDescription(
252
- "Self-update the kit: autodetects the install (git checkout -> ff-only pull; bun/npm global -> @latest), then chains a flag-less sync that also refreshes plugin marketplaces and plugins, even when the kit was already current (--no-sync to skip)."
253
- )
254
- )
274
+ "Self-update the kit: autodetects the install (git checkout -> ff-only pull; bun/npm global -> @latest), then chains a flag-less sync that also refreshes plugin marketplaces and plugins, even when the kit was already current (--no-sync to skip).",
275
+ ),
276
+ );
@@ -1,7 +1,7 @@
1
- import { sotClaudeSettings, topLevelTomlString, type Tool } from "./manifests"
2
- import { payloadText } from "./payload"
1
+ import { sotClaudeSettings, topLevelTomlString, type Tool } from "./manifests";
2
+ import { payloadText } from "./payload";
3
3
 
4
- export const CLAUDE_EFFORT_LEVELS = ["low", "medium", "high", "xhigh"] as const
4
+ export const CLAUDE_EFFORT_LEVELS = ["low", "medium", "high", "xhigh"] as const;
5
5
  export const CODEX_REASONING_EFFORTS = [
6
6
  "none",
7
7
  "minimal",
@@ -10,71 +10,72 @@ export const CODEX_REASONING_EFFORTS = [
10
10
  "high",
11
11
  "xhigh",
12
12
  "max",
13
- "ultra"
14
- ] as const
15
- export const CLAUDE_ADVISOR_STATES = ["on", "off", "default"] as const
13
+ "ultra",
14
+ ] as const;
15
+ export const CLAUDE_ADVISOR_STATES = ["on", "off", "default"] as const;
16
16
 
17
- const VERIFIED = "2026-07-10"
18
- const DEFAULT = "default"
17
+ const VERIFIED = "2026-07-10";
18
+ const DEFAULT = "default";
19
19
 
20
20
  const upstreamEfforts = (tool: Tool): ReadonlyArray<string> =>
21
- tool === "claude" ? CLAUDE_EFFORT_LEVELS : CODEX_REASONING_EFFORTS
21
+ tool === "claude" ? CLAUDE_EFFORT_LEVELS : CODEX_REASONING_EFFORTS;
22
22
 
23
23
  export const effortModifierValues = (tool: Tool): ReadonlyArray<string> => [
24
24
  ...upstreamEfforts(tool),
25
- DEFAULT
26
- ]
25
+ DEFAULT,
26
+ ];
27
27
 
28
- export const effortValueGrammar = (tool: Tool): string => effortModifierValues(tool).join("|")
28
+ export const effortValueGrammar = (tool: Tool): string => effortModifierValues(tool).join("|");
29
29
 
30
30
  export const effortFlagGrammar = (tool: Tool): string =>
31
- `--${tool}-effort=<${effortValueGrammar(tool)}>`
31
+ `--${tool}-effort=<${effortValueGrammar(tool)}>`;
32
32
 
33
- export const advisorValueGrammar = (): string => CLAUDE_ADVISOR_STATES.join("|")
33
+ export const advisorValueGrammar = (): string => CLAUDE_ADVISOR_STATES.join("|");
34
34
 
35
- export const advisorFlagGrammar = (): string => `--claude-advisor=<${advisorValueGrammar()}>`
35
+ export const advisorFlagGrammar = (): string => `--claude-advisor=<${advisorValueGrammar()}>`;
36
36
 
37
37
  export const isEffortModifierValue = (tool: Tool, value: string): boolean =>
38
- effortModifierValues(tool).includes(value)
38
+ effortModifierValues(tool).includes(value);
39
39
 
40
40
  export function validateEffortDefault(tool: Tool, value: unknown): string {
41
- const toolName = tool === "claude" ? "Claude" : "Codex"
42
- const setting = tool === "claude" ? "effortLevel" : "model_reasoning_effort"
41
+ const toolName = tool === "claude" ? "Claude" : "Codex";
42
+ const setting = tool === "claude" ? "effortLevel" : "model_reasoning_effort";
43
43
  if (typeof value !== "string" || value === "") {
44
- throw new Error(`Embedded SoT ${toolName} ${setting} is missing`)
44
+ throw new Error(`Embedded SoT ${toolName} ${setting} is missing`);
45
45
  }
46
46
  if (!upstreamEfforts(tool).includes(value)) {
47
- throw new Error(`Embedded SoT ${toolName} ${setting} '${value}' is outside the verified catalog`)
47
+ throw new Error(
48
+ `Embedded SoT ${toolName} ${setting} '${value}' is outside the verified catalog`,
49
+ );
48
50
  }
49
- return value
51
+ return value;
50
52
  }
51
53
 
52
-
53
54
  export function sotEffort(tool: Tool): string {
54
55
  const value =
55
56
  tool === "claude"
56
57
  ? sotClaudeSettings().effortLevel
57
- : topLevelTomlString(payloadText("SoT/.codex/config.toml"), "model_reasoning_effort")
58
- return validateEffortDefault(tool, value)
58
+ : topLevelTomlString(payloadText("SoT/.codex/config.toml"), "model_reasoning_effort");
59
+ return validateEffortDefault(tool, value);
59
60
  }
60
61
 
61
62
  export function resolveEffort(tool: Tool, value: string): string {
62
- if (value === DEFAULT) return sotEffort(tool)
63
+ if (value === DEFAULT) return sotEffort(tool);
63
64
  if (!upstreamEfforts(tool).includes(value)) {
64
- throw new Error(`Invalid ${tool} effort '${value}'`)
65
+ throw new Error(`Invalid ${tool} effort '${value}'`);
65
66
  }
66
- return value
67
+ return value;
67
68
  }
68
69
 
69
70
  export function effortCatalog(tool: Tool): string {
70
- const setting = tool === "claude" ? "effortLevel" : "model_reasoning_effort"
71
+ const setting = tool === "claude" ? "effortLevel" : "model_reasoning_effort";
71
72
  const lines = [
72
73
  `Available ${tool} effort levels (${setting}; verified ${VERIFIED}):`,
73
74
  ...upstreamEfforts(tool).map((value) => ` ${value}`),
74
- ` default — SoT: ${sotEffort(tool)}`
75
- ]
76
- if (tool === "codex") lines.push(" (support is model-dependent)")
77
- return lines.join("\n")
75
+ ` default — SoT: ${sotEffort(tool)}`,
76
+ ];
77
+ if (tool === "codex") lines.push(" (support is model-dependent)");
78
+ return lines.join("\n");
78
79
  }
79
80
 
80
81
  export function advisorCatalog(): string {
@@ -82,6 +83,6 @@ export function advisorCatalog(): string {
82
83
  `Available claude advisor states (advisorModel; verified ${VERIFIED}):`,
83
84
  " on — set advisorModel: fable",
84
85
  " off — unset advisorModel",
85
- " default — SoT: off (unset)"
86
- ].join("\n")
86
+ " default — SoT: off (unset)",
87
+ ].join("\n");
87
88
  }
@@ -54,14 +54,14 @@ warnings, and the summary. Status-quo confirmations exist but are opt-in.
54
54
 
55
55
  ### Channels and levels
56
56
 
57
- | Emitter | Channel | Default | `--verbose` | Prefix / form |
58
- |---|---|---|---|---|
59
- | `error(msg)` | stderr | shown | shown | `[err]` red (`\x1b[1;31m`) |
60
- | `warn(msg)` | stderr | shown | shown | `[warn]` yellow (`\x1b[1;33m`) |
61
- | `change(msg)` | stderr | shown | shown | `[ok]` green (`\x1b[1;32m`) — ONLY after an operation actually mutated |
62
- | `verbose(msg)` | stderr | hidden | shown | `[ok]` green — no-op confirmations ("already …", "present", "up to date", "left as-is"), skips |
63
- | `progress(msg)` | stderr | interactive only | interactive only | dim, transient single-line status with no newline |
64
- | `data(line)` | stdout | shown | shown | bare — dry-run report lines, `status --json`, summary block, usage text |
57
+ | Emitter | Channel | Default | `--verbose` | Prefix / form |
58
+ | --------------- | ------- | ---------------- | ---------------- | ---------------------------------------------------------------------------------------------- |
59
+ | `error(msg)` | stderr | shown | shown | `[err]` red (`\x1b[1;31m`) |
60
+ | `warn(msg)` | stderr | shown | shown | `[warn]` yellow (`\x1b[1;33m`) |
61
+ | `change(msg)` | stderr | shown | shown | `[ok]` green (`\x1b[1;32m`) — ONLY after an operation actually mutated |
62
+ | `verbose(msg)` | stderr | hidden | shown | `[ok]` green — no-op confirmations ("already …", "present", "up to date", "left as-is"), skips |
63
+ | `progress(msg)` | stderr | interactive only | interactive only | dim, transient single-line status with no newline |
64
+ | `data(line)` | stdout | shown | shown | bare — dry-run report lines, `status --json`, summary block, usage text |
65
65
 
66
66
  - stdout is data, stderr is logs — the logger NEVER writes to stdout
67
67
  (`engineCapture` depends on it).
@@ -134,28 +134,28 @@ active logger binding.
134
134
 
135
135
  ## Module Map
136
136
 
137
- | Module | Owns |
138
- |---|---|
139
- | `parseArgs.ts` | engine usage, target selection, flag parsing, legacy rename hints, model flag validation |
140
- | `index.ts` | sync orchestration, target dispatch, run summary and next-step blocks |
141
- | `../payload.ts` | generated text/byte payload reads and presentation-only source labels |
142
- | `claudeSync.ts` | Claude pipeline: Bun bootstrap, prepared settings transaction, runtime assets, deploy-time modifiers, `~/.claude.json`, readiness-gated removed artifacts, plugins, optional plugins, LSP binaries |
143
- | `bun.ts` | per-run memoized Bun resolution/bootstrap shared by the Claude runtime and direct toolchain ensure |
144
- | `claudeRuntime.ts` | sentinel validation, absolute runtime paths, no-cutover settings projection, and per-host statusline and failure-hook command materialization |
145
- | `settings.ts` | pure Claude settings merge/reconcile semantics and permission-array union |
146
- | `claudeModel.ts` | deployed Claude model modifier and direct `model claude` write path |
147
- | `codexSync.ts` | Codex pipeline: bubblewrap check, config merge, rules, AGENTS.md, personal marketplace, plugin refresh |
148
- | `codexToml.ts` | line-based top-level TOML replacement and deployed Codex model modifier |
149
- | `skillsSync.ts` | universal skill install/prune, ordered symlink/junction/copy fallback, Claude entry healing, managed-skill snapshot |
150
- | `toolchain.ts` | tool presence/version probes, verified-version floor reporting, report table |
151
- | `modes.ts` | direct `model` and `toolchain` modes |
152
- | `models.ts` | model catalog listing and validation |
153
- | `jq.ts` | JSON helpers that preserve jq-style merge/order/stringify behavior where the deployed file contract needs it |
154
- | `exec.ts` | slash-stable path helpers, host-aware PATH probes and invocation, capture/spawn wrappers, and change-detecting write/copy helpers |
155
- | `logger.ts` | Logger shape + stable raw stdout/stderr sink factory; the run-scoped verbosity gate lives in `index.ts` |
156
- | `deps.ts` | external-tool registry: identity, requirement class, presence probe, supported-host install hints, per-manager missing-tool dedup; callers supply the current run Logger to `warnMissing` |
157
- | `os/` | host reader, injected platform normalization, and per-OS `HostOs` fact modules |
158
- | `services.ts` | shared raw-Logger + DependencyManager + Platform factory; wrapped in Effect Layers at `cli/src/services.ts`, with the run-scoped Logger gate applied only by `runEngineNative` |
137
+ | Module | Owns |
138
+ | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
139
+ | `parseArgs.ts` | engine usage, target selection, flag parsing, legacy rename hints, model flag validation |
140
+ | `index.ts` | sync orchestration, target dispatch, run summary and next-step blocks |
141
+ | `../payload.ts` | generated text/byte payload reads and presentation-only source labels |
142
+ | `claudeSync.ts` | Claude pipeline: Bun bootstrap, prepared settings transaction, runtime assets, deploy-time modifiers, `~/.claude.json`, readiness-gated removed artifacts, plugins, optional plugins, LSP binaries |
143
+ | `bun.ts` | per-run memoized Bun resolution/bootstrap shared by the Claude runtime and direct toolchain ensure |
144
+ | `claudeRuntime.ts` | sentinel validation, absolute runtime paths, no-cutover settings projection, and per-host statusline and failure-hook command materialization |
145
+ | `settings.ts` | pure Claude settings merge/reconcile semantics and permission-array union |
146
+ | `claudeModel.ts` | deployed Claude model modifier and direct `model claude` write path |
147
+ | `codexSync.ts` | Codex pipeline: bubblewrap check, config merge, rules, AGENTS.md, personal marketplace, plugin refresh |
148
+ | `codexToml.ts` | line-based top-level TOML replacement and deployed Codex model modifier |
149
+ | `skillsSync.ts` | universal skill install/prune, ordered symlink/junction/copy fallback, Claude entry healing, managed-skill snapshot |
150
+ | `toolchain.ts` | tool presence/version probes, verified-version floor reporting, report table |
151
+ | `modes.ts` | direct `model` and `toolchain` modes |
152
+ | `models.ts` | model catalog listing and validation |
153
+ | `jq.ts` | JSON helpers that preserve jq-style merge/order/stringify behavior where the deployed file contract needs it |
154
+ | `exec.ts` | slash-stable path helpers, host-aware PATH probes and invocation, capture/spawn wrappers, and change-detecting write/copy helpers |
155
+ | `logger.ts` | Logger shape + stable raw stdout/stderr sink factory; the run-scoped verbosity gate lives in `index.ts` |
156
+ | `deps.ts` | external-tool registry: identity, requirement class, presence probe, supported-host install hints, per-manager missing-tool dedup; callers supply the current run Logger to `warnMissing` |
157
+ | `os/` | host reader, injected platform normalization, and per-OS `HostOs` fact modules |
158
+ | `services.ts` | shared raw-Logger + DependencyManager + Platform factory; wrapped in Effect Layers at `cli/src/services.ts`, with the run-scoped Logger gate applied only by `runEngineNative` |
159
159
 
160
160
  ## Platform Support
161
161