A machine-wide heavy-work budget for parallel coding agents.
When several agents work side by side on one machine β separate sessions, repos, git worktrees, or harnesses (OpenCode, Codex CLI, Claude Code, ...) β their builds and test suites stomp on each other, thrash the caches, and starve each other's cores. load-lock gives them one shared counting semaphore: acquire a permit before heavy work, keep doing light work while queued, receive a FIFO offer when capacity frees, claim it, run, release. It is cooperative and advisory β no command wrapping, no automatic shell classification, no approval interruptions.
agent A (OpenCode) agent B (Codex) agent C (Claude Code)
acquire "cargo test" acquire "npm test" acquire "build docs"
granted β runs queued β keeps coding queued β keeps coding
... offer β claim β runs (misses window β d)
release β release β rejoin β offer β claim β
Three agents, one budget β the queue drains FIFO while everyone keeps coding:
- One budget for the whole machine β every client of any harness shares
one capacity pool regardless of repo/worktree/cwd. Default: pool
heavy, capacity 1; fully runtime-configurable by any agent via versioned CAS updates (persisted with author + rationale). - Atomic acquire-or-queue β single daemon event loop; a release can never slip between a failed check and queue registration.
- FIFO offers with opaque claim tokens β outstanding offers reserve capacity; expired offers pass capacity to the next waiter and the absent request until it explicitly rejoins (no endless recycling).
- Real process-lifecycle cleanup β permits attach to actual processes
(pid + process group +
/procstart time, PID-reuse-safe). Background jobs outliving the shell keep their permit until the whole group exits. Never auto-expired merely for being old. Untracked work uses an honest, documented heartbeat-lease tradeoff. Explicit release is always available and idempotent. - Crash-safe β agent crashes release tracked permits on confirmed process death; daemon restarts reconcile a journal against real liveness and auto-respawn transparently.
- Honest notifications β tool-boundary offer delivery everywhere; real
idle wakeup where the harness supports it (live-verified on OpenCode;
hook-based on Claude Code and Codex CLI); a bounded blocking
wait_for_turn(load-lock waiton the CLI) that sleeps until your turn and auto-claims for harnesses without idle wakeup; durable event ids for reconnects. A notification never authorizes work β onlyclaimdoes. - Policy that actually reaches the model β installed per harness via its real mechanism (plugin context hook, SessionStart hooks incl. compact matchers, global instruction files), plus a detailed skill/guide.
- Resource-aware β
inspect_machinereports cgroup/container CPU and memory limits and current pressure; never assumes cores = capacity.
npm install -g @aron98/load-lock
load-lock install --harness opencode # or claude-code | codex | gemini-cli |
load-lock doctor
From then on, agents see the policy and tools automatically:
OpenCode plugin (load_lock_* tools), Claude Code / Codex MCP tools
(mcp__load-lock__*) plus session hooks. Any other MCP-capable harness can
use the generic stdio server; plain shells use the CLI:
load-lock run --reason "nightly build" -- npm run build # acquireβrunβrelease
load-lock status # machine-wide view
load-lock dashboard # live read-only dashboard (q quits)
load-lock help # one-screen usage of every command
load-lock configure --capacity 2 --reason "16-core host" --author me
OpenCode users also get a live dashboard inside the TUI: /load-lock
opens it in-window, every session screen shows a clickable at-a-glance
widget in the right sidebar, and the home screen has a footer indicator β
same data, themed. See docs/OPERATIONS.md β "Dashboard".
Agents running inside a sandbox (bubblewrap/omac, Docker, macOS seatbelt,
WSL2) share the host's budget instead of getting their own: bridge the
daemon's Unix socket into the sandbox, set LOAD_LOCK_NO_SPAWN=1 so the
client never spawns a useless sandbox-local daemon, and optionally tag
holds with LOAD_LOCK_LABEL_PREFIX (e.g. bwrap:issue-42 build).
Ready-to-run per-sandbox recipes β live-verified for bubblewrap and omac,
contract-inspected for the rest, plus the cross-PID-namespace lease
lifecycle β live in docs/OPERATIONS.md β "Sandboxes".
src/core/ daemon + state machine + persistence + machine inspection
src/mcp/ MCP stdio server (universal adapter)
src/adapters/ OpenCode native plugin
src/cli/ CLI incl. installer, hook handlers, run/wait helpers
src/test/ 32 tests: state machine, real multi-process daemon tests,
MCP integration, hook contracts, run helper
demo/ reproducible 3-worktree demo (three agents, one pool)
docs/ ARCHITECTURE / COMPATIBILITY / OPERATIONS / AGENT_GUIDE
skills/ packaged skill
-
docs/ARCHITECTURE.md β design, why a dedicated service (vs WorkOS Airlock / mic-lock / flock wrappers), atomicity, restart semantics, notification honesty, lifecycle tradeoffs.
-
docs/COMPATIBILITY.md β per-harness capability matrix with implemented / contract-tested / proposed labels.
-
docs/OPERATIONS.md β install, config, troubleshooting, recovery, daemon lifecycle, sandbox bridging.
-
docs/AGENT_GUIDE.md β the playbook for agents.
-
docs/ADAPTERS.md β how to write an adapter for a new harness, using the published library surface.
-
Core daemon/protocol/CLI: implemented, 68 automated tests passing (multi-process daemons, real processes, restarts, races, expiry, PID-reuse, subprocess survival; plus 9 dashboard tests β view-model shaping, event-cursor resume across a daemon restart, reconnect, and a
load-lock dashboard --oncerender smoke test). -
OpenCode adapter: implemented and live-verified (tools, policy injection, compaction-proof context hook, execution-boundary wakeup with tokens, skill).
-
Claude Code adapter: implemented, contract-tested against documented hook JSON; not yet live-verified (harness not installed on the verification machine).
-
Codex CLI adapter: implemented and live-verified end-to-end in Docker (interactive TUI via pty: policy injection, MCP round-trip, FIFO queueing behind a competing holder, Stop-hook decision-block wakeup; see COMPATIBILITY.md for the two upstream/provider constraints the verification harness works around).
-
Tier-3 fallback installers (Gemini CLI, Copilot CLI, Cline, Roo Code, Goose): implemented merge-only installers (MCP stdio server entry into the harness's real config + a global instructions-file section/policy rule file), config-tested via temp-HOME round-trips; fallback tier (no hooks, no async push β no idle wakeup).
-
Cursor adapter: implemented (issue #6) β merge-only project-level installer (
.cursor/mcp.jsonMCP entry,.cursor/hooks.jsonstop hook per the now- officially-documented hooks v1 contract,.cursor/rules/load-lock.mdcAlways-apply rule) +hook cursor stophandler emitting{"followup_message":...}idle wakeup.Contract-tested , not live-verified (no Cursor on the verification machine). -
Aider: researched; manual CLI tier. See COMPATIBILITY.md for the matrix.
Linux-first; macOS works with documented liveness-check limitations; Windows has a named-pipe transport adapter (implemented and unit-tested on Linux via platform injection; not yet verified on a Windows machine).