Skip to content

rxdt/loopgate-harness

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

12 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Blue infinity loop

L∞pGate

A coding-agent loop harness for Claude, Codex, Copilot, or any CLI agent. A dumb Ralph loop runner tells an agent to "Go!" and hands it a PROMPT. Agents can edit. Gates decide what lands. You set the plan in motion. The loops eat the prompt, and each iteration must update specs and commit through guardrails.

Python Status PRs Welcome GitHub activity GitHub Release GitHub Repo Size X (formerly Twitter) Follow Claude


TL;DR: Getting Started.

  1. uv run harness install <your-project-name>
  2. Write your project goal in docs/plan.md
  3. harness run <agent=claude|codex|agy|copilot> [max_iterations] [max_minutes]
  4. Not what you wanted? Refine docs/plan.md / docs/PROMPT.md and re-run

Features

  • Quality-first: Fight the AI slop with standards and style πŸ’―
  • Worker-agnostic: Claude, Codex, Copilot, Agy, or any prompt-reading CLI
  • No lazy: Agents work, only if they pass the quality gates you set βœ…
  • Repo-as-memory workflow: specs/status/prompt are durable but code is king, leaving you free 😎
  • Built-in stack: Ruff, Pyright, Pylint, Semgrep, Complexipy, Hypothesis, 100% coverage β˜‘β˜‘β˜‘
  • Progressive: Preflight vs full gate split πŸ†—
  • Forbidden-path containment: Don't touch that!-configurable πŸ›‘
  • Installable project template: harness install loopgate gets the repo ready ▢️
  • No-rot: Fresh-context agent iterations to reduce context rot πŸ”„
  • Simple: One command setup gets you git hooks and everything else
  • No-waste: Timeouts and time-limits for all loops ⏸
  • Agent containment prioritized: Stop the madness (and Semgrep for safety) πŸ”“

Details

docs/PROMPT.md tells each agent to pick a spec and build. docs/specs/ say what to build. The agent decides what next. You keep docs/plan.md current, and specs get rewritten from it (agent is told in docs/PROMPT.md to update the specs). Each iteration the agent updates its spec and PROJECT_STATUS. Ideas from ghuntley, How to Ralph Wiggum.

Tip

If you don't like ANYTHING in this framework, remove it.

Start a project

  1. From inside the checkout, run harness install <your-project-name>. Names the project, installs dependencies, and sets up the git hook.
  2. Write your grand vision into docs/plan.md.
  3. Optionally add the first spec in docs/specs/, or have an agent draft the first specs.
  4. Put product code under src/ and list new source directories in pyproject.toml [tool.coverage.run].
  5. Strict Ruff rules, type checking, pyright, complexipy, and pytest coverage are set in pyproject.toml.
  6. Your coding quirks go in harness/preferences.py.
  7. Run a loop:
harness run <agent> [max_iterations] [max_minutes]  # agent: claude/codex/agy/copilot. ralph loop runner adds prompt

L∞P architecture engine flow

A L∞PS Loop

The repo is the only memory. Each iteration is a fresh-context agent.

  • docs/specs/ say WHAT to build
  • constant docs/PROMPT.md tells the agent: read docs/specs/, review src/, build the most important unfinished thing
  • agent builds
  • agent commits
  • every git commit passes the fast preflight (lint, format, plus loop containment for the agent)
  • every git push runs the full gate: lint, types, semgrep, tests, 100% coverage
  • the loop stops at max_iterations, a nonzero worker exit, or a timeout
  • Unspecified iterations/minutes β†’ default to 2 iterations Γ— 20 minutes each
  • The harness is worker-agnostic. Any agent CLI that reads a prompt from stdin and can edit/commit works.

L∞PS Agents

Safety

harness run launches an autonomous LLM worker with the configured permissions, e.g. --permission-mode acceptEdits or --sandbox danger-full-access.

