Show HN: Devloops – Adversarial agent loops so humans only make the key decision A developer released devloops, an open-source set of reusable agent-loop skills that splits coding-agent maintenance work into three adversarial loops — producer, worker and gatekeeper — so humans only accept issues and merge pull requests. The producer audits code and files candidate issues, the worker implements approved issues as pull requests, and the independent gatekeeper reviews each PR and issues a verdict, with the worker and gatekeeper iterating until approval; agents never merge. The skills install into a project's `.agents/skills/` directory via `devloops/scripts/install.sh`, require Python 3.8 or later, git and a logged-in GitHub CLI `gh`, and use `tick_gate.py` exit codes (0 RUN, 1 NOOP, 2 BUSY, 3 ERROR) to decide whether a scheduled tick starts the agent. Reusable agent-loop skills for coding agents. devloops gives a coding agent three loops: producer , worker , and gatekeeper . Each loop is a skill SKILL.md plus helper scripts . You install the skills into a project's .agents/skills/ directory. A per-project file, devloops.config.yaml , holds the project values repo, branches, commands, protected paths, labels . Most maintenance work is routine: find a problem, write an issue, fix it, review the fix. devloops lets agents do that routine work in an adversarial loop : - The producer audits the code and files candidate issues. - The worker implements approved issues as pull requests. - The gatekeeper is an independent reviewer. It tries to find defects in each PR and gates it with a verdict. It does not trust the worker. The worker and the gatekeeper go back and forth until the gatekeeper approves. The human does not do this routine work. The human makes only the important decisions: - which issues to accept the approved label , - user-visible behavior, permissions, and security-sensitive changes, - the merge. Agents never merge. A human always merges. producer-loop ──► issue auto:producer │ gatekeeper-loop ──► validated | rejected checks the issue against the code │ human ───────────► approved accepts the scope │ worker-loop ─────► PR │ gatekeeper-loop ─► verdict comment + gatekeeper: label │ changes-requested ─► worker responds ─► re-review ... ▼ approve + CI green │ human ───────────► merge - The worker services its open PRs first conflicts, gatekeeper findings, comments, failing CI . It picks a new issue only when no PR needs action. - The worker skips producer issues that do not have the approved label. - The worker and the gatekeeper can share one GitHub account. So verdicts are PR comments with a hidden marker, plus a gatekeeper: label. - The gatekeeper adds gatekeeper:needs-human to security-sensitive PRs and PRs that touch protected paths . A scheduler starts each loop in ticks . Before a worker tick starts the agent, tick gate.py decides if there is anything to do: 1. --lock takes tick.lock . If another tick holds the lock, it prints BUSY . 2. It computes a fingerprint with one GitHub GraphQL request your open PRs: head, mergeable state, CI state, last update, last comment; candidate issues: last update . It keeps this tick-start fingerprint. 3. If the state has no current work and the fingerprint is equal to the saved lastFingerprint , it prints NOOP . The scheduler does not start the agent. 4. At the end of the tick: - idle or needsUser tick: --update --unlock saves the tick-start fingerprint; - tick that did work, or failed: --unlock only. The next tick runs again. 5. idle or needsUser tick: So a change that happens during a tick is never hidden, and only an idle, unchanged state gives NOOP . Exit codes: 0 RUN, 1 NOOP, 2 BUSY, 3 ERROR auth, network, or GraphQL failure . The producer has its own gate, producer gate.py . It picks the most overdue task --next from the task periods in the config. - Python 3.8 or later no third-party packages; tested with 3.13 - git - GitHub CLI gh , logged in, with push permission to the project repo - A coding agent that can load skills from .agents/skills/ git clone https://github.com/fritzprix/devloops.git devloops/scripts/install.sh /path/to/project copy devloops/scripts/install.sh /path/to/project --link symlink follows updates The script installs: - skills/ to