Portable, model-neutral engineering policy, skills, hooks, and repository enforcement for coding agents.
  • Python 91.7%
  • Shell 8.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-11-06 12:58:55 -06:00
.github/workflows CI: drop the macOS Validate leg (owner decision: no Mac runs this system) 2026-10-14 21:20:08 -05:00
bin Replace the global AGENTS.md with a short working agreement 2026-10-10 01:16:08 -05:00
docs Fix review findings on the workflow cleanup: land commits the CHANGELOG release heading before the push so it is reviewed; worker-first names this repo's issues.md as the coordinator's tooling log; fix-issue puts found issues in their own commit; review grades findings BLOCKER/FIX/NIT; README and parity doc say workers run on the Hermes harness; correct three issues.md entries 2026-10-12 16:55:17 -05:00
hooks fix: skip unmanaged global skill symlinks instead of blocking hooks 2026-10-10 01:09:06 -05:00
host/local fix: restore the shared binary catalog contract and drop the jq dependency 2026-08-06 11:02:31 -05:00
lib fix: accept -p/--prompt as Kimi print mode 2026-08-03 18:41:40 -05:00
skills Fix review findings on the workflow cleanup: land commits the CHANGELOG release heading before the push so it is reviewed; worker-first names this repo's issues.md as the coordinator's tooling log; fix-issue puts found issues in their own commit; review grades findings BLOCKER/FIX/NIT; README and parity doc say workers run on the Hermes harness; correct three issues.md entries 2026-10-12 16:55:17 -05:00
tests Keep the legacy-migration test independent of ignored Claude settings: copying .claude/settings.local.json into the fixture made its checkout dirty, so validate.sh failed on any host with local Claude settings 2026-10-12 09:19:19 -05:00
worker-host worker-pane.sh: the pixel-lighter repo gets its own herdr workspace 2026-11-06 12:57:34 -06:00
.gitignore Ignore local Claude Code settings so checkouts stay clean 2026-10-11 07:43:27 -05:00
action.yml feat: extract portable coding agent system 2026-07-13 14:31:08 -05:00
AGENTS.md Working agreement: workers leave the release heading to the coordinator, who records tooling issues in coding-agent-system's issues.md; review fixes are new commits 2026-10-12 17:10:03 -05:00
CHANGELOG.md worker-pane.sh: the pixel-lighter repo gets its own herdr workspace 2026-11-06 12:57:34 -06:00
CLAUDE.md feat: extract portable coding agent system 2026-07-13 14:31:08 -05:00
configure-hosts.py feat: add Kimi worker adapter, parity skills, and launcher hardening 2026-07-30 10:41:46 -05:00
install.sh feat: migrate exact legacy agent installs 2026-07-13 17:01:00 -05:00
issues.md issues.md: validate.sh fails 10 dispatch tests when TMPDIR sits inside a git work tree (Foreman scratch) 2026-11-06 12:58:55 -06:00
LICENSE feat: extract portable coding agent system 2026-07-13 14:31:08 -05:00
OPENCLAW_AGENT_SKILLS_LICENSE feat: add portable global agent system 2026-07-13 00:21:23 -05:00
README.md worker-host/install.sh --apply puts regular file copies, not symlinks, in the Cal and Foreman profile scripts directories (wait-for-workers.sh, worker-watchdog.sh, model-usage-watch, worker-pane.sh, watch-worker.py). The Hermes cron guard blocks a script whose symlink resolves outside the profile scripts directory; the 2026-10-12 apply left two watchdog cron jobs failing every 5 minutes. --check compares copies by content and reports a symlink there as DRIFT symlink; the launcher, helpers, tests and chain-workers.sh stay symlinks. Backups use cp --remove-destination so a same-second backup symlink is never written through. Covered in test-install-check and test-install-apply, which fail on the previous install.sh 2026-10-13 06:22:07 -05:00
STEIPETE_AGENT_SCRIPTS_LICENSE feat: expand portable agent system 2026-07-13 06:42:02 -05:00
system.json Provision the tirith scanner system-wide for isolated worker accounts 2026-09-10 12:11:04 -05:00
validate.sh Add worker-host/install.sh: --check (default, read-only) sha256-compares the 14 installed files and 24 client paths with the repository and prints DRIFT lines, exit 1 on drift; --apply refuses on the reboot hold or any active or unknown run, backs up to /var/backups/agent-worker/<timestamp>/, installs with the target's owner and mode (sudoers checked by visudo), swaps client paths to symlinks into worker-host/, daemon-reloads only when a unit changed and restarts only the broker service, never its socket. Not applied: the live copies still drift, as issues.md now says. README gains a worker-host section 2026-10-12 21:48:04 -05:00

