Plug and play autonomous issue-to-PR agent fleet. Drop bullet.yaml in any repo; issues done automatically. Max 10 agents, label state machine.
  • Shell 97.3%
  • Python 2.7%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
EduarD3V deab116cd5 live-run fixes: spawn prompt-file dir + dead-coder-session recovery
Found during the 5-issue live fleet run on masante-test-repo (#36-40):

1. agent_spawn: the .cmd file lives under $RUN_DIR/meta/<session>.cmd where the
   session name contains a slash (bullet-owner/repo-c-36) — cp failed silently and
   the agent got an empty prompt. mkdir -p the dirname first.
2. preflight: a coder whose tmux session DIES (crash/kill) while the issue stays
   bullet:running was invisible forever — the stall loop only sees LIVE sessions.
   New sweep: running issue + no coder session = relaunch from committed state,
   announce it. Live-verified: #36 relaunched, finished, reviewed (verdict bound to
   the commit, head moved -> automatic re-review fired), integrated.

Run result: 5/5 issues done, 5 merges into bullet-develop (incl. one real conflict
solved by the conflict-solver agent), gates green, rolling PR #41 mergeable=true.
2026-10-13 19:30:39 +02:00
.bullet single SKILL.md: installer found 3; only skills/bullet/SKILL.md may remain 2026-10-12 16:47:49 +02:00
docs review round 2: enforced (not requested) lifecycle invariants + transition test suite 2026-10-13 09:38:22 +02:00
examples .bullet/ per-repo layout + spec: USE-CASES, FEATURES, per-repo SKILL.md, bullet init 2026-10-12 16:04:27 +02:00
hermes single SKILL.md: installer found 3; only skills/bullet/SKILL.md may remain 2026-10-12 16:47:49 +02:00
skills/bullet live-run fixes: spawn prompt-file dir + dead-coder-session recovery 2026-10-13 19:30:39 +02:00
tests review round 2: enforced (not requested) lifecycle invariants + transition test suite 2026-10-13 09:38:22 +02:00
.gitignore .bullet/ per-repo layout + spec: USE-CASES, FEATURES, per-repo SKILL.md, bullet init 2026-10-12 16:04:27 +02:00
LICENSE bullet: plug and play autonomous issue-to-PR fleet 2026-10-12 15:39:12 +02:00
README.md review round 2: enforced (not requested) lifecycle invariants + transition test suite 2026-10-13 09:38:22 +02:00

🔫 bullet

Plug and play autonomous issue→PR fleet. One command to wire a repo, one label to queue an issue, and your issues are automatically done — implemented, reviewed by a second model, gate-checked, and opened as a PR. Max 10 agents. Humans merge.

No server, no database, no framework. Bash + curl + jq + tmux + git worktrees. The forge (Forgejo or GitHub) is the only state store: labels are the state machine.

The loop

queued ──launch──▶ running ──DONE comment──▶ review ──REVIEW: CLEAN/FIXED──▶ done ──gates+push──▶ PR
   ▲                  │                          │                                          │
   └── human removes blocked / edits issue ◀─────┘◀── REVIEW: NEEDS-DECISION ────────────────┘ (human merges)
  • One action per tick. bullet tick (cron every 15–30 min, or your AI agent) does preflight → one transition → report line. Crash-safe: every step idempotent, all state in forge labels + git worktrees + tmux sessions.
  • Who pushes, who merges — the exact boundary:
    • Agents (coder/fixer) push only their own issue branch (issue/N-…). Nothing else.
    • The orchestrator auto-merges per-issue PRs into bullet-develop — after the full gate suite ran green on the merged tree. This is the one machine merge.
    • Humans merge the ONE rolling PR (bullet-develop → trunk). No agent or orchestrator ever pushes trunk or merges that PR.
    • Refs #N everywhere; closing keywords are banned; issues close by human hand.
  • Reviewer is a different model from the coder, fresh session each round, judges the diff against the issue — not the coder's report. Every verdict binds to the commit it examined.

Install & use (30 seconds)

