docks-kit 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/AGENTS.md +14 -15
  2. package/README.md +12 -11
  3. package/SoT/.agents/skills.txt +3 -3
  4. package/SoT/.claude/settings.json +3 -26
  5. package/SoT/models.json +1 -1
  6. package/SoT/toolchain.json +3 -3
  7. package/cli/docs/install.md +39 -12
  8. package/cli/docs/overview.md +3 -4
  9. package/cli/docs/platforms.md +35 -22
  10. package/cli/src/commands/sync.ts +32 -4
  11. package/cli/src/commands/update.ts +116 -0
  12. package/cli/src/engine-native/DESIGN.md +89 -0
  13. package/cli/src/engine-native/claudeModel.ts +48 -0
  14. package/cli/src/engine-native/claudeSync.ts +771 -0
  15. package/cli/src/engine-native/codexSync.ts +439 -0
  16. package/cli/src/engine-native/codexToml.ts +67 -0
  17. package/cli/src/engine-native/exec.ts +54 -0
  18. package/cli/src/engine-native/index.ts +109 -0
  19. package/cli/src/engine-native/jq.ts +63 -0
  20. package/cli/src/engine-native/models.ts +73 -0
  21. package/cli/src/engine-native/modes.ts +133 -0
  22. package/cli/src/engine-native/output.ts +20 -0
  23. package/cli/src/engine-native/parseArgs.ts +223 -0
  24. package/cli/src/engine-native/settings.ts +41 -0
  25. package/cli/src/engine-native/skillsSync.ts +369 -0
  26. package/cli/src/engine-native/toolchain.ts +257 -0
  27. package/cli/src/engine.ts +35 -18
  28. package/cli/src/kitHome.ts +4 -4
  29. package/cli/src/main.ts +14 -1
  30. package/cli/src/manifests.ts +3 -2
  31. package/cli/tsconfig.json +1 -1
  32. package/docks-kit +6 -3
  33. package/package.json +8 -4
  34. package/lib/claude.sh +0 -846
  35. package/lib/codex.sh +0 -518
  36. package/lib/common.sh +0 -229
  37. package/lib/engine.sh +0 -153
  38. package/lib/skills.sh +0 -373
  39. package/lib/toolchain.sh +0 -222
package/cli/src/engine.ts CHANGED
@@ -1,21 +1,30 @@
1
- import { Command as Subprocess } from "@effect/platform"
2
1
  import { Console, Effect } from "effect"
2
+ import { spawnSync } from "node:child_process"
3
+ import { runEngineNative } from "./engine-native"
3
4
  import { kitHome } from "./kitHome"
4
5
 
5
6
  /**
6
- * The single seam between the typed CLI and the bash engine. All mutation runs
7
- * through lib/engine.sh (same flag vocabulary as this CLI), so the engine stays
8
- * independently usable as the zero-dependency escape hatch.
7
+ * The single seam between the typed CLI and EngineNative. Engine execution
8
+ * stays in-process after @effect/cli has parsed pickers and flag spellings.
9
9
  */
10
+ const bashRemovedMessage = "bash engine removed — recover at tag bash-engine-final"
11
+ const bashEngineRequested = (): boolean => process.env["DOCKS_KIT_ENGINE"] === "bash"
12
+
13
+ // bun build --compile runs the embedded entry from a virtual path
14
+ // ("/$bunfs/root/…" on POSIX, "B:\~BUN\root\…" on Windows). There
15
+ // process.execPath IS the CLI, so a re-spawn must not pass main.ts.
16
+ // The Windows check is anchored to the drive-rooted "~BUN" segment so a
17
+ // real checkout under a ~BUN-named directory can't false-positive.
18
+ export const compiled =
19
+ process.argv[1] !== undefined &&
20
+ (process.argv[1].startsWith("/$bunfs/") || /^[A-Za-z]:[\\/]~BUN[\\/]/i.test(process.argv[1]))
21
+
10
22
  export const engine = (args: ReadonlyArray<string>) =>
