Contributions are welcome. @fullstackjam maintains the project and reviews all PRs — he has final say on what gets merged, but good ideas land fast.
git clone https://github.com/YOUR_USERNAME/openboot.git
cd openboot
make install-hooks # opt-in: pre-commit + pre-push checks
git checkout -b fix-something
# Fast feedback loop (runs on every push via git hook, ~15s)
make test-unit
# Commit + push
git commit -m "fix: the thing"
git push origin fix-somethingThen open a PR — use the template, it's short.
- Add a package to
internal/config/data/packages.yaml - Fix a typo or improve an error message
- Add a missing test
See issues labeled good first issue for tracked tasks.
Tests are split across four tiers. Which one runs where:
| Tier | What | How to run | When it runs |
|---|---|---|---|
| L1 Unit + Integration + Contract | Pure-Go logic with faked Runner plus real brew / git / npm against temp dirs and real httptest servers |
make test-unit (~75s) |
Every push (pre-push hook); CI on push/PR |
| L2 Contract schema | JSON schema validation against openboot-contract | (runs in CI only) | CI on push/PR |
| L3 E2E binary | Compiled binary driven by scripts; -tags=e2e |
make test-e2e |
CI on release |
| L4 VM e2e | Full destructive suite (-tags="e2e,vm"). Installs real packages, modifies ~/.zshrc, writes defaults. Each run requires a clean macOS host (Apple Silicon). |
CI only — vm-e2e-spike.yml on macos-14 |
CI — GitHub Actions macos-14 runner, two parallel jobs. No local target. |
Rules of thumb:
- Local dev: run nothing manually if hooks are installed.
make test-uniton demand when you want a sanity check. Skip L2+ unless you're cutting a release. - Before pushing:
make test-unit(the pre-push hook does this automatically). Requiresbrew/git/npmon PATH — they are queried read-only against temp dirs, no real installs. - Before tagging a release: check that the L4 CI job (
vm-e2e-spike.yml) is green on the latest commit onmain.auto-release.ymlopens arelease-readyissue onfeat:thresholds to nudge you here.
L4 tests run on GitHub Actions (macos-14 runner, Apple Silicon, vm-e2e-spike.yml).
Each job gets a fresh macOS VM — no local setup or Makefile target required.
make install-hooks symlinks two hooks from scripts/hooks/ into .git/hooks/:
- pre-commit (<5s) —
go vet+go build. Early-exits when no.gofiles are staged. - pre-push (~75s) —
go test -race ./...(L1 suite: unit + integration + contract).
Skip once with git's standard bypass flag. Remove entirely with make uninstall-hooks.
When adding code that calls external binaries (brew, npm, git, etc): don't hard-code exec.Command — use the package's Runner interface. See internal/brew/runner.go for the pattern. Tests can then substitute a pure-Go fake via brew.SetRunner(…).
Don't hit the network in L1. Use httptest.NewServer + server.Close() when testing connection errors, not DNS timeouts on bogus hostnames.
Don't assume filesystem state. Use t.TempDir() and t.Setenv("HOME", t.TempDir()) when code reads ~/.something.
Integration tests live alongside L1 in test/integration/ and may touch the real filesystem but only inside temp dirs. They must not depend on the developer's ~/.dotfiles, ~/.zshrc, or similar, and must only read (never install/uninstall) real brew / npm / git state.
- Standard Go style (
go vetmust pass — the pre-commit hook enforces this) - Add tests for new features
- Conventional commits (
feat:,fix:,docs:,refactor:) - One logical change per PR
- CLI breaking changes need an entry in CHANGELOG.md + a major version bump
See CLAUDE.md for how everything fits together.
Open a Discussion.