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.
- package/AGENTS.md +14 -15
- package/README.md +12 -11
- package/SoT/.agents/skills.txt +3 -3
- package/SoT/.claude/settings.json +3 -26
- package/SoT/models.json +1 -1
- package/SoT/toolchain.json +3 -3
- package/cli/docs/install.md +39 -12
- package/cli/docs/overview.md +3 -4
- package/cli/docs/platforms.md +35 -22
- package/cli/src/commands/sync.ts +32 -4
- package/cli/src/commands/update.ts +116 -0
- package/cli/src/engine-native/DESIGN.md +89 -0
- package/cli/src/engine-native/claudeModel.ts +48 -0
- package/cli/src/engine-native/claudeSync.ts +771 -0
- package/cli/src/engine-native/codexSync.ts +439 -0
- package/cli/src/engine-native/codexToml.ts +67 -0
- package/cli/src/engine-native/exec.ts +54 -0
- package/cli/src/engine-native/index.ts +109 -0
- package/cli/src/engine-native/jq.ts +63 -0
- package/cli/src/engine-native/models.ts +73 -0
- package/cli/src/engine-native/modes.ts +133 -0
- package/cli/src/engine-native/output.ts +20 -0
- package/cli/src/engine-native/parseArgs.ts +223 -0
- package/cli/src/engine-native/settings.ts +41 -0
- package/cli/src/engine-native/skillsSync.ts +369 -0
- package/cli/src/engine-native/toolchain.ts +257 -0
- package/cli/src/engine.ts +35 -18
- package/cli/src/kitHome.ts +4 -4
- package/cli/src/main.ts +14 -1
- package/cli/src/manifests.ts +3 -2
- package/cli/tsconfig.json +1 -1
- package/docks-kit +6 -3
- package/package.json +8 -4
- package/lib/claude.sh +0 -846
- package/lib/codex.sh +0 -518
- package/lib/common.sh +0 -229
- package/lib/engine.sh +0 -153
- package/lib/skills.sh +0 -373
- package/lib/toolchain.sh +0 -222
package/AGENTS.md
CHANGED
|
@@ -14,18 +14,16 @@ Tool-specific instructions live alongside this file:
|
|
|
14
14
|
|
|
15
15
|
| Path | Purpose |
|
|
16
16
|
|------|---------|
|
|
17
|
-
| `docks-kit` | CLI launcher: runs the compiled binary in `cli/dist/` when present, otherwise Bun-from-source (auto-installs Bun + `node_modules`).
|
|
18
|
-
| `
|
|
19
|
-
| `
|
|
20
|
-
| `lib/` | Shared sync helpers — `common.sh` for flag parsing/validation/preflight, plus per-tool `claude.sh` / `codex.sh` / `skills.sh` sync implementations |
|
|
21
|
-
| `cli/` | Effect-TS CLI (typed front-end over the engine) + bundled docs topics |
|
|
17
|
+
| `docks-kit` | CLI launcher: runs the compiled binary in `cli/dist/` when present, otherwise Bun-from-source (auto-installs Bun + `node_modules`). No-Bun recovery is the platform release binary |
|
|
18
|
+
| `cli/src/engine-native/` | EngineNative implementation for `sync`, `model`, and `toolchain`; idempotent, flag-gated for destructive reconciliation |
|
|
19
|
+
| `cli/` | Effect-TS CLI + bundled docs topics |
|
|
22
20
|
| `SoT/models.json` | Kit-verified model catalog |
|
|
23
|
-
| `SoT/toolchain.json` | Toolchain floors manifest (verified pins consumed by
|
|
21
|
+
| `SoT/toolchain.json` | Toolchain floors manifest (verified pins consumed by EngineNative) |
|
|
24
22
|
| `install.sh` | Global installer |
|
|
25
23
|
| `.github/workflows/release-cli.yml` | `cli-v*` release binaries + npm publish |
|
|
26
24
|
| `README.md` | Front door |
|
|
27
|
-
| `package.json` / `bun.lock` | npm package: `bin` = `cli/src/main.ts`; bundles `
|
|
28
|
-
| `SoT/.agents/skills.txt` | Universal-skill manifest. One [agentskills.io](https://agentskills.io) slug per line;
|
|
25
|
+
| `package.json` / `bun.lock` | npm package: `bin` = `cli/src/main.ts`; bundles `cli/` + `SoT/` |
|
|
26
|
+
| `SoT/.agents/skills.txt` | Universal-skill manifest. One [agentskills.io](https://agentskills.io) slug per line; EngineNative runs `npx skills add` for each missing entry into `~/.agents/skills/`, where Codex et al. discover it natively and Claude Code follows a symlink at `~/.claude/skills/` |
|
|
29
27
|
| `notification.mp3` | Audio asset for Notification hooks (consumed by Claude Code today; tool-agnostic file) |
|
|
30
28
|
| `docs/plans/` | Multi-commit work-item plans (`active/` with status in frontmatter, plus `finished/` archive). Convention: `docs/plans/AGENTS.md` |
|
|
31
29
|
| `CLAUDE.md` | Claude-specific instructions; imports this `AGENTS.md` |
|
|
@@ -43,11 +41,12 @@ For per-tool SoT layouts (`SoT/.claude/`, `SoT/.codex/`), see the matching SoT d
|
|
|
43
41
|
|
|
44
42
|
## Engineering rules
|
|
45
43
|
|
|
46
|
-
- **Idempotent operations.** Every
|
|
44
|
+
- **Idempotent operations.** Every EngineNative sync step must be safe to re-run. Settings merges, plugin installs, and marketplace adds are all idempotent — re-running with no SoT changes is a no-op.
|
|
45
|
+
- **Removed bash engine.** The bash engine was removed after the `bash-engine-final` tag. `DOCKS_KIT_ENGINE=bash` must fail with the removed-engine message; engine bugs are fixed forward in EngineNative.
|
|
47
46
|
- **Targeted syncs.** `./docks-kit sync` accepts positional targets: `claude`, `codex`, and `agents`. Use the narrowest target that matches the SoT change (for example, `./docks-kit sync codex` for Codex-only config edits); targets can be combined with `--dry-run`, `--skip-rtk`, `--reconcile`, `--prune`, `--yes` (auto-accept toolchain prompts), and the deploy-time modifiers `--claude-compact-window=<tokens>` / `--claude-permissive` / `--claude-model=<m>` / `--codex-model=<m>` (see `CLAUDE.md` § Deploy-time modifiers).
|
|
48
47
|
- **Additive by default.** Keys present in deployed config but absent from SoT are preserved on default sync. This protects user-only additions, but means drift accumulates — neither flag-less reset can clean it up. The one exception is the Claude `removed` manifest (`claude::_removed_manifest`), a curated list of unambiguous kit-owned artifacts that `claude::sync_removals` force-prunes on every sync; see `CLAUDE.md` § Pruning stale artifacts.
|
|
49
48
|
- **`--reconcile` / `--prune` are the kit-owned reconcile flags.** Orthogonal — `--reconcile` reconciles the settings layer (SoT-declared keys/tables/arrays win; user-only keys and nested objects are preserved; permissions arrays are replaced wholesale by SoT). `--prune` uninstalls kit-managed installations not in the SoT (plugins, marketplaces, and `~/.agents/skills/*` entries tracked in `~/.agents/.kit-managed-skills`). Combine for a full reset to SoT's kit-managed scope. User-only additions outside the kit's scope (custom env vars, mcpServers, manually-installed skills, third-party plugins not declared in SoT) are always preserved. Each tool's per-tool file documents the specific paths and diff recipes.
|
|
50
|
-
- **SOLID-aligned
|
|
49
|
+
- **SOLID-aligned modules.** `cli/src/engine-native/parseArgs.ts` owns flag parsing/validation. `toolchain.ts` owns the verified-version gate over `SoT/toolchain.json`. `claudeSync.ts`, `codexSync.ts`, and `skillsSync.ts` own tool-specific sync logic. `index.ts` is the thin orchestrator. The public CLI seam is `cli/src/engine.ts`.
|
|
51
50
|
- **Small, reviewable changes.** Bundled multi-concern PRs are harder to review and revert. Split an engine/CLI change and a per-tool config change unless the change requires atomicity.
|
|
52
51
|
- **Dry-run before destructive flags.** Always preview with `./docks-kit sync --dry-run` (or the relevant `diff <(jq -S …)` recipe in the per-tool file) before invoking `--reconcile` or `--prune`. User-added permissions / env vars / plugins absent from SoT will be discarded.
|
|
53
52
|
- **SoT prompt files are rules, not explanation.** `SoT/.claude/CLAUDE.md` and `SoT/.codex/AGENTS.md` are loaded into every agent session's prompt context — every line costs prompt tokens on every turn for every user. Restrict their content to rules, heuristics, and `<constraint>` blocks the agent must *act on* during a turn. Do NOT add inline source citations (`Source: …`, attributed quotes), "why this rule exists" preface text, version-watermarking trivia (e.g. "Distilled from X v2.0, captured 2025-11-07"), per-bug workarounds, or installation instructions. Provenance, motivation, and historical context belong in `CLAUDE.md` / `AGENTS.md` at the repo root (humans read once) or in commit messages — never in the SoT. For every line, apply the official test: would removing it cause the agent to make mistakes? If not, cut it — over-instruction degrades adherence on current frontier models.
|
|
@@ -55,7 +54,7 @@ For per-tool SoT layouts (`SoT/.claude/`, `SoT/.codex/`), see the matching SoT d
|
|
|
55
54
|
|
|
56
55
|
## Code style
|
|
57
56
|
|
|
58
|
-
- Bash: `set -euo pipefail`, quoted variables, `[[ ]]` over `[ ]`, function-scoped `local`.
|
|
57
|
+
- Bash: for launchers/installers/hook assets, use `set -euo pipefail`, quoted variables, `[[ ]]` over `[ ]`, and function-scoped `local`.
|
|
59
58
|
- JSON config: edit the SoT (`SoT/<tool>/`) and run `./docks-kit sync`. Never edit deployed config (`~/.claude/`, `~/.codex/`) directly.
|
|
60
59
|
|
|
61
60
|
## Security
|
|
@@ -66,17 +65,17 @@ For per-tool SoT layouts (`SoT/.claude/`, `SoT/.codex/`), see the matching SoT d
|
|
|
66
65
|
|
|
67
66
|
## Testing
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
Automated coverage includes `bun run test:unit`, `bun run golden:dryrun`, and `bun run golden:mutation`; prove-red modes must exit non-zero after detecting planted mismatches. Also verify user-facing changes via `./docks-kit sync --dry-run`, per-tool sanity (`/doctor`, `/plugin`, etc.), and `diff <(jq -S . <SoT>) <(jq -S . <deployed>)` recipes from the per-tool file.
|
|
70
69
|
|
|
71
70
|
## Skills
|
|
72
71
|
|
|
73
|
-
This project ships **kit-mechanic skills** under `.claude/skills/` — narrowly-scoped references for how
|
|
72
|
+
This project ships **kit-mechanic skills** under `.claude/skills/` — narrowly-scoped references for how EngineNative works (settings merge, plugin bootstrap, universal-skill install, Codex TOML merge, sync orchestration). They cost prompt tokens only inside this repo's sessions and document regression-prone TypeScript sync logic in `cli/src/engine-native/`. **Pipeline content** (multi-agent slash commands, refactor/security/docs workflows, parallel-scanner agents) belongs in the separate [DocksDocks/docks](https://github.com/DocksDocks/docks) plugin — not here. Project-level agents under `.claude/agents/` follow the same rule: kit-mechanic agents that wrap kit-mechanic skills are permitted; pipeline agents live in the docks plugin.
|
|
74
73
|
|
|
75
74
|
<constraint>
|
|
76
|
-
When a kit-mechanic skill, its `references/`, or a wrapper agent (`.claude/agents/*.md` + its `.codex/agents/*.toml` twin) cites
|
|
75
|
+
When a kit-mechanic skill, its `references/`, or a wrapper agent (`.claude/agents/*.md` + its `.codex/agents/*.toml` twin) cites EngineNative internals, name the **module + exported/local function + semantic anchor** (e.g. `claudeSync.ts syncPlugins, pass 5 uninstall guard`) — never a raw `file:NNN` line number, which goes stale on every refactor. Keep exactly one coarse `metadata.source_files[].lines` range per skill file as the sole intentional line-number touchpoint.
|
|
77
76
|
</constraint>
|
|
78
77
|
|
|
79
|
-
**Universal-skill bootstrap.** `SoT/.agents/skills.txt` declares [agentskills.io](https://agentskills.io/specification) slugs the kit installs to `~/.agents/skills/` on every machine via `
|
|
78
|
+
**Universal-skill bootstrap.** `SoT/.agents/skills.txt` declares [agentskills.io](https://agentskills.io/specification) slugs the kit installs to `~/.agents/skills/` on every machine via `skillsSync.ts`. The bootstrap invokes `npx skills add <slug> -g -y -a claude-code codex` per missing skill — `<slug>` comes first because the CLI's `-a/--agent` flag is variadic and would otherwise swallow it. Naming **both** agents (`claude-code` + `codex`, the kit's support matrix) keeps the CLI in multi-agent mode: it writes the canonical `SKILL.md` to the universal `~/.agents/skills/<name>/` path — which Codex reads natively (per [OpenAI's Codex docs](https://developers.openai.com/codex/skills/), `$HOME/.agents/skills` is a user-level skill source) — and symlinks `~/.claude/skills/<name>` → it for Claude Code, which wants its own per-tool directory. A *single* `-a claude-code` would instead trigger a copy-direct shortcut (a real copy into `~/.claude/skills/`, no canonical path, Codex uncovered); `-a '*'` would over-reach into every AI tool the CLI can detect (~50). Add a new universal skill by appending one `<owner>/<repo>` line to `skills.txt` and re-running `./docks-kit sync` — idempotent: existing skills are skipped after checking `~/.agents/skills/<name>`. Skills that depend on a separate CLI binary get an explicit auto-install helper in `skillsSync.ts` (e.g. `syncAgentBrowserCli` runs `npm install -g agent-browser` + `agent-browser install --with-deps` on Linux; the `--with-deps` flag may prompt for sudo to install system libs). That helper also **self-upgrades** a present-but-stale binary: when `agent-browser`'s installed version is older than npm's `latest` it re-runs `npm install -g agent-browser` (the numeric-sort compare never downgrades a locally-newer pre-release, and skips silently when npm is absent/offline); the Chrome download is not repeated on upgrade. A second helper, `syncEffectSolutionsCli`, installs the optional `effect-solutions` Effect-docs CLI used by the `effect-kit` plugin: gated on `effect-kit` being enabled in SoT, it auto-installs Bun when absent (download-then-run, never `curl | bash`) and symlinks **both** `bun` and the CLI into `~/.local/bin`. Linking bun too is mandatory — the CLI's `#!/usr/bin/env bun` shebang needs `bun` on PATH at run time — and `~/.local/bin` is the only dir reliably on the *non-interactive* agent PATH, since `~/.bashrc`'s "if not interactive, return" guard means rc PATH edits never reach agent shells (the same PATH reason the official Codex standalone installer targets `~/.local/bin`).
|
|
80
79
|
|
|
81
80
|
## Plans
|
|
82
81
|
|
package/README.md
CHANGED
|
@@ -23,18 +23,19 @@ from source via Bun — auto-installing Bun and dependencies when missing.
|
|
|
23
23
|
Other install paths (global `bun add -g docks-kit`, curl installer) —
|
|
24
24
|
see `./docks-kit docs install`.
|
|
25
25
|
|
|
26
|
-
**
|
|
26
|
+
**No-Bun recovery path**:
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
```
|
|
28
|
+
Download the platform release binary from GitHub Releases and run it from a
|
|
29
|
+
kit checkout, or set `DOCKS_KIT_HOME` to the checkout containing `SoT/`.
|
|
31
30
|
|
|
32
|
-
Prerequisites:
|
|
31
|
+
Prerequisites for source/global installs: Bun plus `jq` and `curl` for sync
|
|
32
|
+
preflight; Node/npm for npm-global tools.
|
|
33
33
|
|
|
34
34
|
## CLI
|
|
35
35
|
|
|
36
36
|
```text
|
|
37
37
|
docks-kit sync [claude] [codex] [agents] deploy the SoT (default: all three)
|
|
38
|
+
docks-kit update [--no-sync] self-update the kit (autodetects checkout vs global install), then sync
|
|
38
39
|
docks-kit model <claude|codex> [value] get/set the DEPLOYED model (TTY picker)
|
|
39
40
|
docks-kit models [tool] [--json] kit-verified model catalog
|
|
40
41
|
docks-kit toolchain [check|ensure <tool>] verified-version floors for external tools
|
|
@@ -46,8 +47,8 @@ docks-kit docs [topic] self-documentation (9 topics)
|
|
|
46
47
|
```
|
|
47
48
|
|
|
48
49
|
The CLI is a typed front-end ([Effect-TS](https://effect.website) on Bun);
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
all mutation runs through EngineNative in `cli/src/engine-native/`, with
|
|
51
|
+
golden-regression coverage for dry-run output, mutation snapshots, and argv logs.
|
|
51
52
|
|
|
52
53
|
### Key flags (`docks-kit sync`)
|
|
53
54
|
|
|
@@ -91,7 +92,7 @@ and a later flag-less sync reverts them. Full reference: `docks-kit docs flags`
|
|
|
91
92
|
| `SoT/.agents/` | Universal-skill manifest |
|
|
92
93
|
| `SoT/models.json` | Kit-verified model catalog |
|
|
93
94
|
| `SoT/toolchain.json` | Verified-version floors |
|
|
94
|
-
| `
|
|
95
|
+
| `cli/src/engine-native/` | EngineNative sync/model/toolchain implementation |
|
|
95
96
|
| `cli/` | docks-kit CLI (Effect-TS on Bun) + bundled docs topics |
|
|
96
97
|
| `docks-kit` | Launcher (binary → bun-from-source) |
|
|
97
98
|
| `install.sh` | Global installer (Bun bootstrap + `bun add -g`) |
|
|
@@ -104,7 +105,7 @@ and a later flag-less sync reverts them. Full reference: `docks-kit docs flags`
|
|
|
104
105
|
|----------|-----|-------------|
|
|
105
106
|
| Linux | ✅ native | ✅ native |
|
|
106
107
|
| macOS (x64/arm64) | ✅ native | ✅ native |
|
|
107
|
-
| Windows | ✅ native binary
|
|
108
|
+
| Windows | ✅ native binary (`.exe` and `bun add -g` CI-verified) | ✅ EngineNative (TS, default engine — no Git Bash); real-machine verify pending — RTK hooks are native too (rtk ≥0.37.2) |
|
|
108
109
|
|
|
109
110
|
Details: `docks-kit docs platforms`.
|
|
110
111
|
|
|
@@ -112,8 +113,8 @@ Details: `docks-kit docs platforms`.
|
|
|
112
113
|
|
|
113
114
|
Tagging `cli-v*` builds five standalone binaries (+ SHA256SUMS) and attaches
|
|
114
115
|
them to the GitHub release; npm publish runs when the `NPM_TOKEN` secret is
|
|
115
|
-
configured. Package bundles the
|
|
116
|
-
|
|
116
|
+
configured. Package bundles the CLI + SoT, so npm releases are versioned config
|
|
117
|
+
snapshots.
|
|
117
118
|
|
|
118
119
|
## Deeper docs
|
|
119
120
|
|
package/SoT/.agents/skills.txt
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Universal AI-agent skills (agentskills.io standard).
|
|
2
|
-
# Bootstrapped to ~/.agents/skills/ by
|
|
2
|
+
# Bootstrapped to ~/.agents/skills/ by cli/src/engine-native/skillsSync.ts during ./docks-kit sync.
|
|
3
3
|
# One slug per line: <owner>/<repo>. Lines starting with # are comments.
|
|
4
4
|
# Each skill's canonical SKILL.md lands in ~/.agents/skills/<name>/ — Codex
|
|
5
5
|
# reads that path natively; Claude Code gets a ~/.claude/skills/<name>
|
|
6
|
-
# symlink to it.
|
|
6
|
+
# symlink to it. The skills sync names both agents the kit supports
|
|
7
7
|
# (-a claude-code codex) so the CLI keeps the shared canonical copy.
|
|
8
8
|
|
|
9
9
|
# Browser automation CLI — reaches JS-rendered, auth-walled, login-gated pages
|
|
10
|
-
# (x.com, LinkedIn, Confluence) that built-in WebFetch can't.
|
|
10
|
+
# (x.com, LinkedIn, Confluence) that built-in WebFetch can't. The skills sync
|
|
11
11
|
# auto-installs the `agent-browser` npm package + downloads Chrome for Testing
|
|
12
12
|
# (~175 MB) on first sync; Linux runs `agent-browser install --with-deps` which
|
|
13
13
|
# may prompt for sudo to install system libs (libnss3, libatk, ...).
|
|
@@ -124,32 +124,9 @@
|
|
|
124
124
|
"Bash(git push -f origin master *)"
|
|
125
125
|
],
|
|
126
126
|
"ask": [
|
|
127
|
-
"Bash(git push *)",
|
|
128
|
-
"Bash(git reset *)",
|
|
129
127
|
"Bash(git clean *)",
|
|
130
|
-
"Bash(git merge *)",
|
|
131
|
-
"Bash(git rebase *)",
|
|
132
|
-
"Bash(git checkout -- *)",
|
|
133
|
-
"Bash(git checkout . *)",
|
|
134
|
-
"Bash(rm *)",
|
|
135
|
-
"Bash(mv *)",
|
|
136
|
-
"Bash(chmod *)",
|
|
137
|
-
"Bash(chown *)",
|
|
138
|
-
"Bash(kill *)",
|
|
139
|
-
"Bash(pkill *)",
|
|
140
|
-
"Bash(docker run *)",
|
|
141
|
-
"Bash(docker rm *)",
|
|
142
|
-
"Bash(docker stop *)",
|
|
143
128
|
"Bash(docker volume rm *)",
|
|
144
|
-
"Bash(docker system prune *)"
|
|
145
|
-
"Bash(docker-compose down *)",
|
|
146
|
-
"Bash(docker-compose up *)",
|
|
147
|
-
"Bash(sed -i *)",
|
|
148
|
-
"Bash(xargs *)",
|
|
149
|
-
"Bash(pip install *)",
|
|
150
|
-
"Bash(pip uninstall *)",
|
|
151
|
-
"Bash(pip3 install *)",
|
|
152
|
-
"Bash(pip3 uninstall *)"
|
|
129
|
+
"Bash(docker system prune *)"
|
|
153
130
|
]
|
|
154
131
|
},
|
|
155
132
|
"hooks": {
|
|
@@ -198,7 +175,7 @@
|
|
|
198
175
|
"hooks": [
|
|
199
176
|
{
|
|
200
177
|
"type": "command",
|
|
201
|
-
"command": "echo '{\"hookSpecificOutput\":{\"hookEventName\":\"PostToolUseFailure\",\"additionalContext\":\"Last bash command failed. Repository / file state may have shifted
|
|
178
|
+
"command": "echo '{\"hookSpecificOutput\":{\"hookEventName\":\"PostToolUseFailure\",\"additionalContext\":\"Last bash command failed. Repository / file state may have shifted \u2014 re-read affected files before retrying. If the failure is a missing dependency or env mismatch, surface it to the user rather than retrying blindly.\"}}'",
|
|
202
179
|
"timeout": 5
|
|
203
180
|
}
|
|
204
181
|
]
|
|
@@ -221,7 +198,7 @@
|
|
|
221
198
|
"hooks": [
|
|
222
199
|
{
|
|
223
200
|
"type": "prompt",
|
|
224
|
-
"prompt": "You are a quality gate for subagent outputs in a multi-agent code-analysis pipeline.\n\nEvaluate the subagent's `last_assistant_message` field (in the JSON below) against these requirements:\n\n1. ALLOW (return `{}`): Mode-selection or no-issues responses. Examples: \"Which mode do you prefer\", \"select an option\", \"no issues / problems / violations / blockers found\".\n\n2. ALLOW (return `{}`): Output contains at least one concrete file:line citation
|
|
201
|
+
"prompt": "You are a quality gate for subagent outputs in a multi-agent code-analysis pipeline.\n\nEvaluate the subagent's `last_assistant_message` field (in the JSON below) against these requirements:\n\n1. ALLOW (return `{}`): Mode-selection or no-issues responses. Examples: \"Which mode do you prefer\", \"select an option\", \"no issues / problems / violations / blockers found\".\n\n2. ALLOW (return `{}`): Output contains at least one concrete file:line citation \u2014 e.g. `src/auth.ts:42`, `lib/db.ts:100-115`, or path references that include line numbers.\n\n3. BLOCK (return `{\"decision\":\"block\",\"reason\":\"<one-line explanation>\"}`): Output claims about code or findings WITHOUT concrete file:line citations. Vague references like \"the auth handler\" or \"near the database code\" are not acceptable as the only evidence.\n\nSubagent invocation JSON:\n$ARGUMENTS\n\nReturn ONLY the JSON decision (no commentary, no markdown fences).",
|
|
225
202
|
"timeout": 30
|
|
226
203
|
}
|
|
227
204
|
]
|
package/SoT/models.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "Kit-verified model catalog — single source for
|
|
2
|
+
"$comment": "Kit-verified model catalog — single source for EngineNative validators, the docks-kit CLI (models/model commands, pickers, bare-flag help), and docs. Entries are research-proofed: update an entry and its tool-level `verified` date when a model ships or retires. The catalog informs, it doesn't imprison: well-formed IDs outside it (claude-* / codex charset) apply with a warning.",
|
|
3
3
|
"claude": {
|
|
4
4
|
"verified": "2026-07-08",
|
|
5
5
|
"models": [
|
package/SoT/toolchain.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "Kit toolchain manifest — DATA only (versions, floors, policy);
|
|
2
|
+
"$comment": "Kit toolchain manifest — DATA only (versions, floors, policy); check/install logic lives in cli/src/engine-native/toolchain.ts with per-surface sync callbacks in cli/src/engine-native/. kind: required (preflight hard dep) | check (doctor visibility only) | managed (kit installs/upgrades it) | pin (no binary probe — a version pin for a tool the kit invokes via npx). policy (managed only): track (upgrade toward latest, gated by `verified`) | present (install when missing, never upgrade). `verified` = last kit-tested version — anything above it prompts before install (--yes auto-accepts; non-TTY declines and falls back to the pinned `verified` when pinnable). Supply-chain stance: every kit-driven install is pinned to `verified` or gated by it — never floating @latest (npm-worm/Shai-Hulud surface). Update `verified` after testing a new release.",
|
|
3
3
|
"tools": {
|
|
4
|
-
"jq": { "kind": "required", "note": "
|
|
4
|
+
"jq": { "kind": "required", "note": "deployed Claude hooks/statusline assets" },
|
|
5
5
|
"curl": { "kind": "required", "note": "installers + usage fetch" },
|
|
6
6
|
"node": { "kind": "check", "note": "hosts npm globals (agent-browser, LSP servers)" },
|
|
7
7
|
"npm": { "kind": "check", "note": "npm-global installer" },
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"bwrap": { "kind": "check", "os": "linux", "note": "Codex Linux sandbox runtime" },
|
|
12
12
|
"intelephense": { "kind": "check", "verified": "1.18.5", "note": "php-lsp server binary; `verified` pins claude::sync_lsp_servers' npm install" },
|
|
13
13
|
"typescript-language-server": { "kind": "check", "verified": "5.3.0", "note": "typescript-lsp server binary; `verified` pins claude::sync_lsp_servers' npm install" },
|
|
14
|
-
"tsc": { "kind": "check", "verified": "6.0.3", "note": "typescript-lsp dependency (npm package `typescript`); `verified` pins claude::sync_lsp_servers' npm install" },
|
|
14
|
+
"tsc": { "kind": "check", "verified": "6.0.3", "note": "typescript-lsp dependency (npm package `typescript`); `verified` pins claude::sync_lsp_servers' npm install. Deliberately on the 6.x line: typescript-language-server embeds TypeScript's programmatic API, which TS7 (native) doesn't yet expose — the repo's own devDependency runs TS7 for tsc --noEmit" },
|
|
15
15
|
"rtk": { "kind": "managed", "policy": "track", "floor": "0.43.0", "verified": "0.43.0", "pinnable": true,
|
|
16
16
|
"note": "PreToolUse hook — supply-chain review before unverified upgrades; installer honors RTK_VERSION=vX.Y.Z pin" },
|
|
17
17
|
"bun": { "kind": "managed", "policy": "present", "verified": "1.3.14", "pinnable": true,
|
package/cli/docs/install.md
CHANGED
|
@@ -21,12 +21,12 @@ docks-kit sync
|
|
|
21
21
|
bunx docks-kit status
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
The npm package bundles the
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
The npm package bundles the CLI and the SoT — releases are versioned config
|
|
25
|
+
snapshots. Kit-home resolution: `DOCKS_KIT_HOME` env → nearest ancestor
|
|
26
|
+
directory containing `SoT/` + `package.json` (a checkout wins over the bundled
|
|
27
|
+
copy) → the package's own bundled SoT.
|
|
28
28
|
|
|
29
|
-
## 3. curl installer
|
|
29
|
+
## 3. curl installer (Unix-only)
|
|
30
30
|
|
|
31
31
|
```
|
|
32
32
|
curl -fsSL https://raw.githubusercontent.com/DocksDocks/public/main/install.sh -o /tmp/docks-kit-install.sh
|
|
@@ -36,21 +36,48 @@ bash /tmp/docks-kit-install.sh && rm /tmp/docks-kit-install.sh
|
|
|
36
36
|
Download-then-run, never `curl | bash` — stream truncation has bitten this
|
|
37
37
|
kit before. The installer bootstraps Bun when absent, runs
|
|
38
38
|
`bun add -g docks-kit`, and links the binary into `~/.local/bin`.
|
|
39
|
+
**Linux/macOS only** — on Windows use the compiled `.exe` or `bun add -g`
|
|
40
|
+
(both CI-verified; see below).
|
|
39
41
|
|
|
40
|
-
##
|
|
42
|
+
## Windows entrypoints
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
Two supported paths (CI-verified on windows-2025, native PowerShell):
|
|
45
|
+
|
|
46
|
+
- **Compiled binary** — `docks-kit-windows-x64.exe` release asset. No Bun,
|
|
47
|
+
no Git Bash: the exe embeds the runtime and EngineNative runs in-process.
|
|
48
|
+
It still needs the SoT it deploys — run it from inside a kit checkout, or
|
|
49
|
+
point `DOCKS_KIT_HOME` at one.
|
|
50
|
+
- **`bun add -g docks-kit`** — bun creates a working shim for the
|
|
51
|
+
`#!/usr/bin/env bun` bin; outside a checkout the package's own bundled
|
|
52
|
+
SoT is used.
|
|
53
|
+
|
|
54
|
+
`install.sh` is not a Windows path.
|
|
55
|
+
|
|
56
|
+
## Keeping the kit up to date
|
|
43
57
|
|
|
44
58
|
```
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
bash lib/engine.sh toolchain check
|
|
59
|
+
docks-kit update # autodetect + update + chained flag-less sync
|
|
60
|
+
docks-kit update --no-sync # update only
|
|
48
61
|
```
|
|
49
62
|
|
|
50
|
-
|
|
63
|
+
Autodetection: a kit home with `.git` is a checkout (requires a clean
|
|
64
|
+
worktree and an upstream; `git pull --ff-only`, re-runs
|
|
65
|
+
`bun install --frozen-lockfile` when the lockfile changed); a kit home
|
|
66
|
+
under `node_modules` is a global package (`bun add -g` /
|
|
67
|
+
`npm install -g docks-kit@latest`). A compiled binary inside a checkout
|
|
68
|
+
updates the checkout and tells you to rebuild/download the binary.
|
|
69
|
+
Every `docks-kit sync` also does a best-effort behind-upstream check and
|
|
70
|
+
nudges when the checkout is stale (silent offline / detached / no git).
|
|
71
|
+
|
|
72
|
+
## No-Bun recovery
|
|
73
|
+
|
|
74
|
+
No Bun or constrained sandbox: download the platform release binary from GitHub
|
|
75
|
+
Releases and run it from inside a kit checkout, or set `DOCKS_KIT_HOME` to the
|
|
76
|
+
checkout containing `SoT/`.
|
|
51
77
|
|
|
52
78
|
## Prerequisites
|
|
53
79
|
|
|
54
|
-
-
|
|
80
|
+
- jq and curl (sync preflight checks them for the deployed assets and installers)
|
|
81
|
+
- Bun for source/global installs; release binaries embed the runtime
|
|
55
82
|
- Node/npm for npm-global tools (agent-browser, LSP servers)
|
|
56
83
|
- See `docks-kit toolchain check` for the full picture on this machine
|
package/cli/docs/overview.md
CHANGED
|
@@ -14,9 +14,8 @@ AI-assisted dev environment on every machine.
|
|
|
14
14
|
| `SoT/.agents/` | Universal agent skills manifest (agentskills.io standard) |
|
|
15
15
|
| `SoT/models.json` | Kit-verified model catalog (see `docks-kit docs models`) |
|
|
16
16
|
| `SoT/toolchain.json` | Verified-version floors for external tools (see `docks-kit docs toolchain`) |
|
|
17
|
-
| `
|
|
18
|
-
| `
|
|
19
|
-
| `cli/` | This CLI (Effect-TS on Bun) — typed front-end over the engine |
|
|
17
|
+
| `cli/src/engine-native/` | EngineNative mutation logic for sync/model/toolchain |
|
|
18
|
+
| `cli/` | This CLI (Effect-TS on Bun) plus bundled docs |
|
|
20
19
|
| `docks-kit` | Launcher: compiled binary → bun-from-source, with Bun auto-install |
|
|
21
20
|
|
|
22
21
|
## Design rules
|
|
@@ -28,7 +27,7 @@ AI-assisted dev environment on every machine.
|
|
|
28
27
|
- **Deploy-time modifiers** mutate deployed config only — the SoT never
|
|
29
28
|
changes, and a later flag-less sync reverts them (`docks-kit docs modifiers`).
|
|
30
29
|
- **Engine/CLI split**: the CLI adds UX (typed flags, pickers, docs, JSON);
|
|
31
|
-
|
|
30
|
+
EngineNative owns mutation. No-Bun recovery is a platform release binary.
|
|
32
31
|
|
|
33
32
|
## Where to go next
|
|
34
33
|
|
package/cli/docs/platforms.md
CHANGED
|
@@ -2,30 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
| Platform | CLI (docks-kit) | Sync engine | Notes |
|
|
4
4
|
|----------|-----------------|-------------|-------|
|
|
5
|
-
| Linux | native |
|
|
6
|
-
| macOS | native (x64 + arm64) |
|
|
7
|
-
| Windows | native (
|
|
5
|
+
| Linux | native | EngineNative (TS) | Primary target |
|
|
6
|
+
| macOS | native (x64 + arm64) | EngineNative (TS) | Release binary or Bun source path |
|
|
7
|
+
| Windows | native (`.exe` / `bun add -g`, CI-verified) | EngineNative (TS) — no Git Bash | Real-machine verify pending |
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Bash for its Bash tool — so Git Bash is present on any Windows machine
|
|
13
|
-
running Claude Code), Codex CLI (native PowerShell + Windows sandbox),
|
|
14
|
-
RTK (native binaries via GitHub releases/winget — but its PreToolUse hook
|
|
15
|
-
mechanism is Unix-only; Windows falls back to RTK's `--claude-md` mode).
|
|
9
|
+
EngineNative is the only supported engine on all platforms. `DOCKS_KIT_ENGINE=bash`
|
|
10
|
+
now exits with the removed-engine message and points at the `bash-engine-final`
|
|
11
|
+
tag for historical recovery.
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
**experimental and not yet verified on a real Windows machine** — expect
|
|
19
|
-
rough edges around:
|
|
20
|
-
|
|
21
|
-
- shell-rc env exports (needs `setx` translation)
|
|
22
|
-
- the notification hook (ffplay)
|
|
23
|
-
- bubblewrap (Linux-only; skipped)
|
|
13
|
+
## Windows detail
|
|
24
14
|
|
|
25
|
-
|
|
15
|
+
Supported entrypoints (both verified in CI on windows-2025 under native
|
|
16
|
+
PowerShell — see `.github/workflows/windows-entrypoints.yml`):
|
|
26
17
|
|
|
27
|
-
|
|
18
|
+
- **`docks-kit-windows-x64.exe`** (release asset) — the no-toolchain path.
|
|
19
|
+
No Bun, no Git Bash; the exe embeds the runtime and EngineNative runs
|
|
20
|
+
in-process. It still needs the SoT it deploys: run from a kit checkout or
|
|
21
|
+
set `DOCKS_KIT_HOME`.
|
|
22
|
+
- **`bun add -g docks-kit`** — bun creates a working Windows shim for the
|
|
23
|
+
`#!/usr/bin/env bun` bin; outside a checkout kit-home resolves to the
|
|
24
|
+
package's own bundled SoT.
|
|
25
|
+
- `install.sh` is **Unix-only** and not a Windows path.
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
The managed tools all run natively on Windows: Claude Code (requires Git
|
|
28
|
+
Bash for its own Bash tool — that requirement is Claude Code's, not this
|
|
29
|
+
kit's), Codex CLI (native PowerShell + Windows sandbox), RTK (native
|
|
30
|
+
binaries; since rtk 0.37.2 the PreToolUse hook is a native binary command —
|
|
31
|
+
`rtk hook claude`, no shell or jq. Only the kit's *auto-installer* is
|
|
32
|
+
Unix-only: install rtk natively, then sync).
|
|
33
|
+
|
|
34
|
+
CI coverage (all on the pinned windows-2025 label): EngineNative PowerShell
|
|
35
|
+
smoke with `HOME` unset — `%USERPROFILE%` path resolution, `.cmd` tool
|
|
36
|
+
spawning (npm), toolchain gate branches (`.github/workflows/parity.yml`,
|
|
37
|
+
`native-windows` job); the two entrypoints above (`windows-entrypoints.yml`).
|
|
38
|
+
Deployed hook/statusline assets stay shell scripts by design — Claude Code on
|
|
39
|
+
Windows executes them through its own Git Bash.
|
|
40
|
+
|
|
41
|
+
**Status: supported, pending one manual gate** — a real-machine interactive
|
|
42
|
+
verify (Claude Code loads the synced `%USERPROFILE%\.claude`, the rtk hook
|
|
43
|
+
fires, hook/statusline commands run or are knowingly skipped) tracked as
|
|
44
|
+
step 9 of the `windows-support` plan.
|
package/cli/src/commands/sync.ts
CHANGED
|
@@ -1,13 +1,38 @@
|
|
|
1
1
|
import { Args, Command, Options } from "@effect/cli"
|
|
2
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"
|
|
3
6
|
import { bail, engine } from "../engine"
|
|
7
|
+
import { kitHome } from "../kitHome"
|
|
4
8
|
import { modelCatalog, type Tool } from "../manifests"
|
|
5
9
|
|
|
10
|
+
/** Best-effort update autodetection: nudge (never block, never fail) when
|
|
11
|
+
* the kit checkout is behind its upstream. Silent on detached HEADs, no
|
|
12
|
+
* upstream, no network, no git. */
|
|
13
|
+
const updateNudge = (): void => {
|
|
14
|
+
try {
|
|
15
|
+
const home = kitHome()
|
|
16
|
+
if (!existsSync(join(home, ".git"))) return
|
|
17
|
+
if (spawnSync("git", ["-C", home, "fetch", "--quiet"], { stdio: "ignore", timeout: 4000 }).status !== 0) return
|
|
18
|
+
const res = spawnSync("git", ["-C", home, "rev-list", "--count", "HEAD..@{u}"], {
|
|
19
|
+
encoding: "utf8",
|
|
20
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
21
|
+
})
|
|
22
|
+
const behind = (res.stdout ?? "").trim()
|
|
23
|
+
if (res.status === 0 && behind !== "" && behind !== "0") {
|
|
24
|
+
process.stderr.write(`\x1b[1;33m[warn]\x1b[0m kit checkout is ${behind} commit(s) behind its upstream — run: docks-kit update\n`)
|
|
25
|
+
}
|
|
26
|
+
} catch {
|
|
27
|
+
// nudge only — a sync must never fail because the update check did
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
6
31
|
const VALID_TARGETS = ["claude", "codex", "agents"]
|
|
7
32
|
|
|
8
|
-
// Renamed
|
|
9
|
-
// positional args, so the rename hints
|
|
10
|
-
//
|
|
33
|
+
// Renamed pre-CLI flags: @effect/cli routes unknown flags into the excess
|
|
34
|
+
// positional args, so the rename hints are mirrored here before EngineNative
|
|
35
|
+
// sees the normalized argv.
|
|
11
36
|
const LEGACY_HINTS: Record<string, string> = {
|
|
12
37
|
"--force": "--force was renamed to --reconcile",
|
|
13
38
|
"--remove-plugins":
|
|
@@ -125,10 +150,13 @@ export const syncCommand = Command.make(
|
|
|
125
150
|
.forEach((p) => args.push(`--claude-plugin=${p}`))
|
|
126
151
|
}
|
|
127
152
|
|
|
153
|
+
// Not on --dry-run: the nudge's git fetch writes FETCH_HEAD/remote
|
|
154
|
+
// refs, and a preview command must not mutate the checkout.
|
|
155
|
+
if (!config.dryRun) yield* Effect.sync(updateNudge)
|
|
128
156
|
yield* engine(args)
|
|
129
157
|
})
|
|
130
158
|
).pipe(
|
|
131
159
|
Command.withDescription(
|
|
132
|
-
"Deploy the SoT to this machine
|
|
160
|
+
"Deploy the SoT to this machine with EngineNative. Deploy-time modifiers touch deployed config only; a later flag-less sync reverts them to SoT."
|
|
133
161
|
)
|
|
134
162
|
)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Command, Options } from "@effect/cli"
|
|
2
|
+
import { Console, Effect } from "effect"
|
|
3
|
+
import { spawnSync } from "node:child_process"
|
|
4
|
+
import { existsSync } from "node:fs"
|
|
5
|
+
import { join } from "node:path"
|
|
6
|
+
import { bail, compiled } from "../engine"
|
|
7
|
+
import { kitHome } from "../kitHome"
|
|
8
|
+
|
|
9
|
+
const noSync = Options.boolean("no-sync").pipe(
|
|
10
|
+
Options.withDescription("Update the kit only; skip the chained flag-less sync")
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
const git = (home: string, args: Array<string>): { ok: boolean; out: string } => {
|
|
14
|
+
const res = spawnSync("git", ["-C", home, ...args], {
|
|
15
|
+
encoding: "utf8",
|
|
16
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
17
|
+
})
|
|
18
|
+
return { ok: res.error === undefined && res.status === 0, out: `${res.stdout ?? ""}${res.stderr ?? ""}`.trim() }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Spawn the freshly-updated code — the running process still has the old
|
|
22
|
+
* version loaded, so the chained sync must be a new process. */
|
|
23
|
+
const chainSync = (argv0: string, args: Array<string>): Effect.Effect<void> =>
|
|
24
|
+
Effect.sync(() => {
|
|
25
|
+
const res = spawnSync(argv0, args, { stdio: "inherit" })
|
|
26
|
+
if (res.error !== undefined || res.status !== 0) process.exit(res.status ?? 1)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const updateCheckout = (home: string, skipSync: boolean) =>
|
|
30
|
+
Effect.gen(function* () {
|
|
31
|
+
if (spawnSync("git", ["--version"], { stdio: "ignore" }).status !== 0) {
|
|
32
|
+
return yield* bail("git not found - cannot update the kit checkout")
|
|
33
|
+
}
|
|
34
|
+
const dirty = git(home, ["status", "--porcelain"])
|
|
35
|
+
if (!dirty.ok) return yield* bail(`git status failed in ${home}: ${dirty.out}`)
|
|
36
|
+
if (dirty.out !== "") {
|
|
37
|
+
return yield* bail(`kit checkout ${home} has local changes - commit or stash them, then re-run docks-kit update`)
|
|
38
|
+
}
|
|
39
|
+
const upstream = git(home, ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"])
|
|
40
|
+
if (!upstream.ok) {
|
|
41
|
+
return yield* bail("current branch has no upstream - set one (git branch --set-upstream-to) or update manually")
|
|
42
|
+
}
|
|
43
|
+
const before = git(home, ["rev-parse", "HEAD"]).out
|
|
44
|
+
const pull = git(home, ["pull", "--ff-only"])
|
|
45
|
+
if (!pull.ok) return yield* bail(`git pull --ff-only failed (diverged history?):\n${pull.out}`)
|
|
46
|
+
const after = git(home, ["rev-parse", "HEAD"]).out
|
|
47
|
+
|
|
48
|
+
if (before === after) {
|
|
49
|
+
return yield* Console.log(`Already up to date (${after.slice(0, 7)}, upstream ${upstream.out}).`)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const count = git(home, ["rev-list", "--count", `${before}..${after}`]).out
|
|
53
|
+
yield* Console.log(`Updated ${before.slice(0, 7)}..${after.slice(0, 7)} (${count} commit(s) from ${upstream.out}).`)
|
|
54
|
+
|
|
55
|
+
const touched = git(home, ["diff", "--name-only", before, after]).out.split("\n")
|
|
56
|
+
if (touched.includes("bun.lock") || touched.includes("package.json")) {
|
|
57
|
+
const res = spawnSync("bun", ["install", "--frozen-lockfile"], { cwd: home, stdio: "inherit" })
|
|
58
|
+
if (res.error !== undefined || res.status !== 0) {
|
|
59
|
+
return yield* bail("dependencies changed but 'bun install --frozen-lockfile' failed - fix that, then run docks-kit sync", 1)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (compiled) {
|
|
64
|
+
return yield* Console.log(
|
|
65
|
+
"This compiled binary still runs the previous version - rebuild (bash cli/build-binaries.sh) or download the latest release binary, then run: docks-kit sync"
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
if (skipSync) return yield* Console.log("Kit updated. Run: docks-kit sync")
|
|
69
|
+
yield* Console.log("Kit updated - running sync with the new version...")
|
|
70
|
+
return yield* chainSync(process.execPath, [join(home, "cli/src/main.ts"), "sync"])
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const updatePackage = (home: string, skipSync: boolean) =>
|
|
74
|
+
Effect.gen(function* () {
|
|
75
|
+
// Bun's global dir is configurable (BUN_INSTALL_GLOBAL_DIR / BUN_INSTALL),
|
|
76
|
+
// so the ~/.bun path shape alone under-detects Bun installs.
|
|
77
|
+
const underEnvDir = (v: string): boolean => {
|
|
78
|
+
const dir = process.env[v]
|
|
79
|
+
return dir !== undefined && dir !== "" && home.startsWith(dir)
|
|
80
|
+
}
|
|
81
|
+
const viaBun =
|
|
82
|
+
home.includes("/.bun/") ||
|
|
83
|
+
home.includes("\\.bun\\") ||
|
|
84
|
+
underEnvDir("BUN_INSTALL_GLOBAL_DIR") ||
|
|
85
|
+
underEnvDir("BUN_INSTALL")
|
|
86
|
+
const res = viaBun
|
|
87
|
+
? spawnSync("bun", ["add", "-g", "docks-kit@latest"], { stdio: "inherit" })
|
|
88
|
+
: spawnSync("npm", ["install", "-g", "docks-kit@latest"], { stdio: "inherit" })
|
|
89
|
+
if (res.error !== undefined || res.status !== 0) {
|
|
90
|
+
return yield* bail(`global package update failed (${viaBun ? "bun add -g" : "npm install -g"} docks-kit@latest)`, 1)
|
|
91
|
+
}
|
|
92
|
+
if (skipSync) return yield* Console.log("Kit updated. Run: docks-kit sync")
|
|
93
|
+
yield* Console.log("Kit updated - running sync with the new version...")
|
|
94
|
+
// Chain through the package dir just updated (global installs update in
|
|
95
|
+
// place) — a bare `docks-kit` PATH lookup could hit a different shim.
|
|
96
|
+
return yield* chainSync(process.execPath, [join(home, "cli/src/main.ts"), "sync"])
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
export const updateCommand = Command.make("update", { noSync }, (config) =>
|
|
100
|
+
Effect.gen(function* () {
|
|
101
|
+
const home = kitHome()
|
|
102
|
+
if (existsSync(join(home, ".git"))) {
|
|
103
|
+
return yield* updateCheckout(home, config.noSync)
|
|
104
|
+
}
|
|
105
|
+
if (home.includes("node_modules")) {
|
|
106
|
+
return yield* updatePackage(home, config.noSync)
|
|
107
|
+
}
|
|
108
|
+
return yield* bail(
|
|
109
|
+
`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)`
|
|
110
|
+
)
|
|
111
|
+
})
|
|
112
|
+
).pipe(
|
|
113
|
+
Command.withDescription(
|
|
114
|
+
"Self-update the kit: autodetects the install (git checkout -> ff-only pull; bun/npm global -> @latest) and chains a flag-less sync with the new version (--no-sync to skip)."
|
|
115
|
+
)
|
|
116
|
+
)
|