The gate bounds what any commit may touch, but the worker itself is not truly sandboxed to this repo. Consider the balance: without access it cannot do much. With machine access it can wreak havoc. Under a permissive mode it can run arbitrary shell. You are authorizing real changes. Choose the worker and permission mode deliberately.

The Gate: Tiered Checks

pyproject.toml is the single source of harness configuration: [tool.harness.gate] holds forbidden_files, forbidden_dirs, forbidden_patterns, and every check command; [tool.harness.agents] holds the agent presets. harness/preferences.py holds human's style checks other tools can't catch. Containment runs during loop execution. Humans own all of it (pyproject.toml is agent-forbidden; harness/preferences.py is part of harness/).

⚑ harness preflight (pre-commit) β†’ fast checks. Ruff lint + check format for everyone, plus containment for the agents. Self-heals by un-staging forbidden files.

βœ… harness gate (CI/PR pre-push). Local checks mirror CI β†’ ruff lint + format report-only, pyright, pylint, semgrep, complexipy, hypothesis, pytest @ 100% cov.

Only humans can bypass triggered gates and commit by adding flag --no-verify.

Layout

harness/        the gate, loop runner, CLI, custom user checks       (πŸ€– forbidden)
  preferences.py  user-defined preferences not covered by tools      (πŸ€– forbidden)
  gate.py         mirror the CI locally + preferences.py honored     (πŸ€– forbidden)
  tests/          the harness's own tests                            (πŸ€– forbidden)
    test_properties.py  hypothesis tests                             (πŸ€– forbidden)
.githooks/      pre-commit / pre-push gate hooks                     (πŸ€– forbidden)
.github/        CI that re-runs the gate                             (πŸ€– forbidden)
pyproject.toml  project + tooling config                             (πŸ€– forbidden)
AGENTS.md       rules for agents working in the repo                 (πŸ€– forbidden)
docs/PROMPT.md  the standing per-iteration instruction               (human maintained)
docs/           PLAN, PROJECT_STATUS, PROMPT                          (human maintained plan.md)
scratchpad/     scratch dir agents can use for temp files            (For the πŸ€– to play)
docs/specs/     WHAT to build, one PRIORITY-bannered file per track
src/            your product/source code (add to coverage source)

