Skip to main content

AGCoord

Golden botanical AGCoord gourd with a curled green stem and leaf

AGCoord is a machine-local coordinator for developers and coding agents that share a workstation. It gives every check, standalone full gate, and atomic gate-and-publication request one durable job ID, then schedules compatible work across repositories without letting two agents accidentally publish stale or untested code.

The coordinator is local infrastructure: one detached broker per OS user, a private durable spool, per-job logs, and an optional terminal UI. It does not require a hosted service. The core package is forge-neutral; GitHub support is an optional adapter.

Get started

AGCoord's production host runs on x86_64 Ubuntu with AppArmor ABI 4, unified cgroup v2 mounted read-write with nsdelegate, kernel.apparmor_restrict_unprivileged_userns=1, systemd 254 or newer, and Python 3.10 or newer. The broker itself is an ordinary unprivileged user service; no root daemon is installed. Full host requirements are in the native host runbook.

1. Install the client and its native host

The Python client and the native host must be the same version, so the client fetches its own:

version=RELEASE_VERSION
python -m pip install "agcoord==$version"
agc host install --download

--download resolves that version's release bundle — the archive, all four .sha256 sidecars, and the three helpers — into an owner-only cache under ${XDG_CACHE_HOME:-~/.cache}/agcoord/native-host, and reuses it on a later install rather than refetching. agc host install then verifies the complete bundle, creates or validates the default managed configuration, performs the privileged activation, enables and starts the user service, checks the installed identity, and submits an enforced one-CPU proof. It refuses an incomplete bundle, a mismatched client version, or a nondefault spool rather than activating a host it cannot prove.

Every client ships the digest of the broker executable it was released against, and the install refuses a package carrying any other broker. That pin arrives with the Python distribution rather than with the download, which is what makes fetching a bundle over the network meaningful — a package's own manifest and sidecars travel with the files they describe.

Installing from a bundle you already hold

A host without network access takes the same eight files in one owner-only directory:

chmod 0700 /path/to/native-host-bundle
agc host install /path/to/native-host-bundle/agcoord-native-host-x86_64-linux.tar.gz

The low-level commands, the pin contract, the upgrade path, and the failure recovery contract are in the native host runbook.

The client refuses to search PATH or fall back to any unpinned broker. Release installs require the root-owned static artifact; source developers may instead select an absolute current-user-owned development build with the documented native_broker configuration.

2. Confirm the coordinator answers

agc list
agc tui

With the production host package configured, the first command asks systemd to start the long-lived user service; later shells and repositories join the same user-scoped coordinator. Explicit development binaries retain detached on-demand startup. agc tui opens the terminal view and needs the supported Textual 8 release line (textual>=8.2,<9), which the base package installs. Textual 1 through 7 are not supported; a future Textual major is admitted only after its real-TUI behavior is validated.

3. Set the capacities this machine really has

State defaults to ${XDG_STATE_HOME:-~/.local/state}/agcoord. Set AGCOORD_STATE_DIR or pass --state-dir to use a deliberate alternate spool for an unmanaged coordinator; the fixed managed service and agc host operations accept only the default state. A fresh agc host install records the process's available CPU-affinity count as both cpu and jobs capacity and requires cgroup-v2 CPU enforcement; with no configuration at all, capacity defaults to two concurrent job slots. One JSON file, config.json in the state directory, configures the broker that owns it:

{"capacities": {"jobs": 4, "cpu": 8, "browser": 1}, "database_timeout": 10}

database_timeout is the optional positive SQLite lock-wait limit in seconds and defaults to 10. Current-protocol spools use WAL mode automatically so ordinary readers do not block behind writers; transient broker-pump and idle-check contention is retried.

4. Submit your first coordinated check

agc run --label "unit tests" --resource cpu=2 -- python -m pytest -q
agc list
agc log run-0123456789ab --follow

That is the whole loop: declare what the command consumes, let the coordinator admit it when the machine has room, and watch it from any terminal. Run work below covers standalone full validation, atomic gate-and-publish landing, and job management.

Run work

Submit focused checks with the resources they consume:

agc run --label "unit tests" --resource cpu=2 -- python -m pytest -q

Every job implicitly holds one jobs slot. Repeatable --resource options add only named, configured resources; unknown or impossible requests fail instead of waiting forever. Those names are admission accounting by default. Optional bindings entries in the same config.json give selected names explicit units and admission-only, best-effort, or required backend semantics; every run then reports what was requested, actually applied, and measured. See the resource contract for the strict binding shape and current backend availability.

On Linux, the built-in cgroup-v2 backend can own the complete descendant lifecycle for an explicitly delegated, namespace-safe cgroup root. It attaches the blocked launcher before user code, kills detached descendants on finish or cancellation, and recovers ownership across broker restart. Typed cpu/logical-cpu and processes/processes bindings add aggregate cpu.max and pids.max limits plus peak and violation reporting; they do not imply CPU affinity. Memory and swap envelopes, bounded temporary storage, and verified per-device block-I/O limits remain separate opt-in contracts. See delegated cgroup setup before enabling a required binding.

Scratch is opt-in: a run that declares neither a complete tmpfs policy nor a complete project-quota policy receives no AGCoord-provided temporary directory, and inherited TMPDIR, TMP, and TEMP values are removed. Jobs that need accounted temporary storage must declare one of those providers explicitly.