Coding Agent System

A portable, model-neutral engineering system for Codex, Claude Code, Kimi CLI, Cursor, and other coding-agent hosts. The coordinator skills (worker-first, review, land) assume workers run on the Hermes harness through repo-worker, whose host copy lives in worker-host/. It keeps policy terse, loads workflows as skills, dispatches skill-owned hooks, reconstructs work from repository evidence, and uses deterministic checks for the parts that should not depend on judgment.

Ownership

This repository owns the portable layer:

  • AGENTS.md: canonical global engineering policy.
  • skills/: assignable job contracts and their scripts, references, and hooks.
  • hooks/dispatch.py: one host adapter for global and repository skill hooks.
  • bin/: small deterministic helpers for continuity, delivery, review, and repository hygiene.
  • system.json: the exact managed skill, command, binary, and hook catalog.
  • install.sh and configure-hosts.py: idempotent shared installation plus a caller-selected host integration.
  • host/local/: the local-machine invocation defaults for claude, codex, and kimi; these are not part of the shared binary catalog.
  • tests/ and validate.sh: portable enforcement.

Product facts and workflows remain in each product repository. VM credentials, VM launch behavior, and cloud bootstrap belong in hermes-os/coding-agent-vm-setup, which pins this repository at an exact Git revision and supplies its own host integration.

Install

git clone https://github.com/hermes-os/coding-agent-system ~/coding-agent-system
~/coding-agent-system/install.sh
agent-system-doctor

The installer wires the canonical policy and skills into ~/.agents, Codex, Claude Code, Kimi CLI, and Cursor while preserving unrelated host configuration. Kimi receives the policy through a generated default-agent extension because it does not load a home-level AGENTS.md for repository work. That extension disables Kimi's inherited subagents so repository work stays inside its assigned worker boundary. Native Stop and shell-only PreToolUse hooks dispatch through the same skill-owned hook catalog, and a prompt guard rejects any resumed session whose persisted system prompt lacks the current policy digest. Policy updates therefore require a fresh Kimi session; unchanged managed sessions remain resumable.

The managed Kimi launcher covers noninteractive --print and --quiet work, including explicit policy-current session IDs. It rejects interactive picker, continue, wire/ACP, caller agent, config, and skill-directory overrides because those paths can restore or create an unverified system prompt in Kimi CLI 1.47.0. The acp, term, and web subcommands are rejected for the same reason. Administrative Kimi subcommands pass through unchanged.

The shared system does not author model assignments. A provider-required, operator-selected default may remain in local provider configuration as host state. Persistent agent memory is disabled.

The default install selects host/local, which pins Claude Remote Control for every interactive session and enforces one access contract across providers. Agent invocations default to AGENT_ACCESS_MODE=write: Codex bypasses approval and sandbox prompts, Claude uses bypassPermissions, and Kimi uses --yolo. AGENT_ACCESS_MODE=read is the explicit exception for read-only inspection and review; it disables those bypasses. Orchestrators must pair read mode with an external read-only filesystem boundary. Administrative provider commands pass through unchanged.

Integrations such as the VM setup call install.sh --host-integration /path/to/integration; the shared catalog never owns those launchers. Claude and Codex launchers are the base integration contract; a host may declare Kimi support by also supplying an executable bin/agent-kimi.

Global skill hooks remain available from any working directory. Repository skill hooks are discovered only after Git resolves the working directory to a repository root, so a home directory, scratch directory, or cross-repository launcher cannot accidentally reinterpret its .agents tree as project policy. A directory with a broken or inaccessible .git marker still fails closed; inside a valid repository, all repository hook validation remains strict. Start the agent in the target repository when that repository's local hooks should apply.

Use install.sh --coordination-repo /path/to/git-root when a host integration should keep cross-host lease refs in a different repository. The chosen path is recorded locally in ~/.agents/config.json; it is host state, not project memory.

Enrolled hosts can exchange constrained, exact-SHA PR work with agent-forge-handoff. Local forgePeer.localPeer, repository, and trusted-author settings define its authorization surface; handoffs never grant mutation, commands, merge, or deploy authority. See the portfolio skill before enabling a host-specific watcher. Peer enrollment comes only from the canonical host config (or a root-pinned nonstandard install), never a CLI or environment override. A bounded organization discovery call overscans recent constant-label candidates and revalidates every returned packet without interpreting PR bodies as instructions. Canonical peer enrollment is read through one bounded, no-follow descriptor and fails closed if the file or path changes during the read.

