openboot
AGENTS.md277 starsChanged 35 days agoMITView on GitHub
Canonical, tool-neutral instructions for coding agents working on this repo. Codex reads this file directly; Claude Code imports it from CLAUDE.md. If you're a human, you probably want README.md or CONTRIBUTING.md. - Keep shared repository guidance in this file. Do not duplicate it in a tool-specific instruction file. - CLAUDE.md is a thin Claude Code adapter: it imports this file with @AGENTS.md and may contain only Claude-specific additions. - Shared skills use the open Agent Skills format and live in…
- Pipes a download into a shell
- Deletes or force-pushes
- Installs packages
- Commits and pushes
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,774 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository4 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- architecture-reviewSkill
- bootstrap-featureSkill
- ship-prSkill
The file
We split this AGENTS.md into the rules it gives an agent
5 rules. About 0 are common, 4 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 5
If you're a human, you probably want README.md or CONTRIBUTING.md.
- Distinctive: line 10
Keep shared repository guidance in this file.
- Very specific: line 22
When adding a shared skill, create it under .agents/skills/, then expose it to Claude Code without copying its contents:
- Distinctive: line 152
If you added a violation by accident, fix the code by using the allowed wrapper or moving the call into the appropriate package.
- Distinctive: line 154
If the violation is intentional, update the baseline:
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
AGENTS.md
Canonical, tool-neutral instructions for coding agents working on this repo.
Codex reads this file directly; Claude Code imports it from CLAUDE.md.
If you're a human, you probably want README.md or
CONTRIBUTING.md.
Agent compatibility
- Keep shared repository guidance in this file. Do not duplicate it in a tool-specific instruction file.
CLAUDE.mdis a thin Claude Code adapter: it imports this file with@AGENTS.mdand may contain only Claude-specific additions.- Shared skills use the open Agent Skills format and live in
.agents/skills/<name>/SKILL.md. Claude Code discovers the same skills through relative symlinks under.claude/skills/. - Other tools that implement
AGENTS.mdor Agent Skills can consume the same canonical paths without another copy of the instructions. - Tool-specific integration stays tool-specific. Claude Code hooks and
permissions remain in
.claude/settings.jsonand.claude/hooks/.
When adding a shared skill, create it under .agents/skills/, then expose it
to Claude Code without copying its contents:
mkdir -p .claude/skills/<name>
ln -s ../../../.agents/skills/<name>/SKILL.md .claude/skills/<name>/SKILL.mdThe agent-config architecture test verifies the import and skill adapters.
Read first
- CONTRIBUTING.md — test layering L1-L4, Runner interface, and hook setup.
- docs/HARNESS.md — the steering meta-doc: when a class of issue recurs, which file to edit to prevent it next time.
- internal/archtest/README.md — architecture fitness functions and baseline workflow.
Project
OpenBoot is a macOS-only Go 1.26 CLI that automates dev-environment setup: Homebrew packages/casks, npm globals, Oh-My-Zsh, macOS defaults, and dotfiles. Built on Cobra (CLI) + Charmbracelet (bubbletea / lipgloss / huh for TUI).
Entry point: cmd/openboot/main.go -> internal/cli.Execute().
Core flow: openboot install orchestrates plan -> apply in internal/installer/installer.go.
The wizard plans; the apply is always linear. On a TTY the planning phase runs as a full-screen TUI in internal/ui/tui/wizard/ (boot probe -> select -> git -> review), then the wizard exits and hands its InstallPlan to installer.ApplyReviewedPlan, which applies it on the normal terminal with ConsoleReporter + ui.StickyProgress. This split is deliberate: a TUI is right for browsing a 100+ package catalog, and wrong for the apply — an alt-screen install discards its own output when it exits, so twenty minutes of package results and failures vanish. Streamed into the scrollback they stay where the user can scroll back, copy an error, and pipe it. Don't move the apply back inside the alt-screen.
Entry points: bare install -> wizard.Run; -p <preset> -> same, loadout preselected; slug/-u/--from/alias -> wizard.RunForConfig (config mode: the config's own packages on the select screen, preselected). TTY --dry-run uses the same wizard and carries preview-only semantics into apply. Sync-source installs keep their linear diff pre-flight and apply linearly. --silent, --update, --pick, and non-TTY runs never enter the wizard.
Working in parallel
This repo is often worked on from multiple concurrent terminals / agent sessions. Default to git worktree add ../openboot-<topic> -b <branch> rather than juggling branches in a single checkout — two sessions racing on the same working tree corrupts state (mid-edit files, half-staged diffs, hooks firing against the wrong branch). One worktree per concurrent task; remove it with git worktree remove when the PR merges.
Commands
# Build — version injected via -ldflags, default is "dev"
make build
make build-release VERSION=0.25.0 # optimized + UPX
# Test — full tier table in CONTRIBUTING.md
make test-unit # L1 (~75s) — unit + integration + contract; pre-push hook
make test-e2e # L3 compiled binary
# L4 — destructive e2e runs in CI only (vm-e2e-spike.yml on macos-latest)
make test-coverage # coverage.out + coverage.html
# Single test
go test -v -run TestFoo ./internal/<pkg>/...
# Hooks (opt-in): pre-commit = vet+build, pre-push = L1
make install-hooks
go vet ./...
make cleanLayout
cmd/openboot/ # main.go -> cli.Execute()
internal/
auth/ # OAuth-like login, token in ~/.openboot/auth.json (0600)
brew/ # Homebrew ops, sequential install with retry, uninstall
cli/ # Cobra cmds: install, snapshot, login, logout, version
config/ # Package catalog + presets + remote fetch (embed fallback in data/)
diff/ # Pure-logic system-vs-config comparison
dotfiles/ # Clone + stow with .openboot.bak backup
httputil/ # HTTP Do() with rate-limit + Retry-After
installer/ # Install planning + linear apply + snapshot restore
macos/ # defaults write + app restart
npm/ # Batch install with sequential fallback
permissions/ # macOS screen-recording probe
search/ # openboot.dev API client (8s timeout)
shell/ # Oh-My-Zsh install + .zshrc + snapshot restore
snapshot/ # Capture / match / restore env state
state/ # Reminder state in ~/.openboot/state.json
sync/ # Compute diff + execute plan for remote config
system/ # RunCommand / RunCommandSilent, arch, git config
ui/ # bubbletea Model pattern, lipgloss styling
updater/ # Auto-update: check GitHub -> download -> replace
doctor/ # Diagnostic checks for openboot doctor command
logging/ # Structured rotating file log under ~/.openboot/logs/
test/{integration,e2e}/ # integration runs as part of L1; e2e gated by build tags (e2e, vm)
testutil/ # shared helpers + MacHost (destructive E2E on real macOS)
scripts/
install.sh # curl|bash installer
hooks/ # pre-commit, pre-push (install via `make install-hooks`)Where to look
| Task | Location | Notes |
| Add CLI command | internal/cli/ | Register in root.go init(), follow cobra pattern |
| Change install flow | internal/installer/installer.go | plan -> apply orchestrator; PlanFromSelection builds a plan from TUI picks |
| Change interactive install TUI | internal/ui/tui/wizard/ | Redesign v5 planning screens: boot -> select -> git -> review; apply starts only after the wizard exits |
| Change sync behavior | internal/sync/diff.go, internal/sync/plan.go | Diff -> confirm -> execute |
| Add package category | openboot.dev/src/lib/package-metadata.ts | Server is source of truth; CLI fetches /api/packages and caches 24h in ~/.openboot/packages-cache.json. data/packages.yaml is fallback only. |
| Modify presets | internal/config/data/presets.yaml | 3 presets: minimal, developer, full |
| Change brew behavior | internal/brew/brew.go + brew_install.go | Parallel workers, StickyProgress, Uninstall/UninstallCask |
| Cask download progress | internal/brew/cache.go + internal/brew/sizecheck.go | HEAD pre-fetch -> poll brew --cache for bytes; consumed by installCasksWithProgress |
| Add snapshot data | internal/snapshot/capture.go | Extend CaptureWithProgress steps |
| Update self-update | internal/updater/updater.go | AutoUpgrade() called from root.go RunE |
| Change publish flow | internal/cli/snapshot_publish.go (publishSnapshot) | Slug resolution |
| Source resolution (install) | internal/cli/install.go (resolvePositionalArg) | file / user-slug / preset / alias detection |
| HTTP with retry | internal/httputil/ratelimit.go | Use httputil.Do() — handles 429 + Retry-After (archtest: no-raw-http) |
| Test tier / when to run | CONTRIBUTING.md "Test Layering" | L1-L4 table |
| Release process | .github/workflows/ | Tag-driven, release-notes template |
Project-specific conventions
These cannot be inferred from code alone — everything else is enforced by go vet / review.
Bolded rules are enforced mechanically by internal/archtest (fitness functions in L1).
- Error wrapping:
fmt.Errorf("context: %w", err)— never bare returns. - UI output (archtest:
fmtprint): always throughui.*helpers; rawfmt.Printlnis a bug in user-facing paths. - Subprocess (archtest:
no-direct-exec):system.RunCommand(interactive) /system.RunCommandSilent(captured). Do not callexec.Commanddirectly from feature code — add tosystem/if a wrapper is missing. - Destructive ops (archtest:
dryrun): checkcfg.DryRunfirst. Always. - Paths (archtest:
no-os-getenv-home):os.UserHomeDir()— never hardcode~or/Users/..., neveros.Getenv("HOME"). - State: everything user-local goes under
~/.openboot/(auth, cache, snapshots, state). - Concurrency: bounded
sync.WaitGroup— brew install is sequential with retry;GetInstalledPackagesuses 2 goroutines for formula+cask list. No unbounded goroutines. - Embedded data:
//go:embed data/*.yamlloaded ininit(). - Tests: table-driven,
testify/requirefor fatal,testify/assertfor non-fatal. L1 uses theRunnerinterface to fake subprocess calls — no real network, no real fork. - Commits: Conventional (
feat:/fix:/docs:/refactor:/test:/chore:/ci:), one thing per commit.
When archtest fails
The failure message tells you exactly what to do:
- If you added a violation by accident, fix the code by using the allowed wrapper or moving the call into the appropriate package.
If the violation is intentional, update the baseline:
ARCHTEST_UPDATE_BASELINE=1 go test ./internal/archtest/... git add internal/archtest/baseline/
The baseline diff is the audit trail. Explain why the new call site is justified in the commit message; do not silence the rule.
Run before committing
go vet ./... # cheap, ~1s
go test ./internal/... # L1, ~15s, includes archtestBoth are wired into scripts/hooks/pre-commit (vet only) and
scripts/hooks/pre-push (full L1). Install once with make install-hooks.
Actions that require confirmation
git push --forceagainstmainor release tags.git commit --amendon commits already pushed.git reset --hardwhen it would discard uncommitted work.- Triggering L4 e2e tests outside CI; they install real packages on the host.
- Modifying the user's
~/.zshrc, Homebrew installation, or macOSdefaults.
Repository reads and edits, make test-unit, and go vet are safe without
extra confirmation.
Env vars
| Var | Purpose |
OPENBOOT_DISABLE_AUTOUPDATE=1 | Skip auto-update check |
OPENBOOT_GIT_NAME / OPENBOOT_GIT_EMAIL | Git identity override (silent mode) |
OPENBOOT_PRESET | Default preset |
OPENBOOT_USER | Config alias/username |
OPENBOOT_API_URL | Override API base URL (testing; https or http://localhost only) |
OPENBOOT_DOTFILES | Override dotfiles repo URL |
OPENBOOT_DRY_RUN | Dry-run mode for scripts/install.sh (not the CLI) |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

