docks-kit 0.17.0 → 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.
- package/AGENTS.md +37 -33
- package/README.md +1 -0
- package/cli/docs/omp-models.md +114 -58
- package/cli/src/argv.ts +38 -469
- package/cli/src/argvSurface.ts +371 -0
- package/cli/src/argvValidate.ts +122 -0
- package/cli/src/commands/docs.ts +57 -42
- package/cli/src/commands/harnesses.ts +38 -45
- package/cli/src/commands/model.ts +48 -53
- package/cli/src/commands/models.ts +24 -26
- package/cli/src/commands/omp.ts +178 -88
- package/cli/src/commands/plugins.ts +20 -20
- package/cli/src/commands/skills.ts +22 -20
- package/cli/src/commands/status.ts +87 -80
- package/cli/src/commands/sync.ts +113 -87
- package/cli/src/commands/toolchain.ts +21 -21
- package/cli/src/commands/update.ts +139 -117
- package/cli/src/efforts.ts +35 -34
- package/cli/src/engine-native/DESIGN.md +30 -30
- package/cli/src/engine-native/bun.ts +77 -55
- package/cli/src/engine-native/claudeLsp.ts +154 -0
- package/cli/src/engine-native/claudeOptionalPlugins.ts +113 -0
- package/cli/src/engine-native/claudePluginPasses.ts +348 -0
- package/cli/src/engine-native/claudeRemovals.ts +195 -0
- package/cli/src/engine-native/claudeRetired.ts +4 -4
- package/cli/src/engine-native/claudeRuntime.ts +94 -68
- package/cli/src/engine-native/claudeSettings.ts +174 -0
- package/cli/src/engine-native/claudeSettingsModifiers.ts +50 -54
- package/cli/src/engine-native/claudeSync.ts +176 -456
- package/cli/src/engine-native/codexConfig.ts +158 -0
- package/cli/src/engine-native/codexHooks.ts +91 -0
- package/cli/src/engine-native/codexPlugins.ts +290 -0
- package/cli/src/engine-native/codexStatus.ts +24 -0
- package/cli/src/engine-native/codexSync.ts +110 -568
- package/cli/src/engine-native/codexToml.ts +140 -138
- package/cli/src/engine-native/deps.ts +144 -107
- package/cli/src/engine-native/engineCtx.ts +126 -0
- package/cli/src/engine-native/exec.ts +98 -87
- package/cli/src/engine-native/failures.ts +3 -3
- package/cli/src/engine-native/harnesses.ts +62 -72
- package/cli/src/engine-native/index.ts +34 -315
- package/cli/src/engine-native/jq.ts +25 -24
- package/cli/src/engine-native/logger.ts +98 -100
- package/cli/src/engine-native/models.ts +50 -45
- package/cli/src/engine-native/modes.ts +83 -80
- package/cli/src/engine-native/ompFileDeploy.ts +111 -0
- package/cli/src/engine-native/ompMarketplace.ts +136 -0
- package/cli/src/engine-native/ompOverlay.ts +93 -53
- package/cli/src/engine-native/ompPaths.ts +49 -38
- package/cli/src/engine-native/ompPlugins.ts +170 -0
- package/cli/src/engine-native/ompSync.ts +64 -408
- package/cli/src/engine-native/ompYaml.ts +43 -41
- package/cli/src/engine-native/os/darwin.ts +5 -5
- package/cli/src/engine-native/os/index.ts +15 -15
- package/cli/src/engine-native/os/linux.ts +5 -5
- package/cli/src/engine-native/os/posix.ts +28 -24
- package/cli/src/engine-native/os/targets.ts +17 -17
- package/cli/src/engine-native/os/types.ts +31 -31
- package/cli/src/engine-native/os/windows.ts +61 -61
- package/cli/src/engine-native/parseArgs.ts +122 -372
- package/cli/src/engine-native/parseHelp.ts +66 -0
- package/cli/src/engine-native/parseModifiers.ts +222 -0
- package/cli/src/engine-native/services.ts +34 -34
- package/cli/src/engine-native/settings.ts +15 -15
- package/cli/src/engine-native/sharedTypes.d.ts +46 -0
- package/cli/src/engine-native/skillsInstall.ts +105 -0
- package/cli/src/engine-native/skillsLinks.ts +203 -0
- package/cli/src/engine-native/skillsManifest.ts +16 -0
- package/cli/src/engine-native/skillsPrune.ts +108 -0
- package/cli/src/engine-native/skillsSync.ts +28 -362
- package/cli/src/engine-native/syncConcurrency.ts +55 -0
- package/cli/src/engine-native/syncDispatch.ts +141 -0
- package/cli/src/engine-native/toolchain.ts +65 -62
- package/cli/src/engine.ts +65 -57
- package/cli/src/generated/sotPayload.ts +7 -7
- package/cli/src/kitHome.ts +44 -40
- package/cli/src/main.ts +63 -56
- package/cli/src/manifests.ts +53 -54
- package/cli/src/md.d.ts +2 -2
- package/cli/src/payload.ts +9 -9
- package/cli/src/services.ts +21 -13
- package/cli/tsconfig.json +4 -1
- package/package.json +9 -2
- 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
|
|
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 {
|
|
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(
|
|
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(
|
|
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(
|
|
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"], {
|
|
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(
|
|
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(
|
|
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)
|
|
193
|
-
|
|
194
|
-
|
|
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 =
|
|
202
|
-
? ["add", "-g", "docks-kit@latest"]
|
|
203
|
-
|
|
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)
|
|
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
|
+
);
|
package/cli/src/efforts.ts
CHANGED
|
@@ -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(
|
|
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
|
|
58
|
-
|
|
59
|
-
| `error(msg)`
|
|
60
|
-
| `warn(msg)`
|
|
61
|
-
| `change(msg)`
|
|
62
|
-
| `verbose(msg)`
|
|
63
|
-
| `progress(msg)` | stderr
|
|
64
|
-
| `data(line)`
|
|
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
|
|
138
|
-
|
|
139
|
-
| `parseArgs.ts`
|
|
140
|
-
| `index.ts`
|
|
141
|
-
| `../payload.ts`
|
|
142
|
-
| `claudeSync.ts`
|
|
143
|
-
| `bun.ts`
|
|
144
|
-
| `claudeRuntime.ts` | sentinel validation, absolute runtime paths, no-cutover settings projection, and per-host statusline and failure-hook command materialization
|
|
145
|
-
| `settings.ts`
|
|
146
|
-
| `claudeModel.ts`
|
|
147
|
-
| `codexSync.ts`
|
|
148
|
-
| `codexToml.ts`
|
|
149
|
-
| `skillsSync.ts`
|
|
150
|
-
| `toolchain.ts`
|
|
151
|
-
| `modes.ts`
|
|
152
|
-
| `models.ts`
|
|
153
|
-
| `jq.ts`
|
|
154
|
-
| `exec.ts`
|
|
155
|
-
| `logger.ts`
|
|
156
|
-
| `deps.ts`
|
|
157
|
-
| `os/`
|
|
158
|
-
| `services.ts`
|
|
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
|
|