Self-improving agent loops for any GitHub repo. An outer loop triages, prioritizes,
dispatches, reviews, and learns; nanobot workers claim cards and ship PRs. GitHub is the
only state store — issues are the intake, a Projects v2 board is the kanban, PRs are the
audit trail, and a pinned issue is the heartbeat. When the bots are out of their depth,
they summon-human.
Inspired by Autoresearch/Introspection: the durable product isn't the code, it's the loop that maintains it — with humans as a deliberate signal source, not a bottleneck.
┌────────────────────────────────────────────────┐
signals ───▶ │ OUTER LOOP (control + learning) │
issues, │ ingest → triage → prioritize → dispatch │
errors, │ → review outcomes → LEARN (update its policy) │
humans └───────────────┬────────────────▲───────────────┘
│ dispatch │ outcomes (PRs, CI)
▼ │
┌────────────────────────────────┴───────────────┐
│ NANOBOT WORKERS (inner loop) │
│ claim card → branch → build → tests → │
│ PR (Closes #N) → gates → merged by outer loop │
└────────────────────────────────────────────────┘
cd your-repo
npx nanobots-sh init # or: curl -fsSL nanobots.sh/install | shinit asks ~6 questions (test commands, hard-gate areas, WIP cap — with answers
auto-detected from your repo where possible; no model/API key needed to install),
then:
- renders the loop into
.nanobots/(prompts, triage rubric, recipes, learnings log, runner script,config.json), - writes GitHub workflows + issue intake forms,
- scaffolds GitHub state via
gh: the project board, Priority/Size fields, labels, and a pinned status issue, - prints the two manual steps GitHub's API can't do, plus the secrets checklist.
After init the repo is fully self-contained — markdown prompts, one shell script,
plain workflows. No runtime dependency on this package. Your repo's rubric and recipes
are supposed to drift from the templates: that's the learning.
Optional: init --smart additionally uses the claude CLI (if installed) to study your
repo and draft repo-specific recipes and gates into .nanobots/SUGGESTIONS.md.
The loop is stateless: "running" = something executes one cycle on a cadence. Run either
role anywhere — see .nanobots/RUNTIMES.md after install.
| Where | How |
|---|---|
| Laptop (interactive) | /loop in Claude Code with .nanobots/LOOP-PROMPT.md (outer) or WORKER-PROMPT.md |
| VM / your own box | npx nanobots run outer (or bash .nanobots/run-cycle.sh outer) on a systemd/launchd timer |
| GitHub Actions | the installed nanobots-outer.yml cron (set NANOBOTS_OUTER_ENABLED=1) |
| Sandbox cloud (Daytona/E2B/…) | same script + two env vars; a ~20-line launcher when you need per-item isolation |
Billing is an env var, not a feature. CLAUDE_CODE_OAUTH_TOKEN runs everything on a
Claude Pro/Max subscription (mint once: claude setup-token). ANTHROPIC_API_KEY is
metered. Any Anthropic-compatible provider works — e.g. DeepSeek via
ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic. Mix per runtime: cheap model
workers on a VM, frontier model for the outer loop's judgment.
Workers are swappable at the PR seam. A worker is anything that reads an issue's
work-spec and opens a PR with Closes #N — Claude Code (ours), GitHub Copilot's coding
agent (assign the issue), Codex, OpenHands. The board can't tell the difference.
Every finished (or failed) work item gets an entry in .nanobots/LEARNINGS.md — an
append-only memory. Every ~10 entries the outer loop runs a distill pass, promoting
durable lessons into the triage rubric, the recipes, and your agent instructions file.
The loop's policy documents are its weights; GitHub history is the training log.
ghCLI authenticated, with theprojectscope (gh auth refresh -s project)- The Claude GitHub App on the repo (
claude /install-github-app) — only needed for the Actions execution paths - Two secrets for Actions mode:
CLAUDE_CODE_OAUTH_TOKEN, andPROJECTS_PAT— a classic PAT (project+repo) from a human account. Two hard-won facts baked into the design: the defaultGITHUB_TOKENcannot touch org Projects v2 at all, and claude-code-action refuses runs initiated by bot actors, so dispatch comments must post as a human.
npx nanobots-sh init [--smart] [--no-github] [--yes] # scaffold a repo
npx nanobots-sh update # re-render engine-owned files only
npx nanobots-sh run <outer|worker> # one headless cycleupdate never touches repo-owned files (TRIAGE.md, RECIPES.md, LEARNINGS.md,
config.json) — those belong to your repo's loop. Engine-owned files carry a
nanobots:engine-owned marker in their first lines.
extension/ is a zero-dependency MV3 Chrome extension that feeds the loop
from any webpage: click → screenshot → annotate (pen/box/arrow) → filed as a
nanobots:inbox issue the board auto-adds for triage. Screenshots live in your
Cloudflare R2 bucket (free tier; the issue embeds the link, git stays binary-free) —
capture is disabled until R2 is connected, and the options page walks through the
3-minute free setup. It keeps a local history of
everything you've filed (with live state), and has a repo chat — a BYO-model agent
with real repo tools (code/issue search, file read, report filing with your pasted
screenshots). The chat agent's prompt lives in the repo (.nanobots/EXTENSION-PROMPT.md)
and is refined by the outer loop based on how extension-filed reports fare in triage —
the intake itself self-improves. Install: chrome://extensions → Developer mode → Load
unpacked → extension/. See extension/README.md.
- docs/architecture.md — the two loops, the GitHub surface mapping, the cycle spec, design decisions
- docs/research/ — the July 2026 tooling landscape + the GitHub Projects v2 automation reference this design is built on
MIT