Whilly Wiggum loop — Ralph's smarter brother technique for continuous AI agent loops: TRIZ analyzer, Decision Gate, PRD wizard, Rich TUI dashboard, tmux/git-worktree parallelism, self-healing system
Project description
Whilly Orchestrator
Python implementation of the Whilly Wiggum loop — Ralph Wiggum's smarter brother. Same family, same "I'm helping!" spirit, but with TRIZ contradiction analysis, a Decision Gate that refuses nonsense upfront, a PRD wizard, and a Rich TUI dashboard on top of the classic continuous agent loop.
🇷🇺 Краткое описание на русском · 🎓 Workshop kit (HackSprint1)
"I'm helping — and I've read TRIZ." — Whilly Wiggum
What it does
Whilly runs a loop: pick a pending task → hand it to an LLM agent → verify result → commit → next. It keeps running until the task board is empty, a budget is exhausted, or you stop it. Parallel mode dispatches multiple agents in tmux panes or git worktrees.
The base technique was first described in Ghuntley's post on the Ralph Wiggum loop and widely adopted across the Claude Code community. Whilly is the brainier sibling: all of Ralph's "pick task → try → repeat" stamina, plus a TRIZ analyzer for surfacing contradictions, a Decision Gate for refusing garbage tasks, and a PRD wizard for understanding the problem before swinging at it.
Features
- Continuous agent loop — pull tasks from a JSON plan, run Claude CLI on each, retry on transient errors
- Rich TUI dashboard — live progress, token usage, cost totals, per-task status; hotkeys for pause/reset/skip
- Parallel execution — tmux panes or git worktrees, up to N concurrent agents with budget/deadlock guards
- Self-healing system 🛡️ — auto-detect crashes, fix common code errors (NameError, ImportError), restart pipeline
- Task decomposer — LLM-based breakdown of oversized tasks into subtasks
- PRD wizard — interactive Product Requirements Document generation, then auto-derive tasks from the PRD
- TRIZ analyzer — surface contradictions and inventive principles for ambiguous tasks
- State store — persistent task state across restarts, per-task per-iteration logs
- Notifications — budget warnings, deadlock detection, auth/API error alerts
Install
pip install whilly-orchestrator
Or from source:
git clone https://github.com/mshegolev/whilly-orchestrator
cd whilly-orchestrator
pip install -e .
Requires Claude CLI on PATH (or set CLAUDE_BIN).
Quick start
-
Create
tasks.jsondescribing the work:{ "project": "health-endpoint", "tasks": [ { "id": "TASK-001", "phase": "Phase 1", "category": "functional", "priority": "high", "description": "Add a /health endpoint returning {\"status\":\"ok\"}", "status": "pending", "dependencies": [], "key_files": ["app/server.py"], "acceptance_criteria": ["GET /health returns 200 with {\"status\":\"ok\"}"], "test_steps": ["curl -s localhost:8000/health"] }, { "id": "TASK-002", "phase": "Phase 1", "category": "test", "priority": "high", "description": "Write a pytest covering the new endpoint", "status": "pending", "dependencies": ["TASK-001"], "key_files": ["tests/test_health.py"], "acceptance_criteria": ["pytest tests/test_health.py passes"], "test_steps": ["pytest -q tests/test_health.py"] } ] }
-
Run Whilly (2 concurrent agents, $5 budget cap):
WHILLY_MAX_PARALLEL=2 WHILLY_BUDGET_USD=5 whilly tasks.json # straight from a checkout, no install: ./whilly.py tasks.json # or as a module: python -m whilly tasks.json # or just `whilly` with no args for the interactive plan-picker
-
Watch the dashboard. Press
qto quit,dfor task detail,lfor the live log of a running agent,tfor the task overview.
🛡️ Self-Healing System
Whilly includes a built-in self-healing system that automatically detects, analyzes, and fixes code errors to ensure pipeline resilience:
# Standard whilly (no crash protection)
whilly tasks.json
# Self-healing whilly (auto-fix + restart on crashes)
python scripts/whilly_with_healing.py tasks.json
Supported error types:
- ✅
NameError— missing variables/parameters (auto-fix) - ✅
ImportError— missing modules (auto pip install) - ✅
TypeError— function parameter mismatches (diagnosis) - ⚠️
AttributeError— missing object attributes (suggestions)
Features:
- 🔍 Smart error detection via traceback pattern analysis
- 🔧 Automated fixes for common coding errors
- 🔄 Auto-restart with exponential backoff (max 3 retries)
- 📊 Learning from patterns in historical error logs
- 💡 Recovery suggestions for complex issues
See Self-Healing Guide for complete documentation.
Modules
| Module | Purpose |
|---|---|
orchestrator.py |
Main loop, batch planning, interface agreement between agents |
agent_runner.py |
Claude CLI wrapper, JSON output parsing, usage accounting |
tmux_runner.py |
Parallel agents in tmux panes |
worktree_runner.py |
Parallel agents in isolated git worktrees |
dashboard.py |
Rich TUI dashboard with hotkeys |
task_manager.py |
Task lifecycle (pending → in_progress → done/failed) |
state_store.py |
Persistent state across restarts |
decomposer.py |
LLM-based task breakdown |
prd_generator.py, prd_wizard.py, prd_launcher.py |
PRD generation and task derivation |
triz_analyzer.py |
TRIZ contradiction analysis |
self_healing.py |
🛡️ Error detection, analysis, and automated fixing |
recovery.py |
Task status synchronization and consistency validation |
reporter.py |
Per-iteration reports, cost totals, summary markdown |
verifier.py, notifications.py, history.py, config.py |
Infrastructure |
Configuration
Whilly resolves config through layers (last wins):
defaults → user TOML → ./whilly.toml → .env → shell env (WHILLY_*) → CLI flags
Start from the committed template (works cross-platform — macOS / Linux / Windows):
cp whilly.example.toml whilly.toml # project-local
# or place settings at the OS-native user path:
whilly --config path # shows the location
whilly --config edit # opens it in $EDITOR
# legacy .env users: one-shot migration that moves tokens into the OS keyring
whilly --config migrate
See docs/Whilly-Usage.md for the full config guide (TOML fields, secret schemes, user-config paths per OS). The env-var table below is kept as a reference — every WHILLY_* variable has an equivalent TOML field of the same name.
| Variable | Default | Purpose |
|---|---|---|
WHILLY_MODEL |
claude-opus-4-6[1m] |
Claude model id |
WHILLY_MAX_PARALLEL |
3 |
Concurrent agents (1 = sequential) |
WHILLY_MAX_ITERATIONS |
0 |
Max work cycles per plan (0 = unlimited) |
WHILLY_BUDGET_USD |
0 |
Hard cost cap; 80% triggers warning, 100% stops the run |
WHILLY_TIMEOUT |
0 |
Wall-clock cap in seconds (0 = unlimited) |
WHILLY_USE_TMUX |
1 |
Use tmux panes for parallel agents |
WHILLY_WORKTREE |
0 |
Per-task git worktree isolation (needs MAX_PARALLEL>1) |
WHILLY_LOG_DIR |
whilly_logs |
Per-task log directory |
WHILLY_STATE_FILE |
.whilly_state.json |
Crash-recovery state file (--resume reads it) |
WHILLY_HEADLESS |
auto | CI mode — JSON on stdout, exit codes |
CLAUDE_BIN |
claude |
Path to Claude CLI binary |
WHILLY_AGENT_BACKEND |
claude |
Active agent backend (claude or opencode) |
WHILLY_OPENCODE_BIN |
opencode |
Path to the OpenCode CLI binary |
WHILLY_OPENCODE_SAFE |
0 |
1 → drop --dangerously-skip-permissions for OpenCode |
WHILLY_OPENCODE_SERVER_URL |
(unset) | Optional remote OpenCode server URL |
New here? Start with docs/Getting-Started.md — practical walkthroughs from install to first run.
Key CLI flags: --all, --headless, --timeout N, --resume, --reset PLAN.json, --init "desc" [--plan] [--go], --plan PRD.md, --prd-wizard, --no-worktree, --agent {claude,opencode,claude_handoff}.
Task sources (pull issues into plans)
whilly --from-github whilly:ready --go # all open issues with label
whilly --from-github all --go # every open issue, no label filter
whilly --from-issue owner/repo/42 --go # one GitHub issue (slash form — shell-safe)
whilly --from-issue 'owner/repo#42' --go # same, with '#' (quote in zsh/bash)
whilly --from-jira ABC-123 --go # one Jira ticket
whilly --from-project <project-v2-url> --go # GitHub Projects v2 board
whilly --from-issues-project <url> --repo owner/name # board-filtered issues
Lifecycle sync (live board updates as whilly works)
Enable in whilly.toml:
[project_board] # GitHub Projects v2
url = "https://github.com/users/you/projects/4"
default_repo = "you/your-repo"
[jira] # Jira transitions (complements auto-close)
server_url = "https://company.atlassian.net"
username = "you@example.com"
token = "keyring:whilly/jira"
enable_board_sync = true
Task status → column mapping is identical for both: pending → Todo/To Do, in_progress → In Progress, done → In Review, merged → Done, failed → Failed, skipped → Refused/Cancelled, blocked → On Hold/Blocked, human_loop → Human Loop/Waiting for Customer. Override per-section via [project_board.status_mapping] / [jira.status_mapping].
One-off helpers:
whilly --ensure-board-statuses # create any missing Status columns
whilly --post-merge <plan.json> # after an external merge, flush cards to Done
python3 scripts/populate_board.py … # bulk-add issues onto a Projects v2 board
Human-in-the-loop backend (claude_handoff)
WHILLY_AGENT_BACKEND=claude_handoff whilly --from-issue alice/repo/42 --go
Each task's prompt lands in .whilly/handoff/<task_id>/prompt.md; whilly blocks until you write result.json. Three companion commands:
whilly --handoff-list # see pending handoffs
whilly --handoff-show GH-42 # read the prompt
whilly --handoff-complete GH-42 --status complete --message "done"
Accepted statuses: complete / failed / blocked / human_loop / partial. blocked and human_loop map to extra whilly statuses + board columns so tickets needing a decision land in a dedicated column instead of being misreported as failed.
Exit codes in headless mode: 0 success, 1 some tasks failed, 2 budget exceeded, 3 timeout.
See docs/Whilly-Usage.md for the full CLI reference.
Documentation
- Whilly-Usage.md — CLI reference and flag catalog
- Whilly-Interfaces-and-Tasks.md — task file format, state store schema, agent output contract
- docs/workshop/INDEX.md — Workshop kit (HackSprint1)
Workshop kit
Whilly ships with a HackSprint1 workshop kit — a 90-minute hands-on tutorial that takes you from pip install to a running self-hosting bootstrap demo. Two tracks:
- Track A (
tasks.json) — works without GitHub auth, 30 min. - Track B (GitHub Issues) — full e2e with PR creation, 60 min.
Includes BRD, PRD, 12 ADRs, sample plans, and a roadmap. See docs/workshop/INDEX.md for the full guide. RU/EN bilingual.
Backends
Whilly ships with pluggable agent backends behind a single AgentBackend Protocol (see whilly/agents/).
| Backend | Select | CLI wrapped | Notes |
|---|---|---|---|
| Claude (default) | --agent claude / WHILLY_AGENT_BACKEND=claude |
claude --output-format json -p "…" |
Requires Claude CLI. Set CLAUDE_BIN to override path. |
| OpenCode | --agent opencode / WHILLY_AGENT_BACKEND=opencode |
opencode run --format json --model <provider/id> "…" |
Requires sst/opencode on PATH (or WHILLY_OPENCODE_BIN). Set WHILLY_OPENCODE_SAFE=1 to respect its per-tool permission policy. |
Model ids pass through normalization per backend — e.g. claude-opus-4-6 automatically becomes anthropic/claude-opus-4-6 for OpenCode. Completion is signalled identically (<promise>COMPLETE</promise>) so the main loop is backend-agnostic. Decision Gate, tmux runner, and the subprocess fallback all route through the active backend.
Workflow boards
Whilly can sync a GitHub Projects v2 board as issues move through the pipeline (ready → picked_up → in_review → done / refused / failed). Board integration is Protocol-driven (whilly/workflow/BoardSink) — today one adapter ships (GitHubProjectBoard via gh api graphql); Jira/Linear/GitLab drop in as sibling implementations.
Before first use, run the analyzer to map whilly's six lifecycle events to your board columns:
whilly --workflow-analyze https://github.com/users/<you>/projects/<N>
The analyzer prints matched / missing / ambiguous columns and walks you through [A]dd / [M]ap / [S]kip decisions. Output goes to .whilly/workflow.json — a committable artefact so teams share one contract. Extra flags: --apply (auto-add all missing columns, CI-friendly) and --report (dry-run, no writes).
See ADR-014 for the design rationale and extension guide.
Self-hosting pipelines
Two e2e scripts ship for "whilly processes its own GitHub issues end-to-end", differing in how much thinking they do before coding. Pick by issue complexity:
| Script | Stages | Use when |
|---|---|---|
scripts/whilly_e2e_demo.py |
fetch → Decision Gate → execute → PR → review-fix loop | Issue is crisp, single-file, "just do it" scoped. Ralph-loop reference. |
scripts/whilly_e2e_triz_prd.py |
fetch → Gate → TRIZ challenge → PRD → tasks decomp → execute → quality gate → PR | Issue deserves decomposition. "Whilly Wiggum" smarter-brother variant. |
Both honour the workflow board integration (WHILLY_PROJECT_URL=... → cards move at every stage) and share the hard WHILLY_BUDGET_USD cap.
Typical invocation for the TRIZ+PRD pipeline:
unset GITHUB_TOKEN
WHILLY_REPO=mshegolev/whilly-orchestrator \
WHILLY_LABEL=whilly:ready \
WHILLY_BUDGET_USD=30 \
WHILLY_PROJECT_URL=https://github.com/users/mshegolev/projects/4 \
python scripts/whilly_e2e_triz_prd.py --limit 1
--limit N caps issues per run; --dry-run skips all LLM / PR / merge work for plan-only inspection; --allow-auto-merge is OFF by default — a pipeline that modifies whilly's own code always leaves PRs for human review. Details + design rationale in ADR-015.
Troubleshooting / FAQ
| Issue | Fix |
|---|---|
gh auth status returns 401 ("token invalid") |
unset GITHUB_TOKEN (env-based token overrides keyring auth), then gh auth login if needed. |
claude: command not found |
Install Claude CLI from docs.claude.com or set CLAUDE_BIN to its path. |
| Dashboard rendering broken on narrow terminal (<100 cols) | WHILLY_HEADLESS=1 whilly tasks.json — disables TUI, streams JSON events on stdout. |
| Budget hits 0 unexpectedly | Set or raise WHILLY_BUDGET_USD (default unlimited; 0 also means unlimited). |
tmux ls shows no sessions after dispatch |
Either tmux isn't installed, or WHILLY_USE_TMUX=0 — whilly silently falls back to subprocess mode. |
| Agent loops forever without marking done | Ensure prompt ends with the <promise>COMPLETE</promise> marker contract — agent_runner.is_complete checks that string. |
Workshop kit
Running HackSprint1 or a self-paced walkthrough? The full workshop kit (BRD, PRD, ADRs, tutorial, roadmap) lives under docs/workshop/INDEX.md.
Development
pip install -e ".[dev]"
pytest
ruff check whilly/ tests/
ruff format whilly/ tests/
Credits
- Technique lineage: Ghuntley's original Ralph Wiggum loop post — the pattern whilly descends from.
- Spirit of the family — Ralph's "I'm helping!" captures the essence of an agent that just keeps going, no matter what. Whilly is his smarter brother: same stamina, plus TRIZ, Decision Gate, PRD wizard.
Related work
- Earlier Ralph-loop implementations exist across the Claude Code community. Whilly sets itself apart with a Rich TUI dashboard, TRIZ analyzer, Decision Gate pre-flight, PRD wizard, and tmux/git-worktree parallel execution — the "smarter brother" kit on top of the base loop.
License
MIT — see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file whilly_orchestrator-3.2.0.tar.gz.
File metadata
- Download URL: whilly_orchestrator-3.2.0.tar.gz
- Upload date:
- Size: 284.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f9e330f9a6dd75fc580146a3d657fafcab9034761cca82770c2f7895ba53aaea
|
|
| MD5 |
0fa12b21731e1a6c556911947e333771
|
|
| BLAKE2b-256 |
de92f15b2e265b5cdd17b44d6f26a281f3e438b3157a13088387d4ca81610551
|
Provenance
The following attestation bundles were made for whilly_orchestrator-3.2.0.tar.gz:
Publisher:
release.yml on mshegolev/whilly-orchestrator
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
whilly_orchestrator-3.2.0.tar.gz -
Subject digest:
f9e330f9a6dd75fc580146a3d657fafcab9034761cca82770c2f7895ba53aaea - Sigstore transparency entry: 1353931101
- Sigstore integration time:
-
Permalink:
mshegolev/whilly-orchestrator@98ad0827d27fc3221a5828eb617a77184d54f543 -
Branch / Tag:
refs/tags/v3.2.0 - Owner: https://github.com/mshegolev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@98ad0827d27fc3221a5828eb617a77184d54f543 -
Trigger Event:
push
-
Statement type:
File details
Details for the file whilly_orchestrator-3.2.0-py3-none-any.whl.
File metadata
- Download URL: whilly_orchestrator-3.2.0-py3-none-any.whl
- Upload date:
- Size: 253.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
febacc49bdfb59dc672a85e04f01a8b290310b15e1f5ba65a49db83366dff380
|
|
| MD5 |
7b4205c63b16829b4c002a67b5d33bc6
|
|
| BLAKE2b-256 |
29245632048fee470494a48b9a9b4cf01e45f29886aa3f9db02cd3db4c88849b
|
Provenance
The following attestation bundles were made for whilly_orchestrator-3.2.0-py3-none-any.whl:
Publisher:
release.yml on mshegolev/whilly-orchestrator
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
whilly_orchestrator-3.2.0-py3-none-any.whl -
Subject digest:
febacc49bdfb59dc672a85e04f01a8b290310b15e1f5ba65a49db83366dff380 - Sigstore transparency entry: 1353931223
- Sigstore integration time:
-
Permalink:
mshegolev/whilly-orchestrator@98ad0827d27fc3221a5828eb617a77184d54f543 -
Branch / Tag:
refs/tags/v3.2.0 - Owner: https://github.com/mshegolev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@98ad0827d27fc3221a5828eb617a77184d54f543 -
Trigger Event:
push
-
Statement type: