{"id":51678837,"url":"https://github.com/qiankunli/devloop","last_synced_at":"2026-07-15T10:33:05.994Z","repository":{"id":363242603,"uuid":"1262434489","full_name":"qiankunli/devloop","owner":"qiankunli","description":"A guard-railed, closed-loop workflow for AI coding agents: live state bus + execution-level hard intercepts for Claude Code and Codex (GitHub PR / GitLab MR). From step-level to requirement-level; eval-driven, spec-driven, human-in-the-loop.","archived":false,"fork":false,"pushed_at":"2026-07-09T11:25:18.000Z","size":1163,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-09T13:12:39.944Z","etag":null,"topics":["agentic","agentic-coding","agentic-workflow","ai-agents","ai-coding-agent","autonomous-coding-agent","claude-code","claude-code-plugin","coding-agent","developer-tools","eval-driven-development","guardrails","human-in-the-loop","llm","llm-as-judge","spec-driven-development"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/qiankunli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-08T01:37:55.000Z","updated_at":"2026-07-09T11:25:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/qiankunli/devloop","commit_stats":null,"previous_names":["qiankunli/devloop"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/qiankunli/devloop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiankunli%2Fdevloop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiankunli%2Fdevloop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiankunli%2Fdevloop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiankunli%2Fdevloop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qiankunli","download_url":"https://codeload.github.com/qiankunli/devloop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiankunli%2Fdevloop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35501664,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-15T02:00:06.706Z","response_time":131,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic","agentic-coding","agentic-workflow","ai-agents","ai-coding-agent","autonomous-coding-agent","claude-code","claude-code-plugin","coding-agent","developer-tools","eval-driven-development","guardrails","human-in-the-loop","llm","llm-as-judge","spec-driven-development"],"created_at":"2026-07-15T10:33:05.376Z","updated_at":"2026-07-15T10:33:05.984Z","avatar_url":"https://github.com/qiankunli.png","language":"Python","funding_links":[],"categories":["Source Catalog"],"sub_categories":[],"readme":"[English](./README.md) | [简体中文](./README.zh-CN.md)\n\n# devloop\n\n**A guard-railed development loop for AI coding agents.** A cross-CLI plugin marketplace: `devloop` is the first (and flagship) plugin — a developer workflow for Claude Code and Codex, working with both **GitHub (PR)** and **GitLab (MR)** (picked per-repo from the origin remote); `example` is a placeholder showing the repo is built to host *multiple* plugins.\n\n\u003e Claude Code and Codex are supported. Design / architecture: [AGENTS.md](./AGENTS.md). Each plugin's own docs live in its directory.\n\n## The problem\n\nWhen you code with an AI agent, the time sink usually isn't \"is the code correct\" — it's three **structural losses**:\n\n1. **Information lag** — the agent doesn't know the real git / workspace state and guesses from chat history. Classic failure: it grinds away on a feature branch whose MR was *already merged* (and source branch deleted) on the server, never realizing until commit-time preflight stops it — forcing a re-branch + re-commit + re-MR every time.\n2. **Soft conventions can't enforce** — \"don't commit to master\", \"don't `git add -A`\" are just prompts. When the agent decides not to follow them, you have **no execution-level interception**. Committing to a protected branch, staging stray sensitive files, editing on a stale branch — all happen for real.\n3. **Concurrent sessions collide** — running several CLI sessions (or several agents) on one workspace is routine, but they share checkouts and state: a second session switches the branch under the first one's feet and scrambles its uncommitted work, or one session's no-arg command silently resolves to the repo *another* session just touched. Out of the box, nothing arbitrates who owns what.\n\n## What devloop does — two levers\n\n- **A state bus eliminates information lag.** The current subproject's branch / working tree / recent MRs / validation state is injected into *every* prompt, so the agent knows reality before it edits the first line.\n- **Hard intercepts turn soft conventions into execution-level boundaries.** `PreToolUse` hooks return `deny`; the agent cannot route around them.\n\nBoth levers share one hub: a structured state bus under `.devloop/`. State written on `git commit` / `cd` / background polling is reused across N later prompt injections and M protected-branch checks at zero extra cost.\n\nLoss 3 is answered by **session-grain state** riding the same two levers: an owner lock per checkout (guests' branch switches and edits are denied, routed to a worktree) plus a per-session repo binding (one session's fallback never resolves to another session's repo) — see *Aggregate-workspace \u0026 multi-session as first-class* below.\n\n## Design ideas worth knowing\n\n**What to hard-block vs. soft-hint** — the rule: *no legal edit case → hard-block; a legal exception exists → soft-hint.* Your current branch is always in one of four states:\n\n| State | Meaning | Handling |\n|-------|---------|----------|\n| protected | main / master / release* | **hard-block** commit/push |\n| healthy | normal feature branch, in progress | allow |\n| in-flight | PR/MR opened, awaiting human merge | **soft-hint** (inject one `IN-FLIGHT` line) |\n| inactive | PR/MR merged / closed | **hard-block** Edit/Write |\n\n`protected` and `inactive` hard-block cleanly — editing there has no legitimate reason. `in-flight` only hints, because there's a legal exception (you might be amending your own PR/MR) the machine can't reliably tell from new work, so it feeds the fact to the agent and lets it choose.\n\n**Structural guarantees, not just hints** — a new branch's base is decided by *intent, not by where HEAD happens to sit*: opening new work (`--branch`) always cuts from `origin/\u003ctarget\u003e`, and a freshly cut branch is asserted to carry only this run's commits before push/PR. So even if the agent ignores the `IN-FLIGHT` hint, forking off an in-flight branch can't smuggle its commits into the new PR.\n\n**Aggregate-workspace \u0026 multi-session as first-class** — a workspace root holds many independent git subprojects (often symlinked). Scripts never trust shell `cwd` (they resolve the repo by explicit `--repo` → cwd's repo → *this session's* last-active repo; with no binding of its own a session is asked for an explicit `--repo` rather than guessing from another session's activity), and an *owner lock* keeps two concurrent sessions from mixing changes into one working tree. Plain single-repo mode is fully supported too — auto-detected, no manual switch.\n\n**native-first** — every capability sits on the most native event primitive instead of a workaround:\n\n| Capability | Workaround (old) | devloop (native) |\n|------------|------------------|------------------|\n| project-enter awareness | regex-parse `cd` | **`CwdChanged`** auto-enter |\n| survive compaction | TTL safety-net (timed guess) | **`PostCompact`** → re-inject |\n| `AGENTS.md` changes | mtime polling | **`FileChanged`** + `watchPaths` |\n| PR/MR awareness / branch staleness | hook-heartbeat scheduler | **`monitors`** background poll |\n\nAll git goes through one `gitcmd` seam, all code-review hosting through one `lib/forge` facade (GitHub / GitLab as peer adapters, picked per-repo), all user config through one `lib/config` seam. Every guard is **fail-open** — a broken guardrail at worst fails to block; it never blocks your work.\n\n## Where it's heading — from step-level to requirement-level\n\ndevloop makes the loop *run smoothly*, but its **granularity** is still step-level — a human nudges at every step. The north star is to lift that intervention from *step-level* to **requirement-level**: you state a requirement; the agent develops → verifies → reads the result → self-corrects in a closed loop; a human only **accepts** at the end.\n\nThat hinges on the **verify** link climbing from static checks (lint / test) to a real **verdict** the loop can converge against — and a verdict worth converging on isn't one pass/fail. Four parallel, *accumulable* judgment dimensions, each answering its own question:\n\n| dimension | answers | how |\n|-----------|---------|-----|\n| **correctness** | does the contract / behavior hold | black-box, against a running system |\n| **effectiveness** | is the agent's output actually good | black-box (incl. LLM-as-judge) |\n| **capacity** | does it hold under load | black-box |\n| **taste** | is it built the way you'd want — design / boundaries / naming | white-box, reads the diff, no deploy needed |\n\nTwo boundaries keep it honest (and line up with the *levels-of-autonomy*, *eval-driven* and *spec-driven* directions the field is converging on): **the human keeps merge** — release authority never moves into the loop — and **the agent changes code to meet the bar, never moves the bar itself** (specs and thresholds stay human-governed, the same side as merge). Think L4 \"human as approver,\" not L5.\n\ndevloop is the **loop machine** — the state bus, the hard intercepts, and the run / verify / deploy beats; the verdict producers are a separate, pluggable concern. So the open surface is wide: more judgment dimensions and sensors, wiring a verdict back into the loop as feedback, the deploy beat that lets behavioral checks hit a real system, the white-box taste judge. **If this frontier interests you, open an issue or a discussion — ideas here are exactly the kind of contribution we're after.**\n\n*Adjacent lines of work this draws on and sits among: **agentic coding** / **autonomous coding agents**, **self-correcting** \u0026 **verifier-driven** loops, **eval-driven development** (**LLM-as-judge**), **spec-driven development**, and the **levels of autonomy** framing for **human-in-the-loop** AI software engineering.*\n\n---\n\n## Install (Claude Code)\n\nRuntime requirement: **Python 3.10+**. devloop's launcher automatically selects the first supported\n`python3`, `python`, or versioned `python3.x` on `PATH`; set `DEVLOOP_PYTHON` to force a specific binary.\n\n```\n/plugin marketplace add https://github.com/qiankunli/devloop.git\n/plugin install devloop@devloop\n```\n\nOptionally run init once (hooks also auto-init on first `cd` into a repo):\n\n```\n# Mode A: aggregate workspace (one root holding many git subprojects)\n\"${CLAUDE_PLUGIN_ROOT}/scripts/python\" \"${CLAUDE_PLUGIN_ROOT}/scripts/init_workspace.py\" \u003cyour-aggregate-workspace\u003e\n\n# Mode B: a single git repo\n\"${CLAUDE_PLUGIN_ROOT}/scripts/python\" \"${CLAUDE_PLUGIN_ROOT}/scripts/init_repo.py\"\n```\n\nForge features (PR/MR creation + state injection) need a token for your host (`GITHUB_TOKEN` / `GITLAB_TOKEN`, or the `forges` block) — see [devloop/README.md](./devloop/README.md) for the unified `~/.devloop/config.json`.\n\n### Codex / opencode\n\nCodex support is packaged through `.agents/plugins/marketplace.json` and `devloop/.codex-plugin/plugin.json`.\n\n```\ncodex plugin marketplace add https://github.com/qiankunli/devloop.git\ncodex plugin add devloop@devloop\n```\n\nYou can also install it from `/plugins` after adding the marketplace. Start a new Codex session after installation; if Codex asks for hook review, open `/hooks` and trust the devloop hooks.\n\nCodex does not expose every Claude event that devloop uses. The Codex manifest points at `devloop/hooks/hooks.codex.json`, which uses the supported subset (`PreToolUse` / `PostToolUse` / `SessionStart` / `UserPromptSubmit` / `PostCompact`) and refreshes cwd/state from `PostToolUse` as the fallback for Claude's `CwdChanged`. `FileChanged` and `SessionEnd` have no Codex equivalent yet, so AGENTS.md reparse and owner-lock release rely on the existing prompt/TTL fallback paths there. For manual init commands under Codex, use `${PLUGIN_ROOT}` instead of `${CLAUDE_PLUGIN_ROOT}`.\n\n### Updating devloop\n\nClaude Code:\n\n```\n/plugin marketplace update devloop\n/plugin update devloop\n```\n\nCodex:\n\n```\ncodex plugin marketplace upgrade devloop\ncodex plugin remove devloop@devloop\ncodex plugin add devloop@devloop\n```\n\nStart a new session after updating so the runtime loads the new hooks and skills. User-level devloop config stays under `~/.devloop/` and is not removed by a plugin update.\n\nopencode remains placeholder-only until its plugin/hook protocol is wired.\n\n## Plugins\n\n| Plugin | What it is | README |\n|--------|-----------|--------|\n| `devloop` | Developer workflow: git/PR (GitHub + GitLab) + cwd-aware state + lifecycle hooks (lint/test/code-review per phase) + live state injection + execution-level hard intercepts (Claude + Codex) | [devloop/README.md](./devloop/README.md) |\n| `example` | Placeholder demonstrating the multi-plugin marketplace structure | [example/README.md](./example/README.md) |\n\n## Adding a plugin\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqiankunli%2Fdevloop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqiankunli%2Fdevloop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqiankunli%2Fdevloop/lists"}