npx skills add EduarD3V/bullet
# any git host (private Forgejo included):
npx skills add https://git.eduard3v.com/EduarD3V/bullet.git

Then, inside your repo, tell your agent:

/bullet solve my issues

The agent resolves the skill (skills/bullet/SKILL.md — the operating manual), runs bullet doctor, and drains the queue tick by tick. First run in a fresh repo: it offers bullet init — creates .bullet/ (config + per-repo skill), gitignores runtime dirs, and tells you before creating the five state labels on the forge.

Quickstart (manual, 5 minutes)

# 1. Get bullet (or use npx skills add above — same files)
git clone https://git.eduard3v.com/EduarD3V/bullet.git
export PATH=/path/to/bullet/skills/bullet:$PATH

# 2. Plug into your repo — creates .bullet/ (config + skill), labels, doctor, cron line
export BULLET_TOKEN=<forge token with issues+PR write>
bullet init /path/to/your-repo

# 3. Edit /path/to/your-repo/.bullet/bullet.yaml (gates, models, branches)
bullet doctor /path/to/your-repo

# 4. Wire the cron (printed by init), or let your AI agent run `bullet tick`
*/30 * * * * BULLET_TOKEN=… bullet tick /path/to/your-repo >> /path/to/your-repo/.bullet/logs/tick.log 2>&1

# 5. Label an issue `bullet:queued`. That's it — next tick claims it.

Status anytime: bullet status /path/to/your-repo.

What's inside

Path What
bullet entrypoint: init · tick · status · doctor · labels
skills/bullet/ the whole fleet — this dir is what npx skills add installs (self-contained)
skills/bullet/SKILL.md the skill: /bullet solve my issues — agent operating manual
skills/bullet/law/ composable agent law: hard-law, comment-policy, plan-first, gates, budget, refs-not-closes, reviewer-law
<repo>/.bullet/ per-repo home: bullet.yaml (config) · AGENT.md (per-repo agent guide) · state/ meta/ worktrees/ logs/ (runtime, gitignored)
skills/bullet/orchestrator/ one script per phase: init · preflight · launch · monitor · review · publish · status · doctor · labels
skills/bullet/lib/ forge.sh (Forgejo+GitHub API), state.sh (the only label writer), agent.sh, tmux.sh, config.sh, compose.py (prompt assembler)
skills/bullet/prompts/ role prompts: coder, reviewer, fixer — each composed from role + law files
docs/ USE-CASES.md · FEATURES.md · STATE-MACHINE.md · PLUG-AND-PLAY.md
hermes/bullet-fleet.md install as a Hermes skill to let an AI drive bullet

The 10-agent fleet

agents: in .bullet/bullet.yaml (hard cap 10, enforced per tick). Slots auto-split ~70% coder / 20% reviewer / 10% fixer. Each agent = one tmux session (bullet-<repo>-<role>-<issue>) in one git worktree (.bullet/worktrees/issue-<N>). The cap is global across repos. See agents/README.md.

Per-repo skill

bullet init writes .bullet/AGENT.md into the target repo: this repo's commands, paths, label law (including the labels-missing → announce-then-create rule), and operating loop. Any AI agent that reads the repo can then drive the fleet — cron optional.

Design rules (the scars that shaped them)

  1. The forge is the database. No state files to corrupt; reconcile = re-read labels.
  2. One action per tick. Long-running work lives in tmux agents, not in the scheduler.
  3. Labels written by exactly one thing — state.sh. Agents comment, they never relabel.
  4. Never silent mutation. Missing labels are announced, then created. BULLET_DRY_RUN=1 rehearses.
  5. Plan-first, comment at four moments, gates before push, Refs #N never fixes #N.
  6. Humans merge. (Set merge: auto if you really want the fleet to close the loop itself.)

Provenance

Battle-tested law distilled from the gotoi/masante agent loops (40+ unattended runs) and the best open patterns: issue-orchestrator (labels-as-state-machine, gates, human merge), claude-squad (tmux + worktree per agent), vigilante/ariadne (headless CLI agents, isolation).

License

MIT