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.
- package/AGENTS.md +36 -32
- package/cli/docs/omp-models.md +88 -53
- 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 +132 -112
- 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 +67 -64
- 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,32 +1,32 @@
|
|
|
1
|
-
import { Command, Flag } from "effect/unstable/cli"
|
|
2
|
-
import { Console, Effect } from "effect"
|
|
3
|
-
import { engineCapture, type EngineCaptureError } from "../engine"
|
|
1
|
+
import { Command, Flag } from "effect/unstable/cli";
|
|
2
|
+
import { Console, Effect } from "effect";
|
|
3
|
+
import { engineCapture, type EngineCaptureError } from "../engine";
|
|
4
4
|
import {
|
|
5
5
|
deployedClaudeSettings,
|
|
6
6
|
deployedCodexModel,
|
|
7
7
|
pluginsView,
|
|
8
8
|
skillsView,
|
|
9
9
|
sotClaudeSettings,
|
|
10
|
-
sotCodexModel
|
|
11
|
-
} from "../manifests"
|
|
12
|
-
import { kitHome } from "../kitHome"
|
|
10
|
+
sotCodexModel,
|
|
11
|
+
} from "../manifests";
|
|
12
|
+
import { kitHome } from "../kitHome";
|
|
13
13
|
|
|
14
14
|
const json = Flag.Boolean("json").pipe(
|
|
15
15
|
Flag.withDescription("Machine-readable output"),
|
|
16
|
-
Flag.withDefault(false)
|
|
17
|
-
)
|
|
16
|
+
Flag.withDefault(false),
|
|
17
|
+
);
|
|
18
18
|
|
|
19
19
|
interface Drift {
|
|
20
|
-
readonly setting: string
|
|
21
|
-
readonly deployed: string
|
|
22
|
-
readonly sot: string
|
|
23
|
-
readonly drifted: boolean
|
|
20
|
+
readonly setting: string;
|
|
21
|
+
readonly deployed: string;
|
|
22
|
+
readonly sot: string;
|
|
23
|
+
readonly drifted: boolean;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
type ClaudeDeployment =
|
|
27
27
|
| { readonly state: "absent" }
|
|
28
28
|
| { readonly state: "valid"; readonly settings: Record<string, unknown> }
|
|
29
|
-
| { readonly state: "malformed"; readonly diagnostic: string }
|
|
29
|
+
| { readonly state: "malformed"; readonly diagnostic: string };
|
|
30
30
|
|
|
31
31
|
const captureToolchainStatus = () =>
|
|
32
32
|
engineCapture(["toolchain", "check"]).pipe(
|
|
@@ -36,58 +36,63 @@ const captureToolchainStatus = () =>
|
|
|
36
36
|
state: "failed" as const,
|
|
37
37
|
table: "",
|
|
38
38
|
diagnostic: error.diagnostic,
|
|
39
|
-
exitCode: error.code
|
|
40
|
-
})
|
|
41
|
-
)
|
|
42
|
-
)
|
|
39
|
+
exitCode: error.code,
|
|
40
|
+
}),
|
|
41
|
+
),
|
|
42
|
+
);
|
|
43
43
|
|
|
44
44
|
const readClaudeDeployment = (): ClaudeDeployment => {
|
|
45
45
|
try {
|
|
46
|
-
const settings: unknown = deployedClaudeSettings()
|
|
47
|
-
if (settings === undefined) return { state: "absent" }
|
|
46
|
+
const settings: unknown = deployedClaudeSettings();
|
|
47
|
+
if (settings === undefined) return { state: "absent" };
|
|
48
48
|
if (settings === null || typeof settings !== "object" || Array.isArray(settings)) {
|
|
49
49
|
return {
|
|
50
50
|
state: "malformed",
|
|
51
|
-
diagnostic: "deployed Claude settings must contain a JSON object"
|
|
52
|
-
}
|
|
51
|
+
diagnostic: "deployed Claude settings must contain a JSON object",
|
|
52
|
+
};
|
|
53
53
|
}
|
|
54
|
-
return { state: "valid", settings: settings as Record<string, unknown> }
|
|
54
|
+
return { state: "valid", settings: settings as Record<string, unknown> };
|
|
55
55
|
} catch (error) {
|
|
56
|
-
const detail = error instanceof Error ? error.message : String(error)
|
|
56
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
57
57
|
return {
|
|
58
58
|
state: "malformed",
|
|
59
|
-
diagnostic: `deployed Claude settings contain invalid JSON: ${detail}
|
|
60
|
-
}
|
|
59
|
+
diagnostic: `deployed Claude settings contain invalid JSON: ${detail}`,
|
|
60
|
+
};
|
|
61
61
|
}
|
|
62
|
-
}
|
|
62
|
+
};
|
|
63
63
|
|
|
64
64
|
const gatherDrift = (): {
|
|
65
|
-
readonly drift: Array<Drift
|
|
66
|
-
readonly claudeDeployment: ClaudeDeployment
|
|
65
|
+
readonly drift: Array<Drift>;
|
|
66
|
+
readonly claudeDeployment: ClaudeDeployment;
|
|
67
67
|
} => {
|
|
68
|
-
const sot = sotClaudeSettings()
|
|
69
|
-
const claudeDeployment = readClaudeDeployment()
|
|
68
|
+
const sot = sotClaudeSettings();
|
|
69
|
+
const claudeDeployment = readClaudeDeployment();
|
|
70
70
|
const row = (setting: string, deployed: unknown, sotVal: unknown): Drift => {
|
|
71
|
-
const d = String(deployed ?? "(unset)")
|
|
72
|
-
const s = String(sotVal ?? "(unset)")
|
|
73
|
-
return { setting, deployed: d, sot: s, drifted: d !== s }
|
|
74
|
-
}
|
|
75
|
-
const codex = row("codex.model", deployedCodexModel(), sotCodexModel())
|
|
71
|
+
const d = String(deployed ?? "(unset)");
|
|
72
|
+
const s = String(sotVal ?? "(unset)");
|
|
73
|
+
return { setting, deployed: d, sot: s, drifted: d !== s };
|
|
74
|
+
};
|
|
75
|
+
const codex = row("codex.model", deployedCodexModel(), sotCodexModel());
|
|
76
76
|
if (claudeDeployment.state !== "valid") {
|
|
77
77
|
return {
|
|
78
78
|
claudeDeployment,
|
|
79
79
|
drift: [
|
|
80
|
-
{
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
{
|
|
81
|
+
setting: "claude.settings",
|
|
82
|
+
deployed: `(${claudeDeployment.state})`,
|
|
83
|
+
sot: "present",
|
|
84
|
+
drifted: true,
|
|
85
|
+
},
|
|
86
|
+
codex,
|
|
87
|
+
],
|
|
88
|
+
};
|
|
84
89
|
}
|
|
85
90
|
|
|
86
|
-
const dep = claudeDeployment.settings
|
|
91
|
+
const dep = claudeDeployment.settings;
|
|
87
92
|
const env =
|
|
88
93
|
dep.env !== null && typeof dep.env === "object" && !Array.isArray(dep.env)
|
|
89
94
|
? (dep.env as Record<string, unknown>)
|
|
90
|
-
: {}
|
|
95
|
+
: {};
|
|
91
96
|
return {
|
|
92
97
|
claudeDeployment,
|
|
93
98
|
drift: [
|
|
@@ -96,40 +101,40 @@ const gatherDrift = (): {
|
|
|
96
101
|
row(
|
|
97
102
|
"claude.compactWindow",
|
|
98
103
|
env.CLAUDE_CODE_AUTO_COMPACT_WINDOW,
|
|
99
|
-
sot.env?.CLAUDE_CODE_AUTO_COMPACT_WINDOW
|
|
104
|
+
sot.env?.CLAUDE_CODE_AUTO_COMPACT_WINDOW,
|
|
100
105
|
),
|
|
101
|
-
codex
|
|
102
|
-
]
|
|
103
|
-
}
|
|
104
|
-
}
|
|
106
|
+
codex,
|
|
107
|
+
],
|
|
108
|
+
};
|
|
109
|
+
};
|
|
105
110
|
|
|
106
111
|
export const statusCommand = Command.make("status", { json }, (config) =>
|
|
107
112
|
Effect.gen(function* () {
|
|
108
|
-
const { drift, claudeDeployment } = gatherDrift()
|
|
109
|
-
const plugins = pluginsView()
|
|
110
|
-
const skills = skillsView()
|
|
111
|
-
const toolchain = yield* captureToolchainStatus()
|
|
112
|
-
const diagnostics = new Array<{ source: string; message: string; exitCode: number }>()
|
|
113
|
+
const { drift, claudeDeployment } = gatherDrift();
|
|
114
|
+
const plugins = pluginsView();
|
|
115
|
+
const skills = skillsView();
|
|
116
|
+
const toolchain = yield* captureToolchainStatus();
|
|
117
|
+
const diagnostics = new Array<{ source: string; message: string; exitCode: number }>();
|
|
113
118
|
if (claudeDeployment.state === "malformed") {
|
|
114
119
|
diagnostics.push({
|
|
115
120
|
source: "claude.settings",
|
|
116
121
|
message: claudeDeployment.diagnostic,
|
|
117
|
-
exitCode: 1
|
|
118
|
-
})
|
|
122
|
+
exitCode: 1,
|
|
123
|
+
});
|
|
119
124
|
}
|
|
120
125
|
if (toolchain.state === "failed") {
|
|
121
126
|
diagnostics.push({
|
|
122
127
|
source: "toolchain",
|
|
123
128
|
message: toolchain.diagnostic ?? "toolchain capture failed",
|
|
124
|
-
exitCode: toolchain.exitCode ?? 1
|
|
125
|
-
})
|
|
129
|
+
exitCode: toolchain.exitCode ?? 1,
|
|
130
|
+
});
|
|
126
131
|
}
|
|
127
132
|
|
|
128
133
|
if (config.json) {
|
|
129
134
|
const deployment =
|
|
130
135
|
claudeDeployment.state === "malformed"
|
|
131
136
|
? { claude: { state: claudeDeployment.state, diagnostic: claudeDeployment.diagnostic } }
|
|
132
|
-
: { claude: { state: claudeDeployment.state } }
|
|
137
|
+
: { claude: { state: claudeDeployment.state } };
|
|
133
138
|
yield* Console.log(
|
|
134
139
|
JSON.stringify(
|
|
135
140
|
{
|
|
@@ -139,46 +144,48 @@ export const statusCommand = Command.make("status", { json }, (config) =>
|
|
|
139
144
|
plugins,
|
|
140
145
|
skills,
|
|
141
146
|
toolchain,
|
|
142
|
-
diagnostics
|
|
147
|
+
diagnostics,
|
|
143
148
|
},
|
|
144
149
|
null,
|
|
145
|
-
2
|
|
146
|
-
)
|
|
147
|
-
)
|
|
150
|
+
2,
|
|
151
|
+
),
|
|
152
|
+
);
|
|
148
153
|
} else {
|
|
149
|
-
yield* Console.log(`Kit home: ${kitHome()}\n`)
|
|
150
|
-
yield* Console.log("Deployed vs SoT (drift is expected for deploy-time modifiers):")
|
|
154
|
+
yield* Console.log(`Kit home: ${kitHome()}\n`);
|
|
155
|
+
yield* Console.log("Deployed vs SoT (drift is expected for deploy-time modifiers):");
|
|
151
156
|
for (const d of drift) {
|
|
152
|
-
const mark = d.drifted ? "≠" : "="
|
|
153
|
-
yield* Console.log(
|
|
157
|
+
const mark = d.drifted ? "≠" : "=";
|
|
158
|
+
yield* Console.log(
|
|
159
|
+
` ${d.setting.padEnd(22)} deployed=${d.deployed} ${mark} SoT=${d.sot}`,
|
|
160
|
+
);
|
|
154
161
|
}
|
|
155
162
|
if (claudeDeployment.state === "malformed") {
|
|
156
|
-
yield* Console.log(` ERROR claude.settings: ${claudeDeployment.diagnostic}`)
|
|
163
|
+
yield* Console.log(` ERROR claude.settings: ${claudeDeployment.diagnostic}`);
|
|
157
164
|
}
|
|
158
|
-
yield* Console.log("\nToolchain:")
|
|
165
|
+
yield* Console.log("\nToolchain:");
|
|
159
166
|
if (toolchain.state === "failed") {
|
|
160
|
-
yield* Console.log(` ERROR: ${toolchain.diagnostic}`)
|
|
167
|
+
yield* Console.log(` ERROR: ${toolchain.diagnostic}`);
|
|
161
168
|
} else {
|
|
162
|
-
yield* Console.log(toolchain.table.trimEnd())
|
|
169
|
+
yield* Console.log(toolchain.table.trimEnd());
|
|
163
170
|
}
|
|
164
|
-
const enabled = plugins.filter((p) => p.sot === "true").length
|
|
171
|
+
const enabled = plugins.filter((p) => p.sot === "true").length;
|
|
165
172
|
yield* Console.log(
|
|
166
|
-
`\nPlugins: ${plugins.length} known (${enabled} SoT-enabled) — details: docks-kit plugins list
|
|
167
|
-
)
|
|
168
|
-
const installed = skills.filter((s) => s.installed).length
|
|
173
|
+
`\nPlugins: ${plugins.length} known (${enabled} SoT-enabled) — details: docks-kit plugins list`,
|
|
174
|
+
);
|
|
175
|
+
const installed = skills.filter((s) => s.installed).length;
|
|
169
176
|
yield* Console.log(
|
|
170
|
-
`Skills: ${skills.length} known (${installed} installed) — details: docks-kit skills list
|
|
171
|
-
)
|
|
177
|
+
`Skills: ${skills.length} known (${installed} installed) — details: docks-kit skills list`,
|
|
178
|
+
);
|
|
172
179
|
}
|
|
173
180
|
|
|
174
181
|
if (diagnostics.length > 0) {
|
|
175
182
|
yield* Effect.sync(() => {
|
|
176
|
-
process.exitCode = diagnostics[0]?.exitCode ?? 1
|
|
177
|
-
})
|
|
183
|
+
process.exitCode = diagnostics[0]?.exitCode ?? 1;
|
|
184
|
+
});
|
|
178
185
|
}
|
|
179
|
-
})
|
|
186
|
+
}),
|
|
180
187
|
).pipe(
|
|
181
188
|
Command.withDescription(
|
|
182
|
-
"Doctor view: deployed-vs-SoT drift, toolchain, and plugin/skill counts."
|
|
183
|
-
)
|
|
184
|
-
)
|
|
189
|
+
"Doctor view: deployed-vs-SoT drift, toolchain, and plugin/skill counts.",
|
|
190
|
+
),
|
|
191
|
+
);
|
package/cli/src/commands/sync.ts
CHANGED
|
@@ -1,100 +1,126 @@
|
|
|
1
|
-
import { Argument, Command, Flag } from "effect/unstable/cli"
|
|
2
|
-
import { Effect, Option } from "effect"
|
|
3
|
-
import { spawnSync } from "node:child_process"
|
|
4
|
-
import { existsSync } from "node:fs"
|
|
5
|
-
import { join } from "node:path"
|
|
6
|
-
import { bail, engine } from "../engine"
|
|
7
|
-
import type { Logger } from "../engine-native/logger"
|
|
8
|
-
import { kitHome } from "../kitHome"
|
|
9
|
-
import { LoggerService } from "../services"
|
|
1
|
+
import { Argument, Command, Flag } from "effect/unstable/cli";
|
|
2
|
+
import { Effect, Option } from "effect";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { bail, engine } from "../engine";
|
|
7
|
+
import type { Logger } from "../engine-native/logger";
|
|
8
|
+
import { kitHome } from "../kitHome";
|
|
9
|
+
import { LoggerService } from "../services";
|
|
10
10
|
|
|
11
11
|
/** Best-effort update autodetection: nudge (never block, never fail) when
|
|
12
12
|
* the kit checkout is behind its upstream. Silent on detached HEADs, no
|
|
13
13
|
* upstream, no network, no git. */
|
|
14
14
|
const updateNudge = (logger: Logger): void => {
|
|
15
15
|
try {
|
|
16
|
-
const home = kitHome()
|
|
17
|
-
if (!existsSync(join(home, ".git"))) return
|
|
18
|
-
if (
|
|
16
|
+
const home = kitHome();
|
|
17
|
+
if (!existsSync(join(home, ".git"))) return;
|
|
18
|
+
if (
|
|
19
|
+
spawnSync("git", ["-C", home, "fetch", "--quiet"], { stdio: "ignore", timeout: 4000 })
|
|
20
|
+
.status !== 0
|
|
21
|
+
)
|
|
22
|
+
return;
|
|
19
23
|
const res = spawnSync("git", ["-C", home, "rev-list", "--count", "HEAD..@{u}"], {
|
|
20
24
|
encoding: "utf8",
|
|
21
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
22
|
-
})
|
|
23
|
-
const behind = (res.stdout ?? "").trim()
|
|
25
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
26
|
+
});
|
|
27
|
+
const behind = (res.stdout ?? "").trim();
|
|
24
28
|
if (res.status === 0 && behind !== "" && behind !== "0") {
|
|
25
|
-
logger.warn(
|
|
29
|
+
logger.warn(
|
|
30
|
+
`kit checkout is ${behind} commit(s) behind its upstream — run: docks-kit update`,
|
|
31
|
+
);
|
|
26
32
|
}
|
|
27
33
|
} catch {
|
|
28
34
|
// nudge only — a sync must never fail because the update check did
|
|
29
35
|
}
|
|
30
|
-
}
|
|
36
|
+
};
|
|
31
37
|
|
|
32
|
-
const VALID_TARGETS = ["claude", "codex", "agents", "omp"]
|
|
38
|
+
const VALID_TARGETS = ["claude", "codex", "agents", "omp"];
|
|
33
39
|
|
|
34
40
|
const targets: Argument.Argument<ReadonlyArray<string>> = Argument.String("target").pipe(
|
|
35
|
-
Argument.withDescription(
|
|
36
|
-
|
|
37
|
-
)
|
|
41
|
+
Argument.withDescription(
|
|
42
|
+
"Sync targets: claude, codex, agents, omp (default: selected harnesses)",
|
|
43
|
+
),
|
|
44
|
+
Argument.variadic(),
|
|
45
|
+
);
|
|
38
46
|
|
|
39
47
|
const dryRun = Flag.Boolean("dry-run").pipe(
|
|
40
48
|
Flag.withDescription("Preview without applying"),
|
|
41
|
-
Flag.withDefault(false)
|
|
42
|
-
)
|
|
49
|
+
Flag.withDefault(false),
|
|
50
|
+
);
|
|
43
51
|
const reconcile = Flag.Boolean("reconcile").pipe(
|
|
44
|
-
Flag.withDescription(
|
|
45
|
-
|
|
46
|
-
)
|
|
52
|
+
Flag.withDescription(
|
|
53
|
+
"Reconcile kit-owned settings with SoT (SoT keys win; user-only keys preserved; permissions arrays replaced)",
|
|
54
|
+
),
|
|
55
|
+
Flag.withDefault(false),
|
|
56
|
+
);
|
|
47
57
|
const prune = Flag.Boolean("prune").pipe(
|
|
48
|
-
Flag.withDescription(
|
|
49
|
-
|
|
50
|
-
)
|
|
58
|
+
Flag.withDescription(
|
|
59
|
+
"Uninstall kit-managed installs not in SoT (plugins, marketplaces, universal skills)",
|
|
60
|
+
),
|
|
61
|
+
Flag.withDefault(false),
|
|
62
|
+
);
|
|
51
63
|
const skipBubblewrap = Flag.Boolean("skip-bubblewrap").pipe(
|
|
52
64
|
Flag.withDescription("Skip optional bubblewrap bootstrap (Codex Linux sandbox)"),
|
|
53
|
-
Flag.withDefault(false)
|
|
54
|
-
)
|
|
65
|
+
Flag.withDefault(false),
|
|
66
|
+
);
|
|
55
67
|
const skipPluginRefresh = Flag.Boolean("skip-plugin-refresh").pipe(
|
|
56
|
-
Flag.withDescription(
|
|
57
|
-
|
|
58
|
-
)
|
|
68
|
+
Flag.withDescription(
|
|
69
|
+
"Install missing plugins but skip refresh-only updates for existing plugins",
|
|
70
|
+
),
|
|
71
|
+
Flag.withDefault(false),
|
|
72
|
+
);
|
|
59
73
|
const verbose = Flag.Boolean("verbose").pipe(
|
|
60
74
|
Flag.withAlias("v"),
|
|
61
75
|
Flag.withDescription("Also print no-op confirmations (already in sync, up to date, left as-is)"),
|
|
62
|
-
Flag.withDefault(false)
|
|
63
|
-
)
|
|
76
|
+
Flag.withDefault(false),
|
|
77
|
+
);
|
|
64
78
|
const claudeModel = Flag.String("claude-model").pipe(
|
|
65
|
-
Flag.withDescription(
|
|
66
|
-
|
|
67
|
-
)
|
|
79
|
+
Flag.withDescription(
|
|
80
|
+
"Deploy-time modifier: set deployed Claude model (see `docks-kit models claude`)",
|
|
81
|
+
),
|
|
82
|
+
Flag.optional,
|
|
83
|
+
);
|
|
68
84
|
const claudeEffort = Flag.String("claude-effort").pipe(
|
|
69
|
-
Flag.withDescription(
|
|
70
|
-
|
|
71
|
-
)
|
|
85
|
+
Flag.withDescription(
|
|
86
|
+
"Deploy-time modifier: set Claude effortLevel (bare flag shows valid levels)",
|
|
87
|
+
),
|
|
88
|
+
Flag.optional,
|
|
89
|
+
);
|
|
72
90
|
const claudeAdvisor = Flag.String("claude-advisor").pipe(
|
|
73
91
|
Flag.withDescription("Deploy-time modifier: set Claude advisor on/off/default"),
|
|
74
|
-
Flag.optional
|
|
75
|
-
)
|
|
92
|
+
Flag.optional,
|
|
93
|
+
);
|
|
76
94
|
const claudeCompactWindow = Flag.String("claude-compact-window").pipe(
|
|
77
|
-
Flag.withDescription(
|
|
78
|
-
|
|
79
|
-
)
|
|
95
|
+
Flag.withDescription(
|
|
96
|
+
"Deploy-time modifier: set deployed autocompact window in tokens (e.g. 680000 or 680k)",
|
|
97
|
+
),
|
|
98
|
+
Flag.optional,
|
|
99
|
+
);
|
|
80
100
|
const claudePermissive = Flag.Boolean("claude-permissive").pipe(
|
|
81
|
-
Flag.withDescription(
|
|
82
|
-
|
|
83
|
-
)
|
|
101
|
+
Flag.withDescription(
|
|
102
|
+
"Deploy-time modifier: empty permissions.ask/deny in deployed settings (sandboxes)",
|
|
103
|
+
),
|
|
104
|
+
Flag.withDefault(false),
|
|
105
|
+
);
|
|
84
106
|
const claudePlugin = Flag.String("claude-plugin").pipe(
|
|
85
107
|
Flag.withDescription(
|
|
86
|
-
"Sticky opt-in plugin(s); repeatable and/or comma-separated (known: supabase, n8n)"
|
|
108
|
+
"Sticky opt-in plugin(s); repeatable and/or comma-separated (known: supabase, n8n)",
|
|
87
109
|
),
|
|
88
|
-
Flag.atLeast(0)
|
|
89
|
-
)
|
|
110
|
+
Flag.atLeast(0),
|
|
111
|
+
);
|
|
90
112
|
const codexModel = Flag.String("codex-model").pipe(
|
|
91
|
-
Flag.withDescription(
|
|
92
|
-
|
|
93
|
-
)
|
|
113
|
+
Flag.withDescription(
|
|
114
|
+
"Deploy-time modifier: set deployed Codex model (see `docks-kit models codex`)",
|
|
115
|
+
),
|
|
116
|
+
Flag.optional,
|
|
117
|
+
);
|
|
94
118
|
const codexEffort = Flag.String("codex-effort").pipe(
|
|
95
|
-
Flag.withDescription(
|
|
96
|
-
|
|
97
|
-
)
|
|
119
|
+
Flag.withDescription(
|
|
120
|
+
"Deploy-time modifier: set Codex model_reasoning_effort (bare flag shows valid levels)",
|
|
121
|
+
),
|
|
122
|
+
Flag.optional,
|
|
123
|
+
);
|
|
98
124
|
|
|
99
125
|
export const syncCommand = Command.make(
|
|
100
126
|
"sync",
|
|
@@ -113,53 +139,53 @@ export const syncCommand = Command.make(
|
|
|
113
139
|
claudePermissive,
|
|
114
140
|
claudePlugin,
|
|
115
141
|
codexModel,
|
|
116
|
-
codexEffort
|
|
142
|
+
codexEffort,
|
|
117
143
|
},
|
|
118
144
|
(config) =>
|
|
119
145
|
Effect.gen(function* () {
|
|
120
|
-
const bad = config.targets.filter((t) => !VALID_TARGETS.includes(t))
|
|
146
|
+
const bad = config.targets.filter((t) => !VALID_TARGETS.includes(t));
|
|
121
147
|
if (bad.length > 0) {
|
|
122
148
|
return yield* bail(
|
|
123
|
-
`Unknown sync target(s): ${bad.join(", ")} (valid: ${VALID_TARGETS.join(", ")})
|
|
124
|
-
)
|
|
149
|
+
`Unknown sync target(s): ${bad.join(", ")} (valid: ${VALID_TARGETS.join(", ")})`,
|
|
150
|
+
);
|
|
125
151
|
}
|
|
126
152
|
|
|
127
|
-
const args: Array<string> = ["sync", ...config.targets]
|
|
128
|
-
if (config.dryRun) args.push("--dry-run")
|
|
129
|
-
if (config.reconcile) args.push("--reconcile")
|
|
130
|
-
if (config.prune) args.push("--prune")
|
|
131
|
-
if (config.skipBubblewrap) args.push("--skip-bubblewrap")
|
|
132
|
-
if (config.skipPluginRefresh) args.push("--skip-plugin-refresh")
|
|
133
|
-
if (config.verbose) args.push("--verbose")
|
|
134
|
-
if (config.claudePermissive) args.push("--claude-permissive")
|
|
135
|
-
Option.map(config.claudeModel, (m) => args.push(`--claude-model=${m}`))
|
|
136
|
-
Option.map(config.claudeEffort, (level) => args.push(`--claude-effort=${level}`))
|
|
137
|
-
Option.map(config.claudeAdvisor, (state) => args.push(`--claude-advisor=${state}`))
|
|
138
|
-
Option.map(config.claudeCompactWindow, (w) => args.push(`--claude-compact-window=${w}`))
|
|
139
|
-
Option.map(config.codexModel, (m) => args.push(`--codex-model=${m}`))
|
|
140
|
-
Option.map(config.codexEffort, (level) => args.push(`--codex-effort=${level}`))
|
|
153
|
+
const args: Array<string> = ["sync", ...config.targets];
|
|
154
|
+
if (config.dryRun) args.push("--dry-run");
|
|
155
|
+
if (config.reconcile) args.push("--reconcile");
|
|
156
|
+
if (config.prune) args.push("--prune");
|
|
157
|
+
if (config.skipBubblewrap) args.push("--skip-bubblewrap");
|
|
158
|
+
if (config.skipPluginRefresh) args.push("--skip-plugin-refresh");
|
|
159
|
+
if (config.verbose) args.push("--verbose");
|
|
160
|
+
if (config.claudePermissive) args.push("--claude-permissive");
|
|
161
|
+
Option.map(config.claudeModel, (m) => args.push(`--claude-model=${m}`));
|
|
162
|
+
Option.map(config.claudeEffort, (level) => args.push(`--claude-effort=${level}`));
|
|
163
|
+
Option.map(config.claudeAdvisor, (state) => args.push(`--claude-advisor=${state}`));
|
|
164
|
+
Option.map(config.claudeCompactWindow, (w) => args.push(`--claude-compact-window=${w}`));
|
|
165
|
+
Option.map(config.codexModel, (m) => args.push(`--codex-model=${m}`));
|
|
166
|
+
Option.map(config.codexEffort, (level) => args.push(`--codex-effort=${level}`));
|
|
141
167
|
for (const occurrence of config.claudePlugin) {
|
|
142
168
|
if (occurrence.trim() === "") {
|
|
143
|
-
args.push("--claude-plugin=")
|
|
144
|
-
continue
|
|
169
|
+
args.push("--claude-plugin=");
|
|
170
|
+
continue;
|
|
145
171
|
}
|
|
146
172
|
occurrence
|
|
147
173
|
.split(",")
|
|
148
174
|
.map((p) => p.trim())
|
|
149
175
|
.filter((p) => p.length > 0)
|
|
150
|
-
.forEach((p) => args.push(`--claude-plugin=${p}`))
|
|
176
|
+
.forEach((p) => args.push(`--claude-plugin=${p}`));
|
|
151
177
|
}
|
|
152
178
|
|
|
153
179
|
// Not on --dry-run: the nudge's git fetch writes FETCH_HEAD/remote
|
|
154
180
|
// refs, and a preview command must not mutate the checkout.
|
|
155
181
|
if (!config.dryRun) {
|
|
156
|
-
const logger = yield* LoggerService
|
|
157
|
-
yield* Effect.sync(() => updateNudge(logger))
|
|
182
|
+
const logger = yield* LoggerService;
|
|
183
|
+
yield* Effect.sync(() => updateNudge(logger));
|
|
158
184
|
}
|
|
159
|
-
yield* engine(args)
|
|
160
|
-
})
|
|
185
|
+
yield* engine(args);
|
|
186
|
+
}),
|
|
161
187
|
).pipe(
|
|
162
188
|
Command.withDescription(
|
|
163
|
-
"Deploy the SoT to this machine with EngineNative. Deploy-time modifiers touch deployed config only; a later flag-less sync reverts them to SoT."
|
|
164
|
-
)
|
|
165
|
-
)
|
|
189
|
+
"Deploy the SoT to this machine with EngineNative. Deploy-time modifiers touch deployed config only; a later flag-less sync reverts them to SoT.",
|
|
190
|
+
),
|
|
191
|
+
);
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import { Argument, Command, Flag } from "effect/unstable/cli"
|
|
2
|
-
import { Effect, Option } from "effect"
|
|
3
|
-
import { bail, engine } from "../engine"
|
|
1
|
+
import { Argument, Command, Flag } from "effect/unstable/cli";
|
|
2
|
+
import { Effect, Option } from "effect";
|
|
3
|
+
import { bail, engine } from "../engine";
|
|
4
4
|
|
|
5
|
-
const MANAGED = ["bun"]
|
|
5
|
+
const MANAGED = ["bun"];
|
|
6
6
|
|
|
7
7
|
const op = Argument.String("op").pipe(
|
|
8
8
|
Argument.withDescription("check (default) | ensure <tool>"),
|
|
9
|
-
Argument.optional
|
|
10
|
-
)
|
|
9
|
+
Argument.optional,
|
|
10
|
+
);
|
|
11
11
|
const tool = Argument.String("tool").pipe(
|
|
12
12
|
Argument.withDescription(`Managed tool for ensure: ${MANAGED.join(", ")}`),
|
|
13
|
-
Argument.optional
|
|
14
|
-
)
|
|
13
|
+
Argument.optional,
|
|
14
|
+
);
|
|
15
15
|
const verbose = Flag.Boolean("verbose").pipe(
|
|
16
16
|
Flag.withAlias("v"),
|
|
17
17
|
Flag.withDescription("Also print no-op confirmations (present, up to date)"),
|
|
18
|
-
Flag.withDefault(false)
|
|
19
|
-
)
|
|
18
|
+
Flag.withDefault(false),
|
|
19
|
+
);
|
|
20
20
|
|
|
21
21
|
export const toolchainCommand = Command.make("toolchain", { op, tool, verbose }, (config) =>
|
|
22
22
|
Effect.gen(function* () {
|
|
23
|
-
const operation = Option.getOrElse(config.op, () => "check")
|
|
24
|
-
const flags = config.verbose ? ["--verbose"] : []
|
|
23
|
+
const operation = Option.getOrElse(config.op, () => "check");
|
|
24
|
+
const flags = config.verbose ? ["--verbose"] : [];
|
|
25
25
|
|
|
26
26
|
switch (operation) {
|
|
27
27
|
case "check":
|
|
28
|
-
return yield* engine(["toolchain", "check", ...(config.verbose ? ["--verbose"] : [])])
|
|
28
|
+
return yield* engine(["toolchain", "check", ...(config.verbose ? ["--verbose"] : [])]);
|
|
29
29
|
case "ensure": {
|
|
30
|
-
const t = Option.getOrUndefined(config.tool)
|
|
30
|
+
const t = Option.getOrUndefined(config.tool);
|
|
31
31
|
if (t === undefined || !MANAGED.includes(t)) {
|
|
32
|
-
return yield* bail(`toolchain ensure needs a managed tool: ${MANAGED.join(", ")}`)
|
|
32
|
+
return yield* bail(`toolchain ensure needs a managed tool: ${MANAGED.join(", ")}`);
|
|
33
33
|
}
|
|
34
|
-
return yield* engine(["toolchain", "ensure", t, ...flags])
|
|
34
|
+
return yield* engine(["toolchain", "ensure", t, ...flags]);
|
|
35
35
|
}
|
|
36
36
|
default:
|
|
37
|
-
return yield* bail(`Unknown toolchain op '${operation}' (valid: check, ensure)`)
|
|
37
|
+
return yield* bail(`Unknown toolchain op '${operation}' (valid: check, ensure)`);
|
|
38
38
|
}
|
|
39
|
-
})
|
|
39
|
+
}),
|
|
40
40
|
).pipe(
|
|
41
41
|
Command.withDescription(
|
|
42
|
-
"Verified-version floors for external tools (SoT/toolchain.json): check prints the doctor table; ensure installs one managed tool when it is missing."
|
|
43
|
-
)
|
|
44
|
-
)
|
|
42
|
+
"Verified-version floors for external tools (SoT/toolchain.json): check prints the doctor table; ensure installs one managed tool when it is missing.",
|
|
43
|
+
),
|
|
44
|
+
);
|