@crvouga/dev-fleet 0.1.0 → 0.2.0

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 (110) hide show
  1. package/README.md +237 -37
  2. package/agents/setup.md +42 -12
  3. package/ansible/macos/manager.yml +7 -7
  4. package/ansible/macos/policy.json +2 -10
  5. package/ansible/monitoring/README.md +86 -25
  6. package/ansible/monitoring/agent.yml +40 -2
  7. package/ansible/monitoring/hub-route-darwin.yml +51 -0
  8. package/ansible/monitoring/lock.json +5 -0
  9. package/ansible/pyproject.toml +12 -0
  10. package/ansible/ubuntu/baseline.yml +1 -1
  11. package/ansible/ubuntu/disk-gc.py +336 -0
  12. package/ansible/ubuntu/policy.json +12 -3
  13. package/ansible/ubuntu/tailscale.yml +8 -5
  14. package/ansible/ubuntu/tasks/resources.yml +61 -1
  15. package/ansible/uv.lock +190 -0
  16. package/bootstrap/bootstrap.sh +25 -18
  17. package/bootstrap/doctor.ts +46 -1
  18. package/bootstrap/fleet-manager-run.sh +42 -15
  19. package/bootstrap/fleet-remote-bootstrap.sh +85 -12
  20. package/bootstrap/global-config.ts +64 -6
  21. package/bootstrap/install-launcher.sh +3 -0
  22. package/bootstrap/npm.ts +10 -2
  23. package/bootstrap/release-version.ts +157 -0
  24. package/docs/consumer-setup.md +408 -0
  25. package/docs/declared.md +89 -0
  26. package/docs/machine-setup.md +399 -0
  27. package/docs/operations.md +276 -0
  28. package/docs/releasing.md +103 -0
  29. package/docs/state.md +254 -0
  30. package/docs/topology.md +67 -0
  31. package/docs/ubuntu-sync.md +351 -0
  32. package/docs/worker-contract.md +67 -0
  33. package/examples/fleet.json +5 -0
  34. package/llms.txt +35 -0
  35. package/mise.lock +29 -0
  36. package/mise.toml +12 -1
  37. package/package.json +11 -2
  38. package/schema/fleet.schema.json +71 -15
  39. package/src/agents/fleet-verify.ts +9 -0
  40. package/src/agents/native-verify.ts +167 -22
  41. package/src/agents/provider-errors.ts +9 -2
  42. package/src/agents/registry.ts +7 -1
  43. package/src/cli/agent-guide.ts +39 -5
  44. package/src/cli/app.ts +11 -4
  45. package/src/cli/cli.ts +7 -0
  46. package/src/cli/command-index.ts +7 -0
  47. package/src/cli/fleet-state.ts +499 -0
  48. package/src/cli/fleet-sync-checkout.ts +56 -17
  49. package/src/cli/fleet-sync-enrollment.ts +19 -23
  50. package/src/cli/fleet-sync-forward.ts +1 -1
  51. package/src/cli/fleet-sync-manager.ts +64 -8
  52. package/src/cli/fleet-sync-monitoring.ts +5 -5
  53. package/src/cli/fleet-sync-output.ts +4 -1
  54. package/src/cli/fleet-sync-remote.ts +11 -5
  55. package/src/cli/fleet-sync-state.ts +86 -0
  56. package/src/cli/fleet-sync.ts +123 -57
  57. package/src/cli/fleet.ts +4 -2
  58. package/src/cli/managed-health.ts +4 -4
  59. package/src/cli/node-sync.ts +7 -0
  60. package/src/cli/program.ts +20 -4
  61. package/src/cli/project.ts +51 -0
  62. package/src/cli/register-fleet.ts +51 -1
  63. package/src/cli/registry.ts +28 -1
  64. package/src/cli/roster.ts +46 -30
  65. package/src/cli/settings.ts +15 -12
  66. package/src/cli/source-operations.ts +27 -3
  67. package/src/cli/tailnet.ts +2 -2
  68. package/src/definition.ts +31 -1
  69. package/src/diagnostics.ts +1 -1
  70. package/src/fleet-config.ts +105 -19
  71. package/src/machine/source.ts +3 -3
  72. package/src/machine/state.ts +15 -27
  73. package/src/manager-sync.ts +8 -3
  74. package/src/monitoring/agent-evidence.ts +146 -0
  75. package/src/monitoring/apply.ts +15 -3
  76. package/src/monitoring/beszel.ts +11 -4
  77. package/src/monitoring/enroll.ts +2 -1
  78. package/src/monitoring/hub-access.ts +4 -3
  79. package/src/monitoring/hub-backup.ts +121 -0
  80. package/src/monitoring/hub-viewer.ts +8 -8
  81. package/src/monitoring/hub.ts +3 -3
  82. package/src/monitoring/manager-hub.ts +30 -14
  83. package/src/node-converge-linux.ts +2 -0
  84. package/src/package-info.ts +45 -0
  85. package/src/platform/ansible.ts +19 -15
  86. package/src/platform/resource-verify.ts +8 -4
  87. package/src/platform/ubuntu-audit.ts +5 -2
  88. package/src/remote-bootstrap.ts +17 -19
  89. package/src/repair-catalog.ts +1 -1
  90. package/src/runner.ts +1 -1
  91. package/src/state/bucket.ts +208 -0
  92. package/src/state/check.ts +74 -0
  93. package/src/state/connection.ts +92 -0
  94. package/src/state/enrollment.ts +45 -0
  95. package/src/state/legacy.ts +89 -0
  96. package/src/state/litestream.ts +143 -0
  97. package/src/state/operator.ts +20 -0
  98. package/src/state/paths.ts +40 -0
  99. package/src/state/roster.ts +62 -0
  100. package/src/state/store.ts +169 -0
  101. package/src/state/sync.ts +352 -0
  102. package/src/t3-endpoint.ts +64 -8
  103. package/src/t3-linked-check.ts +23 -1
  104. package/src/toolchain-checks.ts +25 -0
  105. package/src/types.ts +4 -0
  106. package/src/worker-access-checks.ts +56 -3
  107. package/src/worker-host-checks.ts +5 -0
  108. package/src/workstation-checks.ts +1 -1
  109. package/src/index.ts +0 -6
  110. package/src/test-fixtures.ts +0 -36