If an agent edits a forbidden file, the file will be unstaged (not allowed to commit). A forbidden pattern by an agent (e.g. # noqa will also prevent their commit and force them to fix it.)

⚠️ Warnings. Read this before a first run.

  1. This harness does not sandbox agents. It tries to harness bad code in loops via gates. Sandboxing agents will, e.g. prevent them from maintaining git, running Playwright, being seen as trustworthy by semgrep leading to cyclical failures, etc.

  2. The gate is a guardrail, not a jail. Agents are crafty, like people. They will find a way to complete a task at all costs. Trust nothing and no one.

  3. Mind your usage limits. harness run works agents to the cap set. You can easily burn through your tokens, context windows, and provider usage limits. Workers continue running as long as there is work to do.

  4. docs/PROMPT.md tells the worker to push every iteration. Protect main and run the loop on its own branch.

  5. 100% coverage does not mean good tests. That is quantity, not quality. (Upcoming feature: mutation testing)

  6. Note: semgrep --config auto needs network for semgrep registry rules.

Commands

Tool commands are defined once, in [tool.harness.gate.checks] in pyproject.toml; the local gate and CI both run them from there.

harness install <your-project-name>  # rewrite [project] name, uv sync, set core.hooksPath to .githooks
harness preflight  # fast checks: preferences, ruff lint + format (plus loop containment)
harness gate  # full pass: preferences, ruff, format, pyright, pylint, complexipy, semgrep, pytest @ 100% cov, hypothesis
RALPH_LOOP=1 harness gate  # to run as if you are the agent in the loop
harness run <agent> [max_iterations] [max_minutes] [verbose] # claude/codex/agy/copilot, defaults: 2 20 True

# UNDERLYING TOOLS are run the way CI runs them
ruff check . && ruff format --check .  # lint. --check verifies formatting only, no auto-fix
pyright  # static type checker: flags type errors without running code
pylint harness src  # deeper lint: dead code, bad patterns, style beyond ruff
semgrep scan --error --config auto --config p/secrets --exclude-rule yaml.github-actions.security.github-actions-mutable-action-tag.github-actions-mutable-action-tag .  # SAST. exclude-rule allows the template's floating action tags
pytest --cov --cov-report=term-missing --cov-fail-under=100  # Note: Pydantic is included. Use it.

# AGENT CALLS
harness run claude 10 20

harness run codex 2 20

harness run agy 3 10

harness run copilot 2 20

Expanding your harness

function_argument_assignment_has_star  # agents use non-specific `def fun(*)`
function_argument_assignment_underscore_lead  # agents love over-using underscore names `def _fun()`
hidden_signature_star_args  # Complain when a function uses *args or **kwargs (it hides function signatures)
dynamic_star_call  # Calls to def fun(*items) breaks when you can't tell how many arguments f is getting
pointless_class  # ensure classes are added for good reasons (carry state, values, methods)
lazy_assert  # enforce real assertions, stronger tests
objects_injected_into_runtime_memory  # finds calls that manipulate global state (dangerous, tricky)
lambda_found  # abolish lambdas for agents to keep their code simpler
lazy_any_type_hints  # abolish type `Any` used to bypass strict type-checking
chaotic_continue_statements  # abolish unecessary nested continue statements, clean code
complex_comprehension  # no needlessly dense list/set/dict comprehensions, prefer linear code

Coordination

  • Use git log --oneline <branch>..HEAD to show what's unpushed.
  • There is NO worktree/branch creation by design. You can create branches/trees and run a loop in each, then merge (if you really feel like managing that)
  • Agent duties can be contained to a part of the repo. e.g. Codex-1-frontend uses docs/specs/frontend.md, Claude-2-researcher docs/specs/backend...

If you must be a ringleader

Recommendations for running several agents at once on one branch (no worktrees):

  • You (human): seed each spec once with this exact line near the top:

    Spec claimed by agent: <unclaimed>
    
  • The agents: paste this exact block into PROMPT.md line 3:

    Other agents are working this repo. Before touching code, pick a spec whose claim line is
    <unclaimed>, replace it with your name, and commit that claim first. Own that spec's file and its
    tests. Set the line back to <unclaimed> on your last commit.
    
  • What fails when agents do not claim specs/work: agents all pick the top-priority spec, duplicate work, and leave a half-staged git index.

  • What fails with too little time i.e. MAX_MINUTES too low: a worker dies mid-gate before it can commit. Give each iteration enough minutes to finish (the gate itself takes a while). One successful iteration needs ~2-3 min of pure overhead aside from 'real' work.

    • A worker killed too soon leaves its spec claim STUCK: spec stays locked to its name. No other agent will take it until a human resets the line to <unclaimed>.
    • preflight on git commit: ~ a few seconds
    • full gate on git push: ~20-48s
    • push + cleanup: ~ few seconds -
  • Do not rely on agent names for coordination: agents self-name inconsistently and can collide (e.g. two both call themselves the same thing). Names are for human blame/log-matching only; the claim line + committed code are what actually coordinate.

  • Which doc does what:

    • specs = the product work
    • docs/PROMPT.md = how to operate headlessly
    • repo + green gate = the source of truth
    • docs/PROJECT_STATUS.md is a human-readable record, not authoritative
  • No branch/worktree creation in this harness was intentional:

    1. For simplicity and maintainability of the framework.
    2. Because a fresh iteration can't see the unmerged work in another worktree, so agents miss context and scramble to merge while conflicts pile up.
    3. Change this behavior if you're comfortable with granting agents machine access, feeding context to agents, and managing rapidly moving git history.

diagram