If a gate starts several worker-owning tools concurrently, admitted subprocesses can use the public Python child CPU lease API to divide the job's declared CPU budget fairly. Leases support exact or partial grants, waiting, cancellation, crash reclamation, and broker recovery without creating nested jobs. Install agcoord[xdist] to activate the optional pytest-xdist adapter: positive -n modes then lease their worker count inside admitted runs, while plain pytest, -n 0, and pytest outside AGCoord keep their upstream behavior.

Run a standalone full validation for an exact clean Git head when publication is not part of the request:

agc full --label "release gate" --resource cpu=4 -- ./scripts/test.sh

full records the checkout's full 40-character HEAD and checks that the worktree is clean. It remains useful for validation and release preparation, but normal landing does not compose a full row with a later publication row. It is not a barrier or a machine-global lock: compatible work in any repository or worktree can overlap it when configured resource capacities allow it. Only land is a lane barrier, and it excludes just other lands in its repository and jobs from its own worktree.

After pushing the exact clean head and opening a pull request, gate and publish it as one indivisible request:

agc land 123 \
  --label "gate and publish PR 123" \
  --resource cpu=4 \
  -- ./scripts/test.sh
# GitHub is the convenience default and may also be named explicitly.
agc land 123 --adapter github -- ./scripts/test.sh
# Opt out when the request must fail instead of merging an advanced target.
agc land 123 --no-target-sync -- ./scripts/test.sh

land stores the adapter, request, exact checkout/head, gate command, caller environment, and resource claim in one durable repository barrier. The core record keeps adapter and request separate even though the current installed adapter uses GitHub pull-request numbers. If the target advanced while a same-repository request waited, the default GitHub adapter makes one ordinary merge commit from the current target into the unchanged request branch, pushes it with an exact lease, and records that commit as the durable head before running the gate. It then runs the gate once and publishes immediately after a green result without releasing the lane or resources. A red gate publishes nothing. --adapter github is the default when the option is omitted; the core request remains forge-neutral.

Target synchronization never rebases or rewrites existing commits. A merge conflict is aborted and reported before the gate, with the checkout restored cleanly. A concurrent source change, failed lease-protected push, target movement during the gate, or changed post-gate observation ends with a named handback and does not update the target. Use --no-target-sync when even the pre-gate source merge is unwanted. A separate full-plus-merge sequence is not a landing substitute.

Inspect or manage jobs from any terminal:

agc list
agc show land-0123456789ab
agc log land-0123456789ab --follow
agc cancel land-0123456789ab
agc clear
# For planned maintenance:
agc drain --reason "native host upgrade"
agc resume drain-0123456789ab
# After deliberately rewriting main to remove a commit:
agc avoid 0123456789abcdef0123456789abcdef01234567 --reason "removed from main"

clear removes terminal history and its logs only. It refuses while queued or running work exists and never removes the spool, broker ownership, or migration history. drain durably and atomically refuses new submissions without cancelling work already admitted. It waits for those rows—including an authoritative land publication—to become terminal and for the broker to yield ownership. list, show, log, the TUI, and explicit cancellation remain available. Save the returned drain-… ID: only resume with that exact ID reopens submissions. avoid stores a commit that no landing on this machine may publish again: every later agc land refuses before any push if the request, the current target, or the head target synchronization would push reaches it, so a request branch that still carries a commit removed from main cannot bring it back. Rebuild such a request as a fresh branch from the current main. A spool left at protocol 1 through 4 by an AGCoord release before 0.6.0 is refused by every command, which names AGCoord 0.5.2 as the release that migrates it. The Python reference broker and its in-process migrations were retired in 0.6.0; see the pre-native spool guide.

Every canonical contract is listed in the documentation index. The full operating contract, recovery behavior, TUI keys, and resource model are in the coordinator guide. Package maintainers should also read the release guide, and published user-facing changes are recorded in the changelog. Contributors follow the repository workflow in AGENTS.md.

Project status

AGCoord is distributed as the agcoord project on PyPI, with import package agcoord and the agc console command. The python -m agcoord module entry point remains available. Build and install development checkouts in an isolated environment rather than copying modules into another project.

The gourd mascot and its asset notes live under docs/assets.

Release files for agcoord 0.6.0

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.0
File Size Uploaded
agcoord-0.6.0.tar.gz 1.6 MB Details

Built distribution (wheel)

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

Total release size: 1.7 MB

Release files / agcoord-0.6.0.tar.gz

Download URL agcoord-0.6.0.tar.gz
Size 1.6 MB
Tags Source
SHA-256 checksum
How to use checksums
fb9810f904e808280384e36d3943268601e8e59b7f83f77123aa81f4daf6e966
BLAKE2b-256 checksum
How to use checksums
2cde3d9bef73e3450fbff3d8dd7647d93408b6372428bd7395bd402642cde420
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.0-py3-none-any.whl

Download URL agcoord-0.6.0-py3-none-any.whl
Size 83.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
573c00dbcd716aecb41c272a7b2376a528e3b27e2eef132ac27e638f69ccf59f
BLAKE2b-256 checksum
How to use checksums
3b924b24694e4a58f3e36f8752a9bcab66cb5c6737f1d98cf8d1e5c731308735
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