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,445 +1,195 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* EngineNative flag layer:
|
|
3
|
-
*
|
|
4
|
-
* early
|
|
2
|
+
* EngineNative flag layer: target selection and the argv dispatch loop.
|
|
3
|
+
* Modifier/effort mapping lives in parseModifiers.ts; help text and the
|
|
4
|
+
* early-exit error live in parseHelp.ts (re-exported here so existing
|
|
5
|
+
* `from "./parseArgs"` imports keep working).
|
|
5
6
|
*/
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
7
|
+
import type { Ctx } from "./index";
|
|
8
|
+
import { LEGACY_SELECTION, readHarnessSelection, type Harness } from "./harnesses";
|
|
9
|
+
import { advisorCatalog, advisorFlagGrammar, effortCatalog, effortFlagGrammar } from "../efforts";
|
|
10
|
+
import { printModels } from "./models";
|
|
11
|
+
import { ExitError, printCatalog, printUsage } from "./parseHelp";
|
|
9
12
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} from "
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
export const KNOWN_CLAUDE_OPTIN_PLUGINS = ["supabase", "n8n"]
|
|
28
|
-
|
|
29
|
-
interface ModifierMetadata {
|
|
30
|
-
readonly target: "claude" | "codex"
|
|
31
|
-
readonly ignoredWarning: string
|
|
32
|
-
readonly hasValue: (ctx: Ctx) => boolean
|
|
33
|
-
readonly clear: (ctx: Ctx) => void
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const MODIFIER_METADATA = {
|
|
37
|
-
"--claude-model": {
|
|
38
|
-
target: "claude",
|
|
39
|
-
ignoredWarning: "--claude-model ignored: claude target not selected",
|
|
40
|
-
hasValue: (ctx) => ctx.claudeModel !== "",
|
|
41
|
-
clear: (ctx) => {
|
|
42
|
-
ctx.claudeModel = ""
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
"--claude-effort": {
|
|
46
|
-
target: "claude",
|
|
47
|
-
ignoredWarning: "--claude-effort ignored: claude target not selected",
|
|
48
|
-
hasValue: (ctx) => ctx.claudeEffort !== "",
|
|
49
|
-
clear: (ctx) => {
|
|
50
|
-
ctx.claudeEffort = ""
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
"--claude-advisor": {
|
|
54
|
-
target: "claude",
|
|
55
|
-
ignoredWarning: "--claude-advisor ignored: claude target not selected",
|
|
56
|
-
hasValue: (ctx) => ctx.claudeAdvisor !== "",
|
|
57
|
-
clear: (ctx) => {
|
|
58
|
-
ctx.claudeAdvisor = ""
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
"--claude-compact-window": {
|
|
62
|
-
target: "claude",
|
|
63
|
-
ignoredWarning: "--claude-compact-window ignored: claude target not selected",
|
|
64
|
-
hasValue: (ctx) => ctx.claudeCompactWindow !== "",
|
|
65
|
-
clear: (ctx) => {
|
|
66
|
-
ctx.claudeCompactWindow = ""
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
"--claude-permissive": {
|
|
70
|
-
target: "claude",
|
|
71
|
-
ignoredWarning: "--claude-permissive ignored: claude target not selected",
|
|
72
|
-
hasValue: (ctx) => ctx.claudePermissive,
|
|
73
|
-
clear: (ctx) => {
|
|
74
|
-
ctx.claudePermissive = false
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
"--claude-plugin": {
|
|
78
|
-
target: "claude",
|
|
79
|
-
ignoredWarning: "--claude-plugin ignored: claude target not selected",
|
|
80
|
-
hasValue: (ctx) => ctx.claudePlugins.length > 0,
|
|
81
|
-
clear: (ctx) => {
|
|
82
|
-
ctx.claudePlugins = []
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
"--codex-model": {
|
|
86
|
-
target: "codex",
|
|
87
|
-
ignoredWarning: "--codex-model ignored: codex target not selected",
|
|
88
|
-
hasValue: (ctx) => ctx.codexModel !== "",
|
|
89
|
-
clear: (ctx) => {
|
|
90
|
-
ctx.codexModel = ""
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
"--codex-effort": {
|
|
94
|
-
target: "codex",
|
|
95
|
-
ignoredWarning: "--codex-effort ignored: codex target not selected",
|
|
96
|
-
hasValue: (ctx) => ctx.codexEffort !== "",
|
|
97
|
-
clear: (ctx) => {
|
|
98
|
-
ctx.codexEffort = ""
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
} satisfies Record<ModifierFlag, ModifierMetadata>
|
|
102
|
-
|
|
103
|
-
type ScalarModifierFlag =
|
|
104
|
-
| "--claude-model"
|
|
105
|
-
| "--claude-effort"
|
|
106
|
-
| "--claude-advisor"
|
|
107
|
-
| "--codex-model"
|
|
108
|
-
| "--codex-effort"
|
|
109
|
-
|
|
110
|
-
const SCALAR_MODIFIER_FLAGS: Record<ScalarModifierFlag, true> = {
|
|
111
|
-
"--claude-model": true,
|
|
112
|
-
"--claude-effort": true,
|
|
113
|
-
"--claude-advisor": true,
|
|
114
|
-
"--codex-model": true,
|
|
115
|
-
"--codex-effort": true
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
function usage(ctx: Ctx): void {
|
|
120
|
-
const { echo } = ctx.services.logger
|
|
121
|
-
const argv0 = "docks-kit sync"
|
|
122
|
-
echo(`Usage: ${argv0} [claude] [codex] [agents] [omp] [flags]`)
|
|
123
|
-
echo("")
|
|
124
|
-
echo("Targets (positional; default: this machine's harness selection)")
|
|
125
|
-
echo(" claude sync the Claude Code SoT")
|
|
126
|
-
echo(" codex sync the Codex SoT")
|
|
127
|
-
echo(" agents sync universal agent skills")
|
|
128
|
-
echo(" omp sync the Oh My Pi SoT")
|
|
129
|
-
echo("")
|
|
130
|
-
echo("Global flags")
|
|
131
|
-
echo(" --dry-run preview without applying")
|
|
132
|
-
echo(
|
|
133
|
-
" --reconcile reconcile kit-owned settings with SoT (SoT keys win; user-only keys preserved; permissions arrays replaced)"
|
|
134
|
-
)
|
|
135
|
-
echo(
|
|
136
|
-
" --prune uninstall kit-managed installs not in SoT (plugins, marketplaces, skills in SoT/.agents/skills.txt)"
|
|
137
|
-
)
|
|
138
|
-
echo(" --skip-bubblewrap skip optional bubblewrap bootstrap (Codex Linux sandbox)")
|
|
139
|
-
echo(" --skip-plugin-refresh install missing plugins but skip refresh-only updates")
|
|
140
|
-
echo(" --verbose also print no-op confirmations (already in sync, up to date, left as-is)")
|
|
141
|
-
echo("")
|
|
142
|
-
echo("Deploy-time modifiers (deployed config only; SoT untouched; a later flag-less sync reverts)")
|
|
143
|
-
echo(
|
|
144
|
-
" --claude-model=<m> set deployed ~/.claude/settings.json model (aliases: best|opus|fable|sonnet|haiku, full claude-* IDs, or 'default' to unset)"
|
|
145
|
-
)
|
|
146
|
-
echo(` ${effortFlagGrammar("claude").padEnd(39)} set deployed effortLevel`)
|
|
147
|
-
echo(` ${advisorFlagGrammar().padEnd(39)} set deployed advisor state`)
|
|
148
|
-
echo(
|
|
149
|
-
" --claude-compact-window=<n> set deployed autocompact window in tokens (e.g. 680000 or 680k) for disposable sessions"
|
|
150
|
-
)
|
|
151
|
-
echo(
|
|
152
|
-
" --claude-permissive empty permissions.ask/deny in deployed settings (sandboxes/containers; unattended commits + pushes)"
|
|
153
|
-
)
|
|
154
|
-
echo(" --codex-model=<m> set deployed ~/.codex/config.toml model (e.g. gpt-5.5)")
|
|
155
|
-
echo(` ${effortFlagGrammar("codex").padEnd(39)} set deployed model_reasoning_effort`)
|
|
156
|
-
echo("")
|
|
157
|
-
echo("Sticky opt-ins (installed + enabled until --prune)")
|
|
158
|
-
echo(
|
|
159
|
-
` --claude-plugin=<name> opt an optional plugin into this machine (known: ${KNOWN_CLAUDE_OPTIN_PLUGINS.join(", ")}; repeatable)`
|
|
160
|
-
)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/** common::parse_compact_window — normalized tokens or undefined on junk. */
|
|
164
|
-
export function parseCompactWindow(v: string): string | undefined {
|
|
165
|
-
if (/[kK]$/.test(v)) {
|
|
166
|
-
const n = v.slice(0, -1)
|
|
167
|
-
if (!/^[0-9]+$/.test(n)) return undefined
|
|
168
|
-
return String(parseInt(n, 10) * 1000)
|
|
169
|
-
}
|
|
170
|
-
return /^[0-9]+$/.test(v) ? v : undefined
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export function parseClaudePlugin(name: string, err: (message: string) => void): string {
|
|
174
|
-
if (!KNOWN_CLAUDE_OPTIN_PLUGINS.includes(name)) {
|
|
175
|
-
err(`Unknown opt-in plugin '${name}'. Known: ${KNOWN_CLAUDE_OPTIN_PLUGINS.join(", ")}`)
|
|
176
|
-
throw new ExitError(2)
|
|
177
|
-
}
|
|
178
|
-
return name
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function markModifier(ctx: Ctx, flag: ModifierFlag): void {
|
|
182
|
-
const flags = ctx.modifierFlags ?? new Set<ModifierFlag>()
|
|
183
|
-
flags.add(flag)
|
|
184
|
-
ctx.modifierFlags = flags
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function addClaudePlugin(ctx: Ctx, name: string): void {
|
|
188
|
-
if (name === "") {
|
|
189
|
-
printCatalog(
|
|
190
|
-
ctx,
|
|
191
|
-
`Available Claude optional plugins:\n${KNOWN_CLAUDE_OPTIN_PLUGINS.map((plugin) => ` ${plugin}`).join("\n")}`
|
|
192
|
-
)
|
|
193
|
-
ctx.services.logger.err(
|
|
194
|
-
`Invalid Claude plugin '' — valid: ${KNOWN_CLAUDE_OPTIN_PLUGINS.join("|")}`
|
|
195
|
-
)
|
|
196
|
-
throw new ExitError(2)
|
|
197
|
-
}
|
|
198
|
-
ctx.claudePlugins.push(parseClaudePlugin(name, ctx.services.logger.err))
|
|
199
|
-
markModifier(ctx, "--claude-plugin")
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
type TargetFlag = "syncClaude" | "syncCodex" | "syncAgents" | "syncOmp"
|
|
13
|
+
KNOWN_CLAUDE_OPTIN_PLUGINS,
|
|
14
|
+
addClaudePlugin,
|
|
15
|
+
isScalarModifierFlag,
|
|
16
|
+
markModifier,
|
|
17
|
+
parseCompactWindow,
|
|
18
|
+
setModifier,
|
|
19
|
+
} from "./parseModifiers";
|
|
20
|
+
|
|
21
|
+
export { ExitError } from "./parseHelp";
|
|
22
|
+
export {
|
|
23
|
+
KNOWN_CLAUDE_OPTIN_PLUGINS,
|
|
24
|
+
parseClaudePlugin,
|
|
25
|
+
parseCompactWindow,
|
|
26
|
+
validateModifierFlags,
|
|
27
|
+
} from "./parseModifiers";
|
|
28
|
+
|
|
29
|
+
type TargetFlag = "syncClaude" | "syncCodex" | "syncAgents" | "syncOmp";
|
|
203
30
|
|
|
204
31
|
const TARGET_FLAGS = {
|
|
205
32
|
claude: "syncClaude",
|
|
206
33
|
codex: "syncCodex",
|
|
207
34
|
agents: "syncAgents",
|
|
208
|
-
omp: "syncOmp"
|
|
209
|
-
} satisfies Record<Harness, TargetFlag
|
|
35
|
+
omp: "syncOmp",
|
|
36
|
+
} satisfies Record<Harness, TargetFlag>;
|
|
210
37
|
|
|
211
38
|
function selectTarget(ctx: Ctx, target: Harness): void {
|
|
212
|
-
ctx[TARGET_FLAGS[target]] = true
|
|
213
|
-
ctx.targetFilterSet = true
|
|
39
|
+
ctx[TARGET_FLAGS[target]] = true;
|
|
40
|
+
ctx.targetFilterSet = true;
|
|
214
41
|
}
|
|
215
42
|
|
|
216
43
|
function applySelection(ctx: Ctx, selection: ReadonlyArray<Harness>): void {
|
|
217
|
-
ctx.syncClaude = selection.includes("claude")
|
|
218
|
-
ctx.syncCodex = selection.includes("codex")
|
|
219
|
-
ctx.syncAgents = selection.includes("agents")
|
|
220
|
-
ctx.syncOmp = selection.includes("omp")
|
|
44
|
+
ctx.syncClaude = selection.includes("claude");
|
|
45
|
+
ctx.syncCodex = selection.includes("codex");
|
|
46
|
+
ctx.syncAgents = selection.includes("agents");
|
|
47
|
+
ctx.syncOmp = selection.includes("omp");
|
|
221
48
|
}
|
|
222
49
|
|
|
223
50
|
function applyDefaultSelection(ctx: Ctx): void {
|
|
224
|
-
if (ctx.targetFilterSet) return
|
|
225
|
-
|
|
226
|
-
const storedSelection = readHarnessSelection(ctx.home)
|
|
227
|
-
applySelection(ctx, storedSelection ?? LEGACY_SELECTION)
|
|
228
|
-
if (storedSelection !== undefined || !ctx.interactive) return
|
|
51
|
+
if (ctx.targetFilterSet) return;
|
|
229
52
|
|
|
230
|
-
|
|
231
|
-
ctx
|
|
232
|
-
|
|
53
|
+
const storedSelection = readHarnessSelection(ctx.home);
|
|
54
|
+
applySelection(ctx, storedSelection ?? LEGACY_SELECTION);
|
|
55
|
+
if (storedSelection !== undefined || !ctx.interactive) return;
|
|
233
56
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
case "--claude-model":
|
|
237
|
-
ctx.claudeModel = value
|
|
238
|
-
break
|
|
239
|
-
case "--claude-effort":
|
|
240
|
-
ctx.claudeEffort = value
|
|
241
|
-
break
|
|
242
|
-
case "--claude-advisor":
|
|
243
|
-
ctx.claudeAdvisor = value
|
|
244
|
-
break
|
|
245
|
-
case "--codex-model":
|
|
246
|
-
ctx.codexModel = value
|
|
247
|
-
break
|
|
248
|
-
case "--codex-effort":
|
|
249
|
-
ctx.codexEffort = value
|
|
250
|
-
break
|
|
251
|
-
}
|
|
252
|
-
markModifier(ctx, flag)
|
|
57
|
+
ctx.services.logger.echo("No harness selection stored; syncing claude, codex, agents");
|
|
58
|
+
ctx.services.logger.echo("Choose harnesses with: docks-kit harnesses");
|
|
253
59
|
}
|
|
254
60
|
|
|
255
|
-
function isScalarModifierFlag(value: string): value is ScalarModifierFlag {
|
|
256
|
-
return SCALAR_MODIFIER_FLAGS[value as ScalarModifierFlag] === true
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
|
|
260
61
|
export function parseArgs(ctx: Ctx, args: ReadonlyArray<string>): void {
|
|
261
|
-
const { err } = ctx.services.logger
|
|
62
|
+
const { err } = ctx.services.logger;
|
|
262
63
|
for (let index = 0; index < args.length; index += 1) {
|
|
263
|
-
const arg = args[index] ?? ""
|
|
64
|
+
const arg = args[index] ?? "";
|
|
264
65
|
if (isScalarModifierFlag(arg) && args[index + 1] === "") {
|
|
265
|
-
setModifier(ctx, arg, "")
|
|
266
|
-
index += 1
|
|
267
|
-
continue
|
|
66
|
+
setModifier(ctx, arg, "");
|
|
67
|
+
index += 1;
|
|
68
|
+
continue;
|
|
268
69
|
}
|
|
269
70
|
switch (arg) {
|
|
270
71
|
case "claude":
|
|
271
72
|
case "codex":
|
|
272
73
|
case "agents":
|
|
273
74
|
case "omp":
|
|
274
|
-
selectTarget(ctx, arg)
|
|
275
|
-
continue
|
|
75
|
+
selectTarget(ctx, arg);
|
|
76
|
+
continue;
|
|
276
77
|
case "--dry-run":
|
|
277
|
-
ctx.dryRun = true
|
|
278
|
-
continue
|
|
78
|
+
ctx.dryRun = true;
|
|
79
|
+
continue;
|
|
279
80
|
case "--skip-bubblewrap":
|
|
280
|
-
ctx.skipBubblewrap = true
|
|
281
|
-
continue
|
|
81
|
+
ctx.skipBubblewrap = true;
|
|
82
|
+
continue;
|
|
282
83
|
case "--skip-plugin-refresh":
|
|
283
|
-
ctx.skipPluginRefresh = true
|
|
284
|
-
continue
|
|
84
|
+
ctx.skipPluginRefresh = true;
|
|
85
|
+
continue;
|
|
285
86
|
case "--reconcile":
|
|
286
|
-
ctx.reconcile = true
|
|
287
|
-
continue
|
|
87
|
+
ctx.reconcile = true;
|
|
88
|
+
continue;
|
|
288
89
|
case "--prune":
|
|
289
|
-
ctx.prune = true
|
|
290
|
-
continue
|
|
90
|
+
ctx.prune = true;
|
|
91
|
+
continue;
|
|
291
92
|
case "--verbose":
|
|
292
|
-
ctx.verbose = true
|
|
293
|
-
continue
|
|
93
|
+
ctx.verbose = true;
|
|
94
|
+
continue;
|
|
294
95
|
case "--claude-model":
|
|
295
|
-
printModels(ctx, "claude")
|
|
296
|
-
err("--claude-model requires a value: --claude-model=<model>")
|
|
297
|
-
throw new ExitError(2)
|
|
96
|
+
printModels(ctx, "claude");
|
|
97
|
+
err("--claude-model requires a value: --claude-model=<model>");
|
|
98
|
+
throw new ExitError(2);
|
|
298
99
|
case "--codex-model":
|
|
299
|
-
printModels(ctx, "codex")
|
|
300
|
-
err("--codex-model requires a value: --codex-model=<model>")
|
|
301
|
-
throw new ExitError(2)
|
|
100
|
+
printModels(ctx, "codex");
|
|
101
|
+
err("--codex-model requires a value: --codex-model=<model>");
|
|
102
|
+
throw new ExitError(2);
|
|
302
103
|
case "--claude-effort":
|
|
303
|
-
printCatalog(ctx, effortCatalog("claude"))
|
|
304
|
-
err(`--claude-effort requires a value: ${effortFlagGrammar("claude")}`)
|
|
305
|
-
throw new ExitError(2)
|
|
104
|
+
printCatalog(ctx, effortCatalog("claude"));
|
|
105
|
+
err(`--claude-effort requires a value: ${effortFlagGrammar("claude")}`);
|
|
106
|
+
throw new ExitError(2);
|
|
306
107
|
case "--codex-effort":
|
|
307
|
-
printCatalog(ctx, effortCatalog("codex"))
|
|
308
|
-
err(`--codex-effort requires a value: ${effortFlagGrammar("codex")}`)
|
|
309
|
-
throw new ExitError(2)
|
|
108
|
+
printCatalog(ctx, effortCatalog("codex"));
|
|
109
|
+
err(`--codex-effort requires a value: ${effortFlagGrammar("codex")}`);
|
|
110
|
+
throw new ExitError(2);
|
|
310
111
|
case "--claude-advisor":
|
|
311
|
-
printCatalog(ctx, advisorCatalog())
|
|
312
|
-
err(`--claude-advisor requires a value: ${advisorFlagGrammar()}`)
|
|
313
|
-
throw new ExitError(2)
|
|
112
|
+
printCatalog(ctx, advisorCatalog());
|
|
113
|
+
err(`--claude-advisor requires a value: ${advisorFlagGrammar()}`);
|
|
114
|
+
throw new ExitError(2);
|
|
314
115
|
case "--claude-compact-window":
|
|
315
|
-
err(
|
|
316
|
-
|
|
116
|
+
err(
|
|
117
|
+
"--claude-compact-window requires a value: --claude-compact-window=<tokens> (e.g. 680k)",
|
|
118
|
+
);
|
|
119
|
+
throw new ExitError(2);
|
|
317
120
|
case "--claude-permissive":
|
|
318
|
-
ctx.claudePermissive = true
|
|
319
|
-
markModifier(ctx, "--claude-permissive")
|
|
320
|
-
continue
|
|
121
|
+
ctx.claudePermissive = true;
|
|
122
|
+
markModifier(ctx, "--claude-permissive");
|
|
123
|
+
continue;
|
|
321
124
|
case "--claude-plugin":
|
|
322
|
-
err(
|
|
323
|
-
|
|
125
|
+
err(
|
|
126
|
+
`--claude-plugin requires a value: --claude-plugin=<${KNOWN_CLAUDE_OPTIN_PLUGINS.join("|")}>`,
|
|
127
|
+
);
|
|
128
|
+
throw new ExitError(2);
|
|
324
129
|
case "--claude":
|
|
325
130
|
case "--codex":
|
|
326
131
|
case "--agents":
|
|
327
132
|
case "--omp":
|
|
328
|
-
err(`${arg} was renamed: pass the target as a word, e.g. 'sync ${arg.slice(2)}'`)
|
|
329
|
-
throw new ExitError(2)
|
|
133
|
+
err(`${arg} was renamed: pass the target as a word, e.g. 'sync ${arg.slice(2)}'`);
|
|
134
|
+
throw new ExitError(2);
|
|
330
135
|
case "--force":
|
|
331
|
-
err("--force was renamed to --reconcile")
|
|
332
|
-
throw new ExitError(2)
|
|
136
|
+
err("--force was renamed to --reconcile");
|
|
137
|
+
throw new ExitError(2);
|
|
333
138
|
case "--remove-plugins":
|
|
334
|
-
err(
|
|
335
|
-
|
|
139
|
+
err(
|
|
140
|
+
"--remove-plugins was renamed to --prune (it also removes marketplaces + kit-managed skills)",
|
|
141
|
+
);
|
|
142
|
+
throw new ExitError(2);
|
|
336
143
|
case "--680k":
|
|
337
|
-
err("--680k was renamed to --claude-compact-window=680k")
|
|
338
|
-
throw new ExitError(2)
|
|
144
|
+
err("--680k was renamed to --claude-compact-window=680k");
|
|
145
|
+
throw new ExitError(2);
|
|
339
146
|
case "--permissive":
|
|
340
|
-
err("--permissive was renamed to --claude-permissive")
|
|
341
|
-
throw new ExitError(2)
|
|
147
|
+
err("--permissive was renamed to --claude-permissive");
|
|
148
|
+
throw new ExitError(2);
|
|
342
149
|
case "--supabase":
|
|
343
|
-
err("--supabase was renamed to --claude-plugin=supabase")
|
|
344
|
-
throw new ExitError(2)
|
|
150
|
+
err("--supabase was renamed to --claude-plugin=supabase");
|
|
151
|
+
throw new ExitError(2);
|
|
345
152
|
case "--n8n":
|
|
346
|
-
err("--n8n was renamed to --claude-plugin=n8n")
|
|
347
|
-
throw new ExitError(2)
|
|
153
|
+
err("--n8n was renamed to --claude-plugin=n8n");
|
|
154
|
+
throw new ExitError(2);
|
|
348
155
|
case "--skip-rtk":
|
|
349
|
-
err("--skip-rtk was renamed to --skip-bubblewrap")
|
|
350
|
-
throw new ExitError(2)
|
|
156
|
+
err("--skip-rtk was renamed to --skip-bubblewrap");
|
|
157
|
+
throw new ExitError(2);
|
|
351
158
|
case "-h":
|
|
352
159
|
case "--help":
|
|
353
|
-
|
|
354
|
-
throw new ExitError(0)
|
|
160
|
+
printUsage(ctx, KNOWN_CLAUDE_OPTIN_PLUGINS);
|
|
161
|
+
throw new ExitError(0);
|
|
355
162
|
default:
|
|
356
|
-
break
|
|
163
|
+
break;
|
|
357
164
|
}
|
|
358
165
|
if (arg.startsWith("--claude-model=")) {
|
|
359
|
-
setModifier(ctx, "--claude-model", arg.slice("--claude-model=".length))
|
|
166
|
+
setModifier(ctx, "--claude-model", arg.slice("--claude-model=".length));
|
|
360
167
|
} else if (arg.startsWith("--codex-model=")) {
|
|
361
|
-
setModifier(ctx, "--codex-model", arg.slice("--codex-model=".length))
|
|
168
|
+
setModifier(ctx, "--codex-model", arg.slice("--codex-model=".length));
|
|
362
169
|
} else if (arg.startsWith("--claude-effort=")) {
|
|
363
|
-
setModifier(ctx, "--claude-effort", arg.slice("--claude-effort=".length))
|
|
170
|
+
setModifier(ctx, "--claude-effort", arg.slice("--claude-effort=".length));
|
|
364
171
|
} else if (arg.startsWith("--codex-effort=")) {
|
|
365
|
-
setModifier(ctx, "--codex-effort", arg.slice("--codex-effort=".length))
|
|
172
|
+
setModifier(ctx, "--codex-effort", arg.slice("--codex-effort=".length));
|
|
366
173
|
} else if (arg.startsWith("--claude-advisor=")) {
|
|
367
|
-
setModifier(ctx, "--claude-advisor", arg.slice("--claude-advisor=".length))
|
|
174
|
+
setModifier(ctx, "--claude-advisor", arg.slice("--claude-advisor=".length));
|
|
368
175
|
} else if (arg.startsWith("--claude-compact-window=")) {
|
|
369
|
-
const parsed = parseCompactWindow(arg.slice("--claude-compact-window=".length))
|
|
176
|
+
const parsed = parseCompactWindow(arg.slice("--claude-compact-window=".length));
|
|
370
177
|
if (parsed === undefined) {
|
|
371
|
-
err("--claude-compact-window expects a token count (e.g. 680000 or 680k)")
|
|
372
|
-
throw new ExitError(2)
|
|
178
|
+
err("--claude-compact-window expects a token count (e.g. 680000 or 680k)");
|
|
179
|
+
throw new ExitError(2);
|
|
373
180
|
}
|
|
374
|
-
ctx.claudeCompactWindow = parsed
|
|
375
|
-
markModifier(ctx, "--claude-compact-window")
|
|
181
|
+
ctx.claudeCompactWindow = parsed;
|
|
182
|
+
markModifier(ctx, "--claude-compact-window");
|
|
376
183
|
} else if (arg.startsWith("--claude-plugin=")) {
|
|
377
|
-
addClaudePlugin(ctx, arg.slice("--claude-plugin=".length))
|
|
184
|
+
addClaudePlugin(ctx, arg.slice("--claude-plugin=".length));
|
|
378
185
|
} else if (arg.startsWith("--claude-permissive=")) {
|
|
379
|
-
err("--claude-permissive does not take a value")
|
|
380
|
-
throw new ExitError(2)
|
|
186
|
+
err("--claude-permissive does not take a value");
|
|
187
|
+
throw new ExitError(2);
|
|
381
188
|
} else {
|
|
382
|
-
err(`Unknown arg: ${arg}`)
|
|
383
|
-
throw new ExitError(2)
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
applyDefaultSelection(ctx)
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
function printCatalog(ctx: Ctx, catalog: string): void {
|
|
391
|
-
for (const line of catalog.split("\n")) ctx.services.logger.echo(line)
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
export function validateModifierFlags(ctx: Ctx): void {
|
|
396
|
-
const { err, warn } = ctx.services.logger
|
|
397
|
-
const supplied = (flag: ModifierFlag): boolean =>
|
|
398
|
-
MODIFIER_METADATA[flag].hasValue(ctx) || ctx.modifierFlags?.has(flag) === true
|
|
399
|
-
|
|
400
|
-
for (const flag of Object.keys(MODIFIER_METADATA) as Array<ModifierFlag>) {
|
|
401
|
-
const metadata = MODIFIER_METADATA[flag]
|
|
402
|
-
const targetSelected = metadata.target === "claude" ? ctx.syncClaude : ctx.syncCodex
|
|
403
|
-
if (!targetSelected && supplied(flag)) {
|
|
404
|
-
warn(metadata.ignoredWarning)
|
|
405
|
-
metadata.clear(ctx)
|
|
406
|
-
ctx.modifierFlags?.delete(flag)
|
|
189
|
+
err(`Unknown arg: ${arg}`);
|
|
190
|
+
throw new ExitError(2);
|
|
407
191
|
}
|
|
408
192
|
}
|
|
409
193
|
|
|
410
|
-
|
|
411
|
-
if (!validateClaudeModel(ctx, ctx.claudeModel)) {
|
|
412
|
-
printModels(ctx, "claude")
|
|
413
|
-
err(`Invalid Claude model '${ctx.claudeModel}' — use an alias above or a full claude-* ID`)
|
|
414
|
-
throw new ExitError(2)
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
if (supplied("--claude-effort")) {
|
|
418
|
-
if (!isEffortModifierValue("claude", ctx.claudeEffort)) {
|
|
419
|
-
printCatalog(ctx, effortCatalog("claude"))
|
|
420
|
-
err(`Invalid Claude effort '${ctx.claudeEffort}' — valid: ${effortValueGrammar("claude")}`)
|
|
421
|
-
throw new ExitError(2)
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
if (supplied("--claude-advisor")) {
|
|
425
|
-
if (!CLAUDE_ADVISOR_STATES.some((state) => state === ctx.claudeAdvisor)) {
|
|
426
|
-
printCatalog(ctx, advisorCatalog())
|
|
427
|
-
err(`Invalid Claude advisor state '${ctx.claudeAdvisor}' — valid: ${advisorValueGrammar()}`)
|
|
428
|
-
throw new ExitError(2)
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
if (supplied("--codex-model")) {
|
|
432
|
-
if (!validateCodexModel(ctx, ctx.codexModel)) {
|
|
433
|
-
printModels(ctx, "codex")
|
|
434
|
-
err(`Invalid Codex model '${ctx.codexModel}' — must match ^[A-Za-z0-9._-]+$`)
|
|
435
|
-
throw new ExitError(2)
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
if (supplied("--codex-effort")) {
|
|
439
|
-
if (!isEffortModifierValue("codex", ctx.codexEffort)) {
|
|
440
|
-
printCatalog(ctx, effortCatalog("codex"))
|
|
441
|
-
err(`Invalid Codex effort '${ctx.codexEffort}' — valid: ${effortValueGrammar("codex")}`)
|
|
442
|
-
throw new ExitError(2)
|
|
443
|
-
}
|
|
444
|
-
}
|
|
194
|
+
applyDefaultSelection(ctx);
|
|
445
195
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Help text and the early-exit signal for the EngineNative flag layer.
|
|
3
|
+
* Kept dependency-free (besides injected ctx) so modifier mapping and the
|
|
4
|
+
* dispatch loop can both share it without import cycles.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Ctx } from "./index";
|
|
8
|
+
import { advisorFlagGrammar, effortFlagGrammar } from "../efforts";
|
|
9
|
+
|
|
10
|
+
export class ExitError extends Error {
|
|
11
|
+
constructor(readonly code: number) {
|
|
12
|
+
super(`exit ${code}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function printCatalog(ctx: Ctx, catalog: string): void {
|
|
17
|
+
for (const line of catalog.split("\n")) ctx.services.logger.echo(line);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function printUsage(ctx: Ctx, knownPlugins: ReadonlyArray<string>): void {
|
|
21
|
+
const { echo } = ctx.services.logger;
|
|
22
|
+
const argv0 = "docks-kit sync";
|
|
23
|
+
echo(`Usage: ${argv0} [claude] [codex] [agents] [omp] [flags]`);
|
|
24
|
+
echo("");
|
|
25
|
+
echo("Targets (positional; default: this machine's harness selection)");
|
|
26
|
+
echo(" claude sync the Claude Code SoT");
|
|
27
|
+
echo(" codex sync the Codex SoT");
|
|
28
|
+
echo(" agents sync universal agent skills");
|
|
29
|
+
echo(" omp sync the Oh My Pi SoT");
|
|
30
|
+
echo("");
|
|
31
|
+
echo("Global flags");
|
|
32
|
+
echo(" --dry-run preview without applying");
|
|
33
|
+
echo(
|
|
34
|
+
" --reconcile reconcile kit-owned settings with SoT (SoT keys win; user-only keys preserved; permissions arrays replaced)",
|
|
35
|
+
);
|
|
36
|
+
echo(
|
|
37
|
+
" --prune uninstall kit-managed installs not in SoT (plugins, marketplaces, skills in SoT/.agents/skills.txt)",
|
|
38
|
+
);
|
|
39
|
+
echo(" --skip-bubblewrap skip optional bubblewrap bootstrap (Codex Linux sandbox)");
|
|
40
|
+
echo(" --skip-plugin-refresh install missing plugins but skip refresh-only updates");
|
|
41
|
+
echo(
|
|
42
|
+
" --verbose also print no-op confirmations (already in sync, up to date, left as-is)",
|
|
43
|
+
);
|
|
44
|
+
echo("");
|
|
45
|
+
echo(
|
|
46
|
+
"Deploy-time modifiers (deployed config only; SoT untouched; a later flag-less sync reverts)",
|
|
47
|
+
);
|
|
48
|
+
echo(
|
|
49
|
+
" --claude-model=<m> set deployed ~/.claude/settings.json model (aliases: best|opus|fable|sonnet|haiku, full claude-* IDs, or 'default' to unset)",
|
|
50
|
+
);
|
|
51
|
+
echo(` ${effortFlagGrammar("claude").padEnd(39)} set deployed effortLevel`);
|
|
52
|
+
echo(` ${advisorFlagGrammar().padEnd(39)} set deployed advisor state`);
|
|
53
|
+
echo(
|
|
54
|
+
" --claude-compact-window=<n> set deployed autocompact window in tokens (e.g. 680000 or 680k) for disposable sessions",
|
|
55
|
+
);
|
|
56
|
+
echo(
|
|
57
|
+
" --claude-permissive empty permissions.ask/deny in deployed settings (sandboxes/containers; unattended commits + pushes)",
|
|
58
|
+
);
|
|
59
|
+
echo(" --codex-model=<m> set deployed ~/.codex/config.toml model (e.g. gpt-5.5)");
|
|
60
|
+
echo(` ${effortFlagGrammar("codex").padEnd(39)} set deployed model_reasoning_effort`);
|
|
61
|
+
echo("");
|
|
62
|
+
echo("Sticky opt-ins (installed + enabled until --prune)");
|
|
63
|
+
echo(
|
|
64
|
+
` --claude-plugin=<name> opt an optional plugin into this machine (known: ${knownPlugins.join(", ")}; repeatable)`,
|
|
65
|
+
);
|
|
66
|
+
}
|