11
23
  Effect.gen(function* () {
12
- const code = yield* Subprocess.make("bash", join("lib/engine.sh"), ...args).pipe(
13
- Subprocess.workingDirectory(kitHome()),
14
- Subprocess.stdin("inherit"),
15
- Subprocess.stdout("inherit"),
16
- Subprocess.stderr("inherit"),
17
- Subprocess.exitCode
18
- )
24
+ if (bashEngineRequested()) {
25
+ yield* bail(bashRemovedMessage, 2)
26
+ }
27
+ const code = yield* Effect.sync(() => runEngineNative(args))
19
28
  if (code !== 0) {
20
29
  yield* Effect.sync(() => process.exit(code))
21
30
  }
@@ -23,13 +32,21 @@ export const engine = (args: ReadonlyArray<string>) =>
23
32
 
24
33
  /** Run the engine capturing stdout (engine logs/warns go to stderr and pass through). */
25
34
  export const engineCapture = (args: ReadonlyArray<string>) =>
26
- Subprocess.make("bash", join("lib/engine.sh"), ...args).pipe(
27
- Subprocess.workingDirectory(kitHome()),
28
- Subprocess.stderr("inherit"),
29
- Subprocess.string
30
- )
31
-
32
- const join = (rel: string): string => `${kitHome()}/${rel}`
35
+ bashEngineRequested()
36
+ ? bail(bashRemovedMessage, 2)
37
+ : Effect.sync(() => {
38
+ // Child process (raw channel): runEngineNative writes straight to
39
+ // process.stdout, so in-process capture isn't possible.
40
+ const res = spawnSync(process.execPath, compiled ? [...args] : [`${kitHome()}/cli/src/main.ts`, ...args], {
41
+ env: { ...process.env, DOCKS_KIT_ENGINE: "native-raw" },
42
+ encoding: "utf8",
43
+ stdio: ["ignore", "pipe", "inherit"]
44
+ })
45
+ if (res.error !== undefined || res.status !== 0) {
46
+ process.stderr.write(`\x1b[1;33m[warn]\x1b[0m engine capture failed (${args.join(" ")} exited ${res.status ?? "spawn-error"})\n`)
47
+ }
48
+ return res.stdout ?? ""
49
+ })
33
50
 
34
51
  /** Print a message to stderr and exit — for CLI-side validation failures. */
35
52
  export const bail = (message: string, code = 2) =>
@@ -2,19 +2,19 @@ import { existsSync } from "node:fs"
2
2
  import { dirname, join, resolve } from "node:path"
3
3
 
4
4
  const isKitHome = (dir: string): boolean =>
5
- existsSync(join(dir, "SoT")) && existsSync(join(dir, "lib", "engine.sh"))
5
+ existsSync(join(dir, "SoT")) && existsSync(join(dir, "package.json"))
6
6
 
7
7
  /**
8
- * Resolve the kit home (the directory holding SoT/ + lib/engine.sh):
8
+ * Resolve the kit home (the directory holding SoT/ + package.json):
9
9
  * DOCKS_KIT_HOME env → nearest ancestor of cwd (repo-checkout usage) →
10
10
  * the package's own root (bunx / bun add -g usage: main.ts lives at
11
- * <root>/cli/src, and the npm package bundles SoT/ + lib/ alongside).
11
+ * <root>/cli/src, and the npm package bundles SoT/ alongside).
12
12
  */
13
13
  export const kitHome = (): string => {
14
14
  const env = process.env["DOCKS_KIT_HOME"]
15
15
  if (env !== undefined && env !== "") {
16
16
  if (isKitHome(env)) return env
17
- throw new Error(`DOCKS_KIT_HOME=${env} does not contain SoT/ + lib/engine.sh`)
17
+ throw new Error(`DOCKS_KIT_HOME=${env} does not contain SoT/ + package.json`)
18
18
  }
19
19
  let dir = process.cwd()
20
20
  for (;;) {
package/cli/src/main.ts CHANGED
@@ -10,12 +10,14 @@ import { skillsCommand } from "./commands/skills"
10
10
  import { statusCommand } from "./commands/status"
11
11
  import { syncCommand } from "./commands/sync"
12
12
  import { toolchainCommand } from "./commands/toolchain"
13
+ import { updateCommand } from "./commands/update"
13
14
 
14
15
  const root = Command.make("docks-kit", {}, () =>
15
16
  Effect.gen(function* () {
16
17
  yield* Console.log("docks-kit — portable AI coding agent config kit")
17
18
  yield* Console.log("")
18
19
  yield* Console.log(" docks-kit sync [claude] [codex] [agents] deploy the SoT to this machine")
20
+ yield* Console.log(" docks-kit update [--no-sync] self-update the kit, then sync")
19
21
  yield* Console.log(" docks-kit model <claude|codex> [value] get/set the deployed model")
20
22
  yield* Console.log(" docks-kit models [tool] kit-verified model catalog")
21
23
  yield* Console.log(" docks-kit toolchain [check|ensure <tool>] verified-version floors")
@@ -25,7 +27,7 @@ const root = Command.make("docks-kit", {}, () =>
25
27
  yield* Console.log(" docks-kit docs [topic] self-documentation")
26
28
  yield* Console.log("")
27
29
  yield* Console.log("Run 'docks-kit --help' for full option listings (also: --wizard, --completions).")
28
- yield* Console.log("Zero-dependency escape hatch: bash lib/engine.sh <same subcommands/flags>")
30
+ yield* Console.log("No-Bun recovery path: use a platform release binary.")
29
31
  })
30
32
  ).pipe(
31
33
  Command.withDescription(
@@ -33,6 +35,7 @@ const root = Command.make("docks-kit", {}, () =>
33
35
  ),
34
36
  Command.withSubcommands([
35
37
  syncCommand,
38
+ updateCommand,
36
39
  modelCommand,
37
40
  modelsCommand,
38
41
  toolchainCommand,
@@ -43,6 +46,16 @@ const root = Command.make("docks-kit", {}, () =>
43
46
  ])
44
47
  )
45
48
 
49
+ // Harness-private raw channel:
50
+ // `DOCKS_KIT_ENGINE=native-raw` bypasses @effect/cli and hands the raw engine
51
+ // argv to EngineNative so golden tests drive the internal vocabulary directly.
52
+ // PUBLIC engine execution lives at the engine.ts seam after the CLI has
53
+ // parsed/normalized pickers, --flag value forms, and non-engine commands.
54
+ if (process.env["DOCKS_KIT_ENGINE"] === "native-raw") {
55
+ const { runEngineNative } = await import("./engine-native")
56
+ process.exit(runEngineNative(process.argv.slice(2)))
57
+ }
58
+
46
59
  const cli = Command.run(root, {
47
60
  name: "docks-kit",
48
61
  version: "0.1.0"
@@ -1,7 +1,10 @@
1
1
  import { readFileSync, readdirSync, readlinkSync, existsSync } from "node:fs"
2
+ import { homedir } from "node:os"
2
3
  import { join } from "node:path"
3
4
  import { kitHome } from "./kitHome"
4
5
 
6
+ export { homedir }
7
+
5
8
  export interface ModelEntry {
6
9
  readonly id: string
7
10
  readonly kind: "alias" | "id"
@@ -44,8 +47,6 @@ export const sotCodexModel = (): string | undefined =>
44
47
  export const deployedCodexModel = (): string | undefined =>
45
48
  tomlModel(join(homedir(), ".codex", "config.toml"))
46
49
 
47
- export const homedir = (): string => process.env["HOME"] ?? "~"
48
-
49
50
  /** Installed plugins (user scope) vs SoT enabledPlugins tri-state. */
50
51
  export const pluginsView = (): Array<{
51
52
  plugin: string
package/cli/tsconfig.json CHANGED
@@ -10,5 +10,5 @@
10
10
  "forceConsistentCasingInFileNames": true,
11
11
  "verbatimModuleSyntax": true
12
12
  },
13
- "include": ["src/**/*.ts", "src/**/*.d.ts"]
13
+ "include": ["src/**/*.ts", "src/**/*.d.ts", "test/**/*.ts"]
14
14
  }
package/docks-kit CHANGED
@@ -2,7 +2,7 @@
2
2
  # docks-kit — launcher. Resolution order:
3
3
  # 1. compiled binary in cli/dist/ (bun build --compile output)
4
4
  # 2. Bun from source (auto-installs Bun + node_modules when missing)
5
- # Zero-dependency escape hatch (no Bun at all): bash lib/engine.sh <args>
5
+ # No-Bun recovery path: download a release binary for your platform.
6
6
  set -euo pipefail
7
7
 
8
8
  REPO_DIR="$(cd "$(dirname "$0")" && pwd)"
@@ -12,6 +12,9 @@ case "$(uname -s)-$(uname -m)" in
12
12
  Linux-aarch64) KIT_BIN="docks-kit-linux-arm64" ;;
13
13
  Darwin-x86_64) KIT_BIN="docks-kit-darwin-x64" ;;
14
14
  Darwin-arm64) KIT_BIN="docks-kit-darwin-arm64" ;;
15
+ # Git Bash unames look like MINGW64_NT-10.0-19045-x86_64. The compiled
16
+ # binary is the supported Windows path; the Bun fallback below is Unix-shaped.
17
+ MINGW*-x86_64|MSYS*-x86_64|CYGWIN*-x86_64) KIT_BIN="docks-kit-windows-x64.exe" ;;
15
18
  *) KIT_BIN="" ;;
16
19
  esac
17
20
  if [[ -n "$KIT_BIN" && -x "$REPO_DIR/cli/dist/$KIT_BIN" ]]; then
@@ -33,7 +36,7 @@ find_bun() {
33
36
  if ! BUN="$(find_bun)"; then
34
37
  echo "[docks-kit] Bun not found — installing (download-then-run)..." >&2
35
38
  if ! command -v curl >/dev/null 2>&1; then
36
- echo "[docks-kit] curl missing too. Install Bun manually (https://bun.sh) or use the escape hatch: bash $REPO_DIR/lib/engine.sh" >&2
39
+ echo "[docks-kit] curl missing too. Install Bun manually (https://bun.sh) or download a docks-kit release binary." >&2
37
40
  exit 1
38
41
  fi
39
42
  # Pin the Bun release to the kit-verified version when jq can read it
@@ -46,7 +49,7 @@ if ! BUN="$(find_bun)"; then
46
49
  curl -fsSL https://bun.sh/install -o "$tmp_installer" && bash "$tmp_installer" ${BUN_PIN:+"bun-v$BUN_PIN"} >/dev/null 2>&1 || true
47
50
  rm -f "$tmp_installer"
48
51
  if ! BUN="$(find_bun)"; then
49
- echo "[docks-kit] Bun install failed. Escape hatch: bash $REPO_DIR/lib/engine.sh <args>" >&2
52
+ echo "[docks-kit] Bun install failed. Download a docks-kit release binary for a no-Bun recovery path." >&2
50
53
  exit 1
51
54
  fi
52
55
  fi
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docks-kit",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Portable AI coding agent config kit — SoT sync engine + typed CLI for Claude Code, Codex, and universal agent skills",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -15,7 +15,6 @@
15
15
  "cli/src",
16
16
  "cli/docs",
17
17
  "cli/tsconfig.json",
18
- "lib",
19
18
  "SoT",
20
19
  "notification.mp3",
21
20
  "docks-kit",
@@ -24,7 +23,10 @@
24
23
  ],
25
24
  "scripts": {
26
25
  "typecheck": "tsc --noEmit -p cli",
27
- "build:binaries": "bash cli/build-binaries.sh"
26
+ "build:binaries": "bash cli/build-binaries.sh",
27
+ "golden:dryrun": "bun cli/test/golden-dryrun.ts",
28
+ "golden:mutation": "bun cli/test/golden-mutation.ts",
29
+ "test:unit": "vitest run"
28
30
  },
29
31
  "dependencies": {
30
32
  "@effect/cli": "0.75.2",
@@ -33,7 +35,9 @@
33
35
  "effect": "3.21.4"
34
36
  },
35
37
  "devDependencies": {
38
+ "@effect/vitest": "0.29.0",
36
39
  "@types/bun": "^1.3.0",
37
- "typescript": "^5.7.2"
40
+ "typescript": "7.0.2",
41
+ "vitest": "3.2.7"
38
42
  }
39
43
  }