Skip to content

feat(sandbox): add Herdr setup command - #80

Merged
pratikbin merged 2 commits into
mainfrom
feat/setup-herdr
Aug 26, 2026
Merged

feat(sandbox): add Herdr setup command#80
pratikbin merged 2 commits into
mainfrom
feat/setup-herdr

Conversation

@pratikbin

@pratikbin pratikbin commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Adds createos sandbox setup herdr. It wires the CreateOS Sandbox plugin into Herdr, so a coding agent runs inside a sandbox and its PTY attaches to a Herdr pane.

#78 created the sandbox setup group and has merged, so this now targets main directly and adds the second subcommand to that group.

The companion plugin is NodeOps-app/createos-plugins under packages/herdr-plugin (NodeOps-app/createos-plugins#24).

Why this one does the work itself

Orca drives a per-workspace environment, so setup orca splits into a machine half (--recipe, which Orca calls) and a human half that prints install instructions, because Orca performs its own plugin install.

Herdr has no such hook, and its entire plugin API is the herdr CLI. So this command can do every step, and does:

createos sandbox setup herdr
  1. signed in to CreateOS          ── ListSandboxes, same gate as setup orca
  2. herdr >= 0.7.5 on PATH         ── plugin panes and `pane split --env`
  3. bun on PATH                    ── the plugin runs on it
  4. git on PATH                    ── the plugin uploads what git tracks
  5. herdr plugin install <repo>/packages/herdr-plugin --yes
  6. write plugin config.json       ── agent, shape, rootfs, autoPause, remoteRoot
  7. splice keys into config.toml   ── Herdr ignores keys in a plugin manifest
  8. herdr config check + server reload-config

--doctor stops after step 4 and changes nothing.

Review attention

It writes to the user's config.toml. That is the part worth arguing about, so it is guarded three ways: the file is copied to config.toml.before-createos first; only bindings that are not already present are appended; and herdr config check runs afterwards, failing the command if Herdr rejects the result. --no-keys opts out entirely, and herdr config reset-keys undoes it. A second run adds nothing.

It never replaces an existing plugin config.json without --force. It says so rather than staying silent.

The Herdr config root is derived, not guessed. herdr plugin config-dir <id> returns <root>/plugins/config/<id>, so walking up three levels follows Herdr wherever Herdr puts it, instead of hardcoding ~/.config/herdr.

--local is the plugin-development path. herdr plugin link deliberately skips build commands, which would leave the plugin without the generated launcher carrying absolute bun and createos paths — Herdr runs plugin commands as a bare argv with no shell expansion. So the command runs build.sh itself after linking, and refuses a directory with no herdr-plugin.toml.

Verification

go build, go vet, gofmt -l, and go test ./... are clean. Three unit tests cover the version gate, keybinding idempotency plus backup, and agent-list consistency.

Run against an isolated HOME with a local checkout:

signed in to CreateOS
herdr 0.8.2 found at /Users/…/herdr
bun found on PATH
git found on PATH
linking …/packages/herdr-plugin
running the plugin build step
plugin linked
wrote …/plugins/config/createos.sandbox/config.json
added 6 keybindings to …/config.toml (undo with 'herdr config reset-keys')

herdr config check then reported config: ok, and herdr plugin list showed the plugin enabled. A second run reported kept your existing config.json and keybindings already present.

The version gate matters: a naive string compare reads 0.10.0 as older than 0.7.5 and would refuse a newer Herdr. herdrVersionLess compares per part, and a non-numeric part sorts as 0 so a pre-release never reads as newer.

Mesh

repo status
fc n/a — no backend change; the command only calls the existing ListSandboxes
fc-sdk n/a — CLI only
createos-plugins done — the plugin README now documents this command as the install route
website-04 missing-needs-updatecontent/docs/Sandbox/CLI/Commands.md documents no setup subcommand at all, orca included. That gap predates this PR and belongs with #78. Not written here, since documenting an unmerged command is premature.

Lint

golangci-lint 2.11.3, the version pinned in .tool-versions, reports 0 issues.

An earlier revision of this description claimed the linter could not run against this repository. That was wrong on both counts, and is corrected here: the local binary was v1 against a v2 config, and the sandbox attempt used an arbitrary v2.6.2 instead of the pinned 2.11.3. CI runs it correctly. Installing the pinned version with asdf reproduced all fifteen findings locally, and d88925c fixes every one of them at the source rather than suppressing them — the three #nosec comments that remain each name why the argv or path is safe, matching the convention already used in orca.go.

@pratikbin
pratikbin changed the base branch from feat/orca-per-workspace-env to main August 25, 2026 14:09
@pratikbin
pratikbin merged commit 9432293 into main Aug 26, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant