Skip to main content

AGCoord

Golden botanical AGCoord gourd with a curled green stem and leaf

Local CI and merge queue for coding agents that share one machine.

When several coding agents share one workstation, nothing coordinates them. They compete for the machine, so test runs time out or get OOM-killed for reasons that have nothing to do with the code. They merge on stale evidence, so main breaks from changes that were never tested together. And they leave no shared record of what ran, on which head, with what result.

AGCoord is the missing layer. One detached broker per OS user owns a queue for every repository and worktree on the machine:

  • Resource-aware admission. A job declares the CPU, memory, and scratch it needs. It starts when the machine has room, and on a supported host cgroup v2 holds it to what it declared.
  • Atomic landing. agc land 123 -- ./scripts/test.sh brings the current target into the pull-request branch, runs your gate once, and merges the pull request in the same durable step. A red gate publishes nothing. A moved target never reuses a green result.
  • One record. Every job has a stable ID, a combined log, and a row you can list, follow, cancel, or watch in a terminal UI from any shell.

It works with any agent that can run a shell command, such as Claude Code, Codex, or Aider, and with people. It complements hosted CI rather than replacing it. The core is forge-neutral; GitHub support is an optional adapter. Why AGCoord exists makes the case in depth.

What you need

  • Linux on x86_64, and Python 3.10 or newer for the agcoord client.
  • For the two-minute try-out below: nothing else. The released broker runs as your own user with admission-only accounting.
  • For enforced limits: an Ubuntu 24.04-class host (unified cgroup v2 mounted read-write with nsdelegate, AppArmor ABI 4, kernel.apparmor_restrict_unprivileged_userns=1, systemd 254 or newer) and one privileged install step. The broker itself runs as an unprivileged user service; no root daemon is installed.
  • For landing: a GitHub pull request. Checks and full gates need no forge at all.

AGCoord is alpha software that moves quickly. A client commands only a broker of its own minor release line, and the changelog records every user-facing change.

Try it in two minutes, without root

The client talks to a broker executable that must match its version exactly, and it ships the SHA-256 of that executable. One command fetches the release broker, verifies it against that pin, places it under ~/.local/libexec/agcoord, and configures an unmanaged spool:

python -m pip install agcoord            # in a virtual environment, or: pipx install agcoord
agc host install --user

Now submit work from inside any Git checkout:

cd ~/src/your-repo
agc run --label "unit tests" --resource cpu=2 -- python -m pytest -q
agc list
agc tui

The first client starts the broker on demand, and closing the terminal does not cancel the job. The quickstart continues from here: watching two oversized jobs queue behind each other, following logs, moving to the enforced host, and landing a pull request. After pip install --upgrade agcoord, run agc host install --user again; a client refuses a user-owned broker that is not the one it was released with.

Turn on enforcement

On a supported Ubuntu host, one privileged step installs the pinned broker as a root-owned file, enables a systemd user service and an enforcing AppArmor profile, and proves a one-CPU limit before reporting success. It needs an empty default spool: if you ran the try-out on this machine, agc drain it and move ~/.local/state/agcoord aside first.

python -m pip install --upgrade agcoord
agc host install --download

--download fetches the release bundle that matches the installed client, verifies its checksums and the broker against the digest the client ships with, and refuses anything else. A fresh install records the machine's available CPU count as both cpu and jobs capacity with a required cgroup-v2 binding, so --resource cpu=N becomes a real cpu.max limit. Memory, tmpfs, persistent scratch, process, and block-I/O bindings live in the same config.json. The native host runbook has the full host contract, offline installation from a bundle, upgrades, recovery, and rollback.

Tell your agents

Agents follow the tools they are given. Paste this into your repository's CLAUDE.md or AGENTS.md, and every agent on the machine coordinates through the same queue:

Run every check through the local coordinator and declare what it uses:
  agc run --label "<what>" --resource cpu=2 -- <command>
Land a pull request only through one gate-and-publish request; never merge directly:
  agc land <pr> --resource cpu=4 -- <full test command>
Never run agc from inside an admitted job. A stale-main or head-changed refusal means:
update the branch, push, and submit a new land request.

The agent guide has the long form, what every refusal and handback means and what to do next, and notes for sandboxed shells. This repository's own AGENTS.md is a worked example.

Run work

agc run  --label "unit tests"   --resource cpu=2 -- python -m pytest -q   # an ordinary check
agc full --label "release gate" --resource cpu=4 -- ./scripts/test.sh      # a clean exact-head receipt
agc land 123 --label "land PR 123" --resource cpu=4 -- ./scripts/test.sh   # gate and publish, one row
agc list                                                                   # every job on the machine
agc show check-0123456789ab                                                # one durable row, as JSON
agc log land-0123456789ab --follow                                         # one combined log
agc cancel check-0123456789ab                                              # process-group cancellation
agc tui                                                                    # live view across repositories

Every job implicitly holds one jobs slot. Repeatable --resource NAME=UNITS options add named, configured resources; an unknown or impossible request fails instead of waiting forever. Without a binding, a name is admission accounting only. With a binding in config.json, the broker applies and measures it, and every run reports what was requested, applied, and observed. Scratch is opt-in: a job that declares neither a tmpfs nor a project-quota policy receives no temporary directory from AGCoord, and inherited TMPDIR, TMP, and TEMP values are removed. The resource contract covers bindings, delegated cgroups, child CPU leases for tools that fan out inside one job, and the optional pytest-xdist adapter.

full validates an exact clean head and keeps a durable receipt; it is ordinary lane work, not a barrier. land is the only barrier. Push the branch, open the pull request, and submit from a clean checkout of that head: the row excludes other lands in its repository and jobs from its own worktree, holds its lane and resources from preflight through publication, and never rebases or rewrites commits. If the target advanced, the default GitHub adapter first merges it into the request branch and pushes with an exact lease; --no-target-sync refuses instead. A red gate records gate-failed and publishes nothing. stale-main, head-changed, pr-not-ready, publish-failed, merge-error, and avoided-commit are the other handbacks, and none of them moves the target. Cancellation is refused only once a land is publishing. The atomic landing contract is the authority.

Maintenance stays in the same tool. agc drain --reason ... refuses new submissions while admitted work finishes, and agc resume <drain-id> reopens the queue. agc avoid <sha> stores a commit that no landing on this machine may publish again after a target rewrite. agc clear removes terminal history while the queue is idle.

State lives in ${XDG_STATE_HOME:-~/.local/state}/agcoord; AGCOORD_STATE_DIR or --state-dir selects a different spool for an unmanaged coordinator. One config.json there holds capacities, bindings, cgroup_root, database_timeout, and native_broker; with no file at all, capacity defaults to two job slots. A spool left below protocol 5 by a release before 0.6.0 is refused with instructions; see migrating a pre-native spool.

How it compares

If you use What it coordinates Machine resources Merge gating
GitHub merge queue, Mergify Pull requests, on hosted CI No Yes, in CI
pueue, task-spooler, nq Shell commands on one machine Parallel count only No
Claude Squad, Conductor, Vibe Kanban Agent sessions and worktrees No Manual
Gas Town An agent workforce with an LLM-run merge queue Session count cap Yes
Container limits One container Static per container No
AGCoord Jobs from any agent, tool, or person Declared and enforced Yes, atomic with the gate

AGCoord sits under the session managers and beside the hosted queues. Use one or the other per branch: a branch that requires a hosted merge queue rejects the direct ref update that atomic publication performs for anyone without bypass rights. The comparison covers each of these by situation, with Gas Town in depth.

Documentation

Project status

AGCoord is distributed as the agcoord project on PyPI, with import package agcoord and the agc console command; python -m agcoord remains an equivalent module entry point. Build and install development checkouts in an isolated environment rather than copying modules into another project. Contributors follow AGENTS.md and the contributor workflow. The gourd mascot and its asset notes live under docs/assets.

Release files for agcoord 0.6.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agcoord 0.6.3
File Size Uploaded
agcoord-0.6.3.tar.gz 1.6 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for agcoord 0.6.3
File Interpreter ABI Platform
agcoord-0.6.3-py3-none-any.whl Python 3 none any Details

Total release size: 1.7 MB

Release files / agcoord-0.6.3.tar.gz

Download URL agcoord-0.6.3.tar.gz
Size 1.6 MB
Tags Source
SHA-256 checksum
How to use checksums
c2801ca647a1ae1543234262ea06e50e6f9d0a9d40b0a5831b0728f23af76079
BLAKE2b-256 checksum
How to use checksums
02d4824b10b95a6eabb87c3e2ea26165c2dbfbb94209dba32652260b0a0a3f37
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.11

Release files / agcoord-0.6.3-py3-none-any.whl

Download URL agcoord-0.6.3-py3-none-any.whl
Size 85.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
95bee0b8fe192afb9eb7bbce77fdeba48c71053a5c5d8a1c8eef43179a01e297
BLAKE2b-256 checksum
How to use checksums
6a4cab45c1ea6faf09b38e37769b3326d7212138869fdc0cb75eeb55a67e884d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.11
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page