@@ -0,0 +1,399 @@
1
+ > This document was written for the fleet dev-fleet was extracted from. Paths and
2
+ > commands were updated; some statements still describe that fleet and are being
3
+ > revised. The README is authoritative.
4
+
5
+ ## Machine setup: macOS, Windows and Linux
6
+
7
+ This is the shared development setup for **crvouga/dev-fleet**. One versioned
8
+ manifest, `mise.toml`, owns the developer tools; `mise.lock` and `.mise/locks/`
9
+ own resolved artifacts and dependency graphs. Both bootstraps apply that same
10
+ manifest to the current user globally. Other projects can override versions with
11
+ their own mise configuration. No paid account or cloud secrets are needed to
12
+ install the toolchain.
13
+
14
+ ### New machine
15
+
16
+ A manager or a worker is set up by `fleet-sync`, run from the published
17
+ package ([README](../README.md#quickstart)): it checks out the revision on the
18
+ machine and runs `bootstrap/bootstrap.sh` from that checkout. Nothing is
19
+ downloaded and run by hand.
20
+
21
+ To develop dev-fleet, run `bash bootstrap/bootstrap.sh` from a checkout. The
22
+ script only ever installs the toolchain of the checkout it is in.
23
+
24
+ Native Windows, in x64 PowerShell (5.1 or newer):
25
+
26
+ ```powershell
27
+ Invoke-WebRequest https://raw.githubusercontent.com/crvouga/dev-fleet/main/bootstrap/bootstrap.ps1 -OutFile "$env:TEMP\workspace-bootstrap.ps1"
28
+ & "$env:TEMP\workspace-bootstrap.ps1"
29
+ ```
30
+
31
+ If script execution is blocked, use a process-scoped policy for this reviewed
32
+ script: `powershell -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\workspace-bootstrap.ps1"`.
33
+ Do not change the machine-wide execution policy. WSL is optional: run the Linux
34
+ bootstrap **inside WSL**, from a checkout there, to install Linux tools; the
35
+ native Windows and WSL tool installations, Docker connections and credentials
36
+ are separate.
37
+
38
+ On Windows the default checkout is `~\workspace`; override it with
39
+ `-WorkspaceDir C:\path\workspace`. An existing checkout is reused, never reset
40
+ or implicitly pulled. From a checkout, run `& ./bootstrap/bootstrap.ps1`.
41
+
42
+ The scripts install checksum-verified mise **2026.10.24**, trust this repository's
43
+ configuration, install pinned Bun, install the shared tools with `--locked`, copy
44
+ the managed global config/lock/sidecars, set up persistent shims on PATH, and run
45
+ `bun install --frozen-lockfile`. The published global config also trusts the
46
+ agent worktree roots in `AGENT_WORKTREE_ROOTS` (`bootstrap/global-config.ts`,
47
+ currently `~/.t3/worktrees`): each agent task gets a new checkout, and an
48
+ untrusted `mise.toml` there makes every mise shim, `claude` and `bun` included,
49
+ exit before the agent starts. Entries added locally with
50
+ `mise settings add trusted_config_paths PATH` are kept on every publish.
51
+ Reopen your terminal/editor afterward. To refresh
52
+ an already-open Unix terminal immediately, run `exec "$SHELL" -l`; an installer
53
+ cannot change its parent shell's environment. **If `bun` or `mise` is missing,
54
+ run `bash bootstrap/bootstrap.sh` from this checkout first, not a Bun command.**
55
+ Unix PATH blocks cover `.profile`, existing `.bash_profile`/`.bash_login`,
56
+ `.bashrc`, `.zshenv`, `.zshrc` and fish's config. Zsh uses `ZDOTDIR` when set.
57
+ POSIX blocks are quiet, idempotent
58
+ and placed before interactive-only early returns, so noninteractive SSH/agent
59
+ commands can find the same shims without loading an interactive UI;
60
+ Windows updates only the user's PATH; AWS CLI v2 additionally uses the official
61
+ versioned MSI (a UAC prompt may appear) because mise's AWS recipe supports only
62
+ macOS/Linux. Its version comes from the same manifest and its Windows SHA-256 is
63
+ pinned in `vars.aws_windows_msi_sha256`; no unversioned installer is executed.
64
+ CI/non-interactive setup never opens an elevation prompt and requires an
65
+ administrator context if that MSI needs installation. Existing unrelated mise config/lockfiles
66
+ are refused: back them up and move them first, then merge intentional overrides
67
+ using project configs. `MISE_CONFIG_DIR` and `XDG_CONFIG_HOME` are respected for
68
+ configuration; the PATH step also respects `MISE_DATA_DIR`, `XDG_DATA_HOME` and
69
+ `MISE_SHIMS_DIR`, including Windows' `%LOCALAPPDATA%` default.
70
+
71
+ Fleet's remote bootstrap invokes this same owner with a private `--status-file`
72
+ path. The JSON record contains only a version, installer phase and status, never
73
+ commands or raw errors. It is diagnostic progress, not proof of fleet readiness.
74
+ The native T3 archive verifier checks actual content, modes, links and ownership
75
+ by the development user; archive-builder numeric user/group IDs are not portable.
76
+ A mismatch leaves the running service and application state untouched.
77
+
78
+ ### OS prerequisites and supported platforms
79
+
80
+ - **macOS x64 / Apple Silicon:** install Apple's Command Line Tools. If Git is
81
+ absent, bootstrap launches `xcode-select --install`, stops, and asks you to rerun
82
+ after installation. These tools provide Git and native compilers. `curl`, `tar`
83
+ and `unzip` must be available.
84
+ - **Linux x64 / arm64, glibc:** Git, curl, trusted CA certificates, tar, unzip, xz
85
+ and a C/C++ compiler/make. If Git is absent, bootstrap installs prerequisites
86
+ with `sudo apt-get` or `sudo dnf`; other distributions receive an actionable
87
+ error. On Debian/Ubuntu with Git already installed, use
88
+ `sudo apt-get install git curl ca-certificates tar unzip xz-utils build-essential`.
89
+ Alpine/musl is not in this baseline.
90
+ - **Native Windows x64:** Git for Windows (includes OpenSSH and Git Bash).
91
+ Bootstrap installs it through WinGet if missing; without WinGet, install Git
92
+ from https://git-scm.com/download/win. Windows ARM64 is not yet validated.
93
+ For packages with native C/C++ addons, install Visual Studio Build Tools with
94
+ the Desktop development with C++ workload and Windows SDK. Enable Developer
95
+ Mode if using workstation symlink features; core toolchain setup uses copies
96
+ and does not require symlinks or an administrator shell.
97
+
98
+ Git, OS compilers/SDKs, Docker Engine/Desktop, desktop apps, and kernel versions
99
+ are **OS prerequisites**, not covered by the mise lock. The same tool versions
100
+ are selected across OSes, using different platform binaries; this does not make
101
+ all OS behavior or every project command identical. Existing infrastructure
102
+ scripts may require Bash/Unix tooling; use Git Bash where supported or WSL for
103
+ Linux-specific workflows. Exact container builds should pin base image digests.
104
+
105
+ ### Included toolchain
106
+
107
+ The generated guide includes the exact tool table from `mise.toml` below. Scope:
108
+
109
+ - **Source control:** OS Git/OpenSSH, pinned GitHub CLI and Git LFS.
110
+ - **JavaScript/TypeScript:** Node **with npm**, Bun, pnpm, Yarn and Deno.
111
+ TypeScript, ESLint, Prettier, Turbo and test frameworks remain project
112
+ dependencies installed from `bun.lock`; do not install duplicate global copies.
113
+ - **Languages/builds:** Python (precompiled), uv/uvx, Go, Rust/Cargo/rustfmt/Clippy,
114
+ CMake, Ninja and Just. OS compilers/linkers remain prerequisites: Apple Command
115
+ Line Tools, Linux build-essential/GCC, or Windows MSVC Build Tools + SDK.
116
+ Java (Temurin 25 LTS) and .NET 10 SDK are locked on-demand tools.
117
+ Project manifests still select project-specific language/library versions.
118
+ - **CLI utilities:** ripgrep (`rg`), fd, fzf, bat, delta, jq and Mike Farah yq.
119
+ - **Delivery/infra:** Vercel, Wrangler, Railway, OpenTofu, Vault CLI (for the OpenBao-compatible secret service), Docker CLI,
120
+ ShellCheck, shfmt, actionlint, AWS CLI v2, kubectl and Helm. Installing provider CLIs does not authorize agents
121
+ to provision resources; shared infrastructure is still OpenTofu-owned.
122
+ - **Agent harnesses:** Claude Code (`claude`), Codex (`codex`), Gemini CLI
123
+ (`gemini`), GitHub Copilot CLI (`copilot`) and OpenCode (`opencode`).
124
+ Installed versions are checked by doctor on all three OSes. Start the CLI you
125
+ want to use and complete its interactive sign-in; installation does not copy
126
+ tokens, choose paid plans or grant agent permissions. OpenCode's optional
127
+ settings remain managed by `personal` and Vault. Codex sign-in follows the
128
+ [official CLI guide](https://learn.chatgpt.com/docs/codex/cli).
129
+ Claude/Copilot background self-updaters are disabled through mise environment
130
+ settings so they cannot silently replace locked versions; update through this
131
+ repository instead.
132
+ - **Security/data/HTTP:** Gitleaks for secret scanning, SOPS + age for encrypted
133
+ files, xh for HTTP requests, and usql for SQL database connections. Installing
134
+ these tools does not create encryption keys or copy credentials.
135
+ - **Agent/container development:** Dev Containers CLI (`devcontainer`) is included.
136
+ MCP Inspector is pinned on demand; use it only for the MCP server you intend
137
+ to inspect, and follow the tool's local access instructions.
138
+ - **On demand:** Atlas (macOS/Linux), Azure CLI, Google Cloud CLI, AWS CDK/SAM,
139
+ Java/.NET SDKs and MCP Inspector are locked lazy tools. Install one with
140
+ `mise install --locked <tool>`, for example `mise install --locked gcloud`, or
141
+ install the whole catalog with `mise install --locked --include-lazy`.
142
+ AWS SAM is currently macOS/Linux only in mise; native Windows users can use
143
+ AWS's supported SAM installer when their project needs it.
144
+ Lazy tools are excluded from the base doctor's required checks; large SDKs
145
+ may require their documented OS prerequisites and project-specific versions.
146
+
147
+ **nvm is intentionally replaced by mise's Node version management.** Unix nvm
148
+ and nvm-windows are different implementations. Use `mise use node@<version>` in
149
+ a project instead of `nvm install/use`; root `.nvmrc` remains a compatibility pin
150
+ for existing CI. Remove/disable old nvm, fnm, asdf or Volta shell initialization
151
+ if it shadows managed tools. Never silently delete another manager's files.
152
+ Do not independently upgrade npm, Corepack shims, or globally npm-install tools
153
+ already owned by mise. The npm version comes from the pinned Node release.
154
+
155
+ ### Verify, authenticate and configure
156
+
157
+ After reopening the shell:
158
+
159
+ ```sh
160
+ cd ~/workspace
161
+ mise exec -- bun bootstrap/doctor.ts
162
+ mise exec -- bun bootstrap/doctor.ts --json
163
+ # Require a working container runtime and both plugins:
164
+ mise exec -- bun bootstrap/doctor.ts --docker
165
+ ```
166
+
167
+ Doctor fails missing/wrong required tool versions and missing Git/npm. Missing
168
+ GitHub authentication and Docker runtime/plugins are warnings unless Docker is
169
+ explicitly required. `--json` emits structured checks without credential values.
170
+ `mise doctor` diagnoses mise itself. Use `where.exe node` / `Get-Command node -All`
171
+ on Windows, or `type -a node` on Unix, to find conflicting installations.
172
+
173
+ Authentication remains per-machine and interactive; never copy tokens into Git:
174
+
175
+ ```sh
176
+ gh auth login
177
+ gh auth setup-git
178
+ gh auth status
179
+ vercel login
180
+ wrangler login
181
+ railway login
182
+ ```
183
+
184
+ Only sign into providers the task actually needs. Git identity is personal:
185
+ set `git config --global user.name` and `git config --global user.email` after
186
+ confirming the desired name/email. Do not guess an email or overwrite an existing
187
+ identity. Enable Git LFS hooks when needed with `git lfs install`.
188
+
189
+ Optional existing workstation/agent settings:
190
+
191
+ ```sh
192
+ sh bootstrap/install-launcher.sh
193
+ personal workstation doctor
194
+ # Only for tasks needing the workspace's managed secrets:
195
+ vault login --method=userpass username=example-user
196
+ personal workstation sync
197
+ ```
198
+
199
+ The machine bootstrap installs tools/dependencies only. `personal:install` additionally
200
+ installs the existing workstation launcher and converges OpenCode configuration;
201
+ it may need platform permissions and a Vault login for credential-backed
202
+ features. `bun run setup` remains dependency installation only.
203
+
204
+ ### Working with modern repositories
205
+
206
+ After bootstrap, clone with `gh repo clone owner/repo`, read that repository's
207
+ `AGENTS.md`/README and language manifests, and trust its mise config only after
208
+ review. Use its lockfile and declared package manager: `bun install --frozen-lockfile`,
209
+ `npm ci`, `pnpm install --frozen-lockfile`, `yarn install --immutable`,
210
+ `uv sync --locked`, `cargo build --locked` or `go mod download` as appropriate.
211
+ Do not install global copies of project-owned TypeScript, ESLint, Prettier, test
212
+ frameworks or SDK libraries. For a `.devcontainer` project, use
213
+ `devcontainer up --workspace-folder .` after Docker readiness succeeds.
214
+
215
+ Database servers (PostgreSQL, MySQL, Redis, etc.) and local services belong in
216
+ the project's versioned Compose/devcontainer configuration. The shared setup
217
+ provides the Docker and SQL clients; it does not start unrequested background
218
+ servers or occupy their ports. Python and Bun provide SQLite support without
219
+ requiring a separate global database daemon. Mobile/iOS/Android toolchains and
220
+ platform-specific native dependencies remain project/OS prerequisites.
221
+
222
+ Cloud sign-in is per machine: `aws configure sso` / `aws sso login`,
223
+ `gcloud auth login` and `az login` only when the task needs that provider.
224
+ Use named profiles and existing credentials; never put access keys in this repo.
225
+ Kubernetes contexts, cloud resource creation and production deployment still
226
+ follow each repository's authorization and IaC rules.
227
+
228
+ ### Containers: CLI versus engine
229
+
230
+ The manifest installs the **Docker client**. Containers also require a local or
231
+ remote Docker engine, Compose v2 and Buildx plugins. These cannot be installed as
232
+ one identical unprivileged binary on all OSes.
233
+
234
+ - **macOS:** run `personal workstation tools docker-setup` to install the pinned,
235
+ checksum-verified Docker Desktop bundle from this repository and open it.
236
+ Complete its first-run agreement/setup in the app. Repeated invocation reuses
237
+ an existing installation. The shared mise Docker client remains in use.
238
+ Vendor installation documentation: Docker Desktop from https://docs.docker.com/desktop/setup/install/mac-install/.
239
+ - **Windows:** install/start Docker Desktop from https://docs.docker.com/desktop/setup/install/windows-install/.
240
+ `winget install --exact --id Docker.DockerDesktop` is the package-manager route.
241
+ Enable its WSL2 backend/virtualization prerequisites and finish any reboot.
242
+ - **Linux:** follow https://docs.docker.com/engine/install/ for the distribution.
243
+ Install Engine plus `docker-buildx-plugin` and `docker-compose-plugin`, then
244
+ start the daemon (usually `sudo systemctl enable --now docker`). Use Docker's
245
+ documented rootless mode when appropriate. Adding a user to the `docker` group
246
+ grants root-equivalent access; do not do so silently in bootstrap.
247
+ - **Remote/headless:** select a preconfigured Docker context instead. Do not
248
+ overwrite an existing context or expose an unauthenticated TCP daemon.
249
+
250
+ Docker Desktop supplies Compose/Buildx. On Linux they must be installed as CLI
251
+ plugins. The pinned mise client should discover plugins in standard Docker
252
+ locations; if not, check `docker info` and configure Docker's `cliPluginsExtraDirs`
253
+ for that installation. Verify with `docker version`, `docker compose version`,
254
+ `docker buildx version`, and optionally `docker run --rm hello-world` (downloads
255
+ an image). CLI pinning does not pin or upgrade your engine/plugins.
256
+
257
+ ### Lockfile coverage and reviewed package metadata
258
+
259
+ Most binary tools have platform URLs/checksums in `mise.lock`; npm/Python tools
260
+ also have dependency graphs in `.mise/locks/`. Rust is managed by the native
261
+ Rustup backend: mise pins the exact release, and Rustup verifies its versioned
262
+ component distribution manifests rather than recording component hashes in mise's
263
+ lock. AWS Windows uses the reviewed MSI checksum in the same manifest.
264
+
265
+ MCP Inspector's dependency graph currently selects the manually published Pino
266
+ 9.14.0 backport, whose npm publisher metadata differs from the newer 10.x trusted
267
+ publisher stream. The manifest's single-version trust-policy exception was added
268
+ after verifying npm's SHA-512 integrity and all 139 published JavaScript files
269
+ against `pinojs/pino`'s `v9.14.0` tag, plus matching package scripts/dependencies.
270
+ The frozen graph still verifies its artifact integrity; no global trust checks
271
+ are disabled. Remove that narrow exception when the upstream metadata is fixed.
272
+
273
+ ### Keep machines synchronized
274
+
275
+ From the checkout, on any platform:
276
+
277
+ ```sh
278
+ git pull --ff-only
279
+ mise install --locked bun
280
+ mise exec --locked bun -- bun bootstrap/setup.ts
281
+ ```
282
+
283
+ For an installed workstation CLI, `personal workstation update` pulls with a clean-tree/fast-forward
284
+ guard, refreshes the toolchain/global config and frozen dependencies, and runs the
285
+ existing workstation convergence. `personal workstation tools sync` reapplies tool pins/global config
286
+ without pulling or touching project dependencies; `personal workstation tools check --json` verifies
287
+ them. Sync is explicit; Git commits do not silently update other machines.
288
+
289
+ For multiple development computers, use [the fleet package](operations.md):
290
+ `devfleet fleet-node-add` registers an existing SSH alias in a local roster,
291
+ `devfleet fleet-nodes --onboard` generates per-node connection/auth/editor steps,
292
+ and `devfleet fleet-status --json` diagnoses SSH, authentication, T3 Connect
293
+ settings/API and checkout/lockfile drift. `devfleet fleet-repair --repair workspace`
294
+ previews convergence through this same setup script; applying requires
295
+ `--apply --yes`. No credentials are copied or cloud resources provisioned;
296
+ VS Code/T3 end-to-end tests remain explicit operator steps.
297
+
298
+ Bootstrap each node once using the same reviewed checkout revision, then check
299
+ tool discovery through its actual SSH alias (not just an interactive terminal):
300
+
301
+ ```sh
302
+ ssh YOUR_ALIAS 'command -v mise; command -v bun; command -v node; command -v npm'
303
+ devfleet fleet-status --json
304
+ devfleet fleet-repair --repair workspace
305
+ devfleet fleet-repair --repair workspace --apply --yes
306
+ ```
307
+
308
+ Review the sync plan before applying. SSH must already work and nodes must be in
309
+ your local fleet roster; bootstrap does not create accounts, pair T3, authorize
310
+ SSH keys or copy credentials. Remote Bash sessions depend on sshd sourcing
311
+ `.bashrc`; shells launched with startup files disabled need an explicit PATH or
312
+ the absolute `~/.local/bin/mise exec --locked -- COMMAND` entry point. On Windows,
313
+ restart the parent editor/agent process to inherit the updated user PATH.
314
+
315
+ To change versions: edit pins with `mise use --pin <tool>@<version>` (or edit
316
+ `mise.toml`), run `mise lock`, review `mise.toml`, `mise.lock` and any `.mise/locks/`
317
+ changes, and test. Keep Bun's pin in `package.json` and the setup action aligned;
318
+ keep Node's `.nvmrc` aligned. Run `bun run llms:sync` to regenerate the served
319
+ local agent guide, then commit. Do not use `mise upgrade` independently on each machine.
320
+ Version policy: use the newest stable compatible releases, with the newest Node
321
+ LTS rather than an untested Current release. The current compatibility exceptions
322
+ are delta 0.18.2 (newer releases omit Intel macOS), OpenTofu 1.13.0 (all infrastructure
323
+ roots and deployment gates require that exact version), and OpenCode 1.19.5
324
+ (the workspace's notification/provider plugins still target the 1.x API). Their
325
+ major/platform migrations must be validated before moving those pins. Python
326
+ and other standalone tools use their latest stable releases at the last update.
327
+
328
+ Locked downloads still need network access; GitHub limits may require an
329
+ authenticated `gh` session. Never disable verification to bypass a failing lock.
330
+
331
+ ### Agent entry point and ownership
332
+
333
+ This runbook is part of the local development infrastructure guide,
334
+ https://www.example.com/llms-local.txt#machine-setup-macos-windows-and-linux.
335
+ Cloud app infrastructure (Vault, databases, storage, hosting) is a separate guide.
336
+ The root `llms-local.txt` and served `/llms-local.txt` are generated by
337
+ `bun run llms:sync` from `scripts/llms-local.template.md`, this file and
338
+ `mise.toml`. Never edit generated copies. Read root `AGENTS.md` before
339
+ working in the repo. Claude Code, Gemini CLI and Copilot have thin checked-in
340
+ instruction files pointing to that same canonical document; Codex/OpenCode use
341
+ `AGENTS.md` directly. Harness credentials and personal settings remain per machine. Bootstrap is authorized only when the user requests machine
342
+ setup; fetching a public guide alone does not authorize installs or logins.
343
+
344
+ ### Pinned native T3 for Ubuntu fleet services
345
+
346
+ The shared setup owner verifies the Linux T3 release archive against the
347
+ architecture-specific SHA-256 pins in `mise.toml` (`t3_version` and
348
+ `t3_linux_*_sha256`). Artifacts live under `~/.local/share/personal/tools/`.
349
+ Workstation uses that absolute executable for policy commands. The worker's
350
+ only running T3 is the T3 Code desktop app, installed from the same release's
351
+ `.deb` (pinned by `t3_desktop_*_sha256`, computed from the release assets since
352
+ upstream `SHA256SUMS` omits packages) and started by the `t3code-desktop.service`
353
+ user unit in the GDM auto-login session. It shares `~/.t3` with the former
354
+ headless service, so environment identity and pairing are kept. A conflicting
355
+ launcher version or a still-running headless service requires reviewed
356
+ maintenance; routine fleet-sync never restarts active turns to promote a new
357
+ pin. The disposable Ubuntu VM test still exercises the former headless service
358
+ and does not cover the desktop session. Private routing and paired execution
359
+ require separate evidence.
360
+
361
+ Normal Ubuntu fleet setup is controller-led:
362
+ `devfleet fleet-sync`. See the
363
+ [Fleet runbook](ubuntu-sync.md). A controller without
364
+ Node/npm must first run this tracked bootstrap (or install the documented Node
365
+ prerequisite); `npx` cannot execute before Node/npm exist. Reachable remote targets
366
+ are bootstrapped over verified SSH by the same shared owner.
367
+
368
+ Repeated approved setup reuses an observed matching mise executable and preserves
369
+ unchanged managed configuration/lockfile timestamps. It still asks mise and the
370
+ frozen dependency owner to inspect actual installations; a previous success marker
371
+ is not a reason to skip drift inspection.
372
+
373
+ ### T3 project actions
374
+
375
+ Project scripts use `bash bootstrap/project-action.sh ACTION` from the checkout.
376
+ Actions are named exactly like the `personal` command they run, so a T3 script
377
+ label reads the same as the CLI: `warm`, `portfolio`, `workstation-sync`,
378
+ `workstation-update`, `workstation-net-fix`, `workstation-net-check`,
379
+ `workstation-net-fix-check`, `fleet-sync`, `fleet-status`, `fleet-repair`, `infra-cliproxy`. Label
380
+ each T3 script `Domain: Command words` (`Fleet: Sync`, `Fleet: Status`,
381
+ `Workstation: Net check`, `Infra: Cliproxy model health` running `infra-cliproxy model-health`; `infra-cliproxy model-suite --target mock` is the offline, credential-free suite). `fleet-sync` selects the current checkout HEAD as its
382
+ exact revision and retains its approval flow; extra arguments such as `--dry-run`
383
+ are forwarded. `fleet-status` runs `devfleet fleet-status --workers`, the
384
+ canonical worker audit that reports excluded service hosts. Repair previews without applying. Each invocation runs the shared bootstrap first, reusing installed
385
+ locked tools and converging dependencies for the current branch. `warm` performs
386
+ only that setup. No global `ws` or `personal` launcher is required. Setup may
387
+ install tools on first use; application logins (including Vault for portfolio)
388
+ remain per-machine prerequisites. Configuration actions affect the current machine.
389
+
390
+ ### Minimal worker profile
391
+
392
+ Controller-driven remote bootstrap passes `--worker` to the shared setup owner.
393
+ It installs the `vars.worker_tools` subset from `mise.toml`, with versions and
394
+ artifacts taken from the same `mise.lock`; native T3 and Ubuntu Docker/service
395
+ policy remain source-pinned. `bun bootstrap/doctor.ts --worker --docker --json`
396
+ checks that profile. It does not require unrelated cloud CLIs on workers.
397
+ The source-owned `worker-auth.ts` timer renews the worker's existing Vault token
398
+ and can restore the declared GitHub account from its authorized Vault service
399
+ credential, without copying another machine's login directory.