feat: add one-line installer and service manager #524

Merged
dries merged 2 commits from feat/install-script into main 2026-08-20 23:12:48 +02:00
Owner

curl -fsSL .../install.sh | bash -s -- install — checks the toolchain (git, go, node, pnpm; warns on tmux/opencode/lsof), shallow-clones to ~/.local/share/ocman/src, builds frontend + binary, installs to ~/.local/bin/ocman, and starts it in the background.

The same script installs itself as ocman-ctl, so the manager commands come for free:

ocman-ctl start|stop|restart|status|logs
ocman-ctl update              # pull, rebuild, restart
ocman-ctl uninstall [--purge] # --purge also deletes state.db
ocman-ctl doctor

Process tracking is a pidfile under ~/.local/state/ocman, validated against the live process's args so a recycled pid can never be SIGTERM'd by stop. scripts/install_test.sh exercises that lifecycle (double start/stop, stale pidfile, foreign pid) against a fake binary — no network, no build.

Deliberately left out, per YAGNI: no launchd/systemd unit (so no reboot persistence), no prebuilt-binary fast path, no auto-install of go/pnpm, no Go version parsing (GOTOOLCHAIN fetches the pinned toolchain).

`curl -fsSL .../install.sh | bash -s -- install` — checks the toolchain (git, go, node, pnpm; warns on tmux/opencode/lsof), shallow-clones to `~/.local/share/ocman/src`, builds frontend + binary, installs to `~/.local/bin/ocman`, and starts it in the background. The same script installs itself as `ocman-ctl`, so the manager commands come for free: ``` ocman-ctl start|stop|restart|status|logs ocman-ctl update # pull, rebuild, restart ocman-ctl uninstall [--purge] # --purge also deletes state.db ocman-ctl doctor ``` Process tracking is a pidfile under `~/.local/state/ocman`, validated against the live process's args so a recycled pid can never be SIGTERM'd by `stop`. `scripts/install_test.sh` exercises that lifecycle (double start/stop, stale pidfile, foreign pid) against a fake binary — no network, no build. Deliberately left out, per YAGNI: no launchd/systemd unit (so no reboot persistence), no prebuilt-binary fast path, no auto-install of go/pnpm, no Go version parsing (GOTOOLCHAIN fetches the pinned toolchain).
feat: add one-line installer and service manager
All checks were successful
CI / Frontend (pull_request) Successful in 7m5s
CI / Build (pull_request) Successful in 4m43s
CI / Playwright E2E (pull_request) Successful in 9m7s
CI / Backend (pull_request) Successful in 11m10s
CI / Semantic Tag (pull_request) Successful in 6s
CI / Coverage Results (pull_request) Successful in 15s
aeec416a43
install.sh checks the toolchain, builds from source, installs the binary
to ~/.local/bin and starts it in the background. The same script installs
itself as ocman-ctl for start/stop/restart/status/logs/update/uninstall.

Process tracking is a pidfile under ~/.local/state/ocman, validated
against the running process's args so a recycled pid can never be killed
by stop.

Coverage ratchet: ✅ pass

Suite Baseline This PR Δ
frontend 71.22% 71.19% -0.03 ✅
go 81.30% 81.30% +0.00 ✅

Tolerance: -0.1%. Baseline stored on gh-pages.

<!-- coverage-ratchet --> ### Coverage ratchet: ✅ pass | Suite | Baseline | This PR | Δ | | |---|---|---|---|---| | frontend | 71.22% | 71.19% | -0.03 | ✅ | | go | 81.30% | 81.30% | +0.00 | ✅ | _Tolerance: -0.1%. Baseline stored on `gh-pages`._
fix: install built binary and ctl script atomically via rename
All checks were successful
CI / Frontend (pull_request) Successful in 8m25s
CI / Backend (pull_request) Successful in 10m40s
CI / Build (pull_request) Successful in 4m5s
CI / Coverage Results (pull_request) Successful in 32s
CI / Playwright E2E (pull_request) Successful in 5m5s
CI / Semantic Tag (pull_request) Successful in 6s
5cf5d99e58
dries merged commit c6e09a8542 into main 2026-08-20 23:12:48 +02:00
dries deleted branch feat/install-script 2026-08-20 23:12:48 +02:00
Sign in to join this conversation.
No description provided.