To replace an older cataloged but unmanifested installation, pass its clean tracked source explicitly:

./install.sh --migrate-from-system-root /path/to/old/system

Migration uses the old source's own system.json, retires exact legacy-only paths, and accepts only destinations that still match that source tree. An altered, untracked, or unrelated path fails the whole preflight without changing host configuration.

Repository Contract

Product repositories keep one root AGENTS.md beginning with:

READ ~/.agents/AGENTS.md BEFORE ANYTHING (skip if missing).

CLAUDE.md is a symlink to AGENTS.md. Product-specific skills live under .agents/skills. The records are the commit log, CHANGELOG.md (an entry for each user-visible change, under ## Unreleased), and a root issues.md that lists known issues no commit has fixed yet. Agents write no plan, spec, or hand-off files unless the owner asks for one.

Run the deterministic repository check before delivery:

agent-repo-check --repo "$PWD" --strict

It validates instruction wiring, local skills and hooks, document metadata, active-plan shape, and tracked high-risk clutter. Project tests and delivery commands still come from the repository's own guide.

After the global-system revision is published, wire a repository to that exact revision with:

agent-repo-adopt --repo "$PWD"

This creates only the CLAUDE.md pointer when missing and a managed GitHub Actions workflow pinned to the full global-system commit SHA. It refuses to overwrite an unrelated workflow or repository guide. Re-run with --check to detect a stale pin without changing files.

Worker host

worker-host/ is the source of the live worker system on Hermes's Linux host, laid out by install target: libexec/ (runner, broker, Hermes adapter and configs, Codex auth sync, coordination probe) for /usr/local/libexec, etc/ for /etc (model policy, sudoers rule), systemd/ for /etc/systemd/system, bin/ for the client tools in the Cal and Foreman profiles, and tests/, which validate.sh runs. The two root-only tests (test-worker-broker-policy, test-worker-permission-policy) run only with WORKER_HOST_ROOT_TESTS=1 (as root or through sudo -n); validate.sh does not set it, so they are skipped by default: WORKER_HOST_ROOT_TESTS=1 worker-host/tests/run-tests.

worker-host/install.sh --check   # read-only; prints DRIFT lines, exits 1 on drift
worker-host/install.sh --apply   # installs from the repo; refuses while a run is active

--apply backs up each replaced file under /var/backups/agent-worker/<timestamp>/, installs with the target's current owner and mode, replaces the client paths with symlinks into worker-host/ (except the five bin/ tools in the Cal and Foreman profile scripts/ directories, which become regular file copies: the Hermes cron scheduler blocks a script whose symlink resolves outside that directory, and --check reports a symlink there as drift), runs systemctl daemon-reload only when a unit changed, and restarts only the broker service (never its socket). It also refuses while ~/.hermes/profiles/cal/state/HOLD-FOR-REBOOT exists, and while worker-host/ has uncommitted changes or untracked files: it installs committed content only. The Cal workspace copies of agent-hermes-worker and agent-worker-coordination-probe (~/.hermes/profiles/cal/workspace/scripts/) are older than the installed ones; --apply replaces them with symlinks to the worker-host/ copies, which match the installed versions.

Before it installs a unit or the broker, --apply records the systemd steps it still owes (daemon-reload, try-restart agent-worker-broker.service) in /var/backups/agent-worker/pending. If a run starts during the apply, the broker is installed but not restarted: it prints the exact sudo systemctl ... command to run when idle and exits 3. If it stops between a unit install and daemon-reload, it prints that command too. --check lists recorded steps as PENDING lines (exit 1), and the next --apply runs them instead of reporting nothing to apply. Exit status: 0 done or no drift, 1 drift or refused, 2 usage, 3 installed with a systemd step still pending.

Validation

./validate.sh
./install.sh
agent-system-doctor --repo "$PWD"

The source catalog is intentionally small. Add a shared skill only when it is a reusable job with a distinct output contract; keep product workflows local.

Attribution

The architecture follows Peter Steinberger's public agent-scripts work. See STEIPETE_AGENT_SCRIPTS_LICENSE and OPENCLAW_AGENT_SKILLS_LICENSE for adapted components and their licenses. New repository code is MIT licensed.