A forge-agnostic framework for AI-native development: human writes the spec, AI builds, humans merge.
Human owns intent and acceptance. AI owns everything between.
No build starts on an ambiguous spec. Specs go through a state machine:
draft → clarify (agent interrogates ambiguity, human answers in batches) → propose (agent breaks down epics/stories/sub-issues) → human approved→ finalize (sub-issues created unlabeled, parent issue = final spec). Trigger labels stay human-only — deciding what to build is the human's call.devloop spec ` advances one round per invocation; every round is a comment
on the issue, so the whole negotiation is on the record.
┌─ SPEC (human) ─────────────────────────────────────────────┐
│ issues + trigger labels · spec templates · /spec command │
│ rule: no build starts without human-authored intent │
├─ ORCHESTRATE (framework) ──────────────────────────────────┤
│ forge adapters (github · gitlab · gitea) · event routing │
│ label vocabulary · command routing · budgets/rate caps │
├─ EXECUTE (pluggable) ──────────────────────────────────────┤
│ agent runtimes: opencode · claude · goose · custom argv │
│ any model backend · skills = Agent Skills spec (SKILL.md) │
├─ VERIFY (AI) ──────────────────────────────────────────────┤
│ user-defined gate command · evidence files required │
│ gate fails → PR marked needs-work, never merged │
├─ REVIEW (AI + human) ──────────────────────────────────────┤
│ AI pre-review rounds (capped) → fixes pushed → HUMAN merge │
├─ MONITOR (AI → human) ─────────────────────────────────────┤
│ scheduled drift probes · tracking issues · verdict tables │
│ chronic flags → candidates for human to call │
└────────────────────────────────────────────────────────────┘
An agent running under devloop can never:
- merge or approve a PR
- apply a trigger label (
ai-fix,ai-build,ai-remove) - close an issue it was spawned from
Comment commands (/retry <issue>, /review <pr>) are the one exception,
and they are safe: devloop executes them for an authorized human (the
author is access-gated before anything happens), and closing a stale PR on
/retry is executing that human's explicit sanction — not the agent judging
its own work. The same carve-out closes an issue whose devloop PR a human
just merged: the merge IS the human's verdict; devloop only records it.
Labels create work; commands re-fire it. Trigger labels and
ready-for-agent are mutually exclusive. Humans merge.
Post in an issue or PR thread (authorized users only — same [access]
policy as everything else):
/retry <issue>— reset the attempt budget, close the issue's stale devloop PR if any, and re-fire the build/review <pr>— run the AI pre-review rounds on an open PR on demand (/reviewinside a PR thread targets that PR)
The workflow triggers on issue_comment with a YAML-level gate so plain
comments never spin up a runner job; non-command comments cost nothing.
Prereqs (all free, ~5 min once):
- Python 3.11+
gh(GitHub CLI), authenticated:gh auth login- an agent CLI, authenticated — e.g.
opencodeorclaude(any model backend they support;runtime.argvtakes anything) - git push access to the target repo
pip install -e . # no runtime deps, stdlib only
devloop init # writes config.toml + skills/ into your repo
# ... edit config.toml: [forge].repo at minimum; check [runtime] and [access]
gh label create ai-fix -R you/your-repo --color 0E8A16 # repeat for
gh label create ai-build -R you/your-repo --color 2A6E3F # ai-remove too
gh label create ai-remove -R you/your-repo --color B60205 # (names must match config)
# The spec loop — one `devloop spec` round per exchange:
devloop spec 42 # ① agent posts clarify questions → you answer in the thread
devloop spec 42 # ② agent posts epic/story/sub-issue breakdown
# you reply `approved`
devloop spec 42 # ③ sub-issues created (unlabeled) + issue body = final spec
# you apply a trigger label on a story issue → `devloop once` builds it
devloop once # process everything pending
devloop watch # poll loop for local / CI-less setupsOn GitHub, the bundled workflow file runs devloop once on label events,
pushes to the default branch, and a schedule; devloop command on comment
commands; and devloop merged closes out issues whose devloop PR a human
just merged. Per-forge auth, scheduling,
label setup, and access-control mapping: see docs/environments.md
(GitLab/Gitea are M2 — no adapter yet).
[forge]
kind = "github" # github | gitlab (future) | gitea (future)
repo = "owner/name"
[labels]
fix = "ai-fix"
new = "ai-build"
remove = "ai-remove"
[runtime]
engine = "opencode" # argv is fully overridable — any agent CLI works
argv = ["opencode", "run"]
[pipeline]
verify = "" # your gate, e.g. "make verify"
review_rounds = 2 # AI pre-review rounds; 0 = off
repair_rounds = 1 # AI fix attempts on review findings before the
# human sees them; 0 = findings go straight up
max_parallel = 1 # raise to build concurrently; each build gets its
# own worktree and file-overlap deliveries defer
max_attempts = 3 # failed attempts per issue before a human re-labels
max_per_day = 0 # per-issue daily attempt cap; 0 = unlimited
# (runaway detection — a poison task can't burn
# tokens all day)
poll_seconds = 300
timeout = 1800 # per-agent-run timeout, secondsEverything is overridable; zero-config works with defaults.
Org-standard knobs once, per-repo deltas on top (pi's global/project
model): ~/.config/devloop/config.toml holds the defaults; the repo
config.toml overrides key-by-key — sections merge, repo wins. No global
file, no change in behavior.
GitHub Enterprise Server: set [forge].base_url = "ghe.example.com" —
it reaches every gh call as GH_HOST; authenticate with
gh auth login --hostname ghe.example.com. Git remote operations are
untouched (the checkout's remote already points at the right host).
- Guardrails bind devloop's forge calls, not the agent's shell. The agent
runtime can still invoke
gh/gitdirectly — real enforcement (tool denylists at the runtime layer) lands in M1. Until then, run agents with your runtime's own permission controls. devloop initreads bundled templates from the source tree — install editable (pip install -e .) until M1 ships proper package data.- Config keys are validated with a warning on unknown keys; unknown values are not type-checked.
devloop/ orchestrator: events → agent job → PR
forge/ Forge interface + adapters (github today)
runtime/ AgentRuntime interface + engines
skills/ bundled generic skill pack (SKILL.md spec)
tests/ guardrail + routing checks