Your code evolves while you sleep. 🦉 Spec-driven autonomous coding loop.
Project description
Your code evolves while you sleep.
Write specs. Start the loop. Wake up to clean commits.
🦉 Ollie is a nocturnal owl.
While you sleep, he reads your specs, spawns a fresh agent iteration for each task, verifies the result with real shell commands, and only commits when they pass.
Quick Start · How It Works · Writing Specs · Compared To · FAQ
You have 20 lint categories to fix, 200 functions missing type annotations, and error handling copy-pasted everywhere. You know what to do — you just don't have the hours. owloop does it while you sleep.
owloop run → pick spec → fresh agent context → verify with shell commands → commit → next spec → 🌅
🌙 Quick Start
# Install from PyPI
uv tool install owloop
# or: pip install owloop
owloop init # creates specs/ and templates
# edit specs/01-example.md with your task
owloop run # start the loop
All commands
| Command | Description |
|---|---|
owloop init |
Initialize project (creates specs/, .gitignore entries) |
owloop spec "goal" |
Turn a vague goal into a concrete spec via agent clarification |
owloop check |
Validate all specs before running the loop (pre-flight linter) |
owloop run |
Start the autonomous loop with TUI |
owloop run -n 20 |
Limit to 20 iterations |
owloop run --max-duration 120 |
Stop after 2 hours |
owloop run --max-tokens 200000 |
Stop after token budget reached |
owloop run --idle-timeout 1800 |
Kill hung agent after 30min silence |
owloop plan |
Generate implementation plan from specs |
owloop status |
Show specs and completion progress |
owloop report |
Generate HTML summary report for the latest run |
owloop spec-from-issue 42 |
Generate a spec draft from a GitHub issue |
owloop version |
Show installed version |
Global options
| Option | Description |
|---|---|
--ascii |
Use ASCII art instead of Unicode glyphs (better on older Windows terminals) |
--no-color |
Disable colored terminal output |
--compact |
Force the compact single-column TUI layout |
🦉 How It Works
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#d4a025', 'primaryTextColor': '#0b1026', 'primaryBorderColor': '#3a4270', 'lineColor': '#3a4270', 'secondaryColor': '#121a2e', 'tertiaryColor': '#121a2e', 'fontFamily': 'Inter, system-ui, sans-serif' }}}%%
graph LR
A["🦉 Pick spec"]:::owl --> B["fresh agent context"]:::neutral
B --> C{"DONE?"}:::neutral
C -- yes --> D["✅ Commit"]:::neutral --> E{"More specs?"}:::neutral
C -- no --> R["🔄 Retry ≤3"]:::retry --> A
E -- yes --> A
E -- no --> F["🌅 Complete"]:::done
classDef owl fill:#d4a025,stroke:#d4a025,color:#0b1026
classDef done fill:#8fd19e33,stroke:#8fd19e,color:#f2ecd8
classDef retry fill:#e0777d33,stroke:#e0777d,color:#f2ecd8
classDef neutral fill:#121a2e,stroke:#3a4270,color:#f2ecd8
| Property | How |
|---|---|
| Natural-language specs | owloop spec "goal" reads the codebase, asks clarifying questions, drafts a concrete spec. |
| Pre-flight linting | owloop check validates specs before the loop starts — no wasted tokens on bad specs. |
| Fresh context | Each iteration starts a brand-new agent process. No context rot. |
| Cross-iteration notes | run-notes.md carries learnings between iterations — fresh context without repeating mistakes. |
| Deterministic completion | grep for <promise>DONE</promise> — no AI judgment, no surprises. |
| Worktree isolation | Runs in a separate git worktree. Your main checkout stays untouched. |
| Auto Mode | --permission-mode auto: Ollie asks before risky moves, never YOLO. |
| Fix-loop detection | Same files modified 3+ rounds → Ollie warns of a death spiral. |
| Token budget cap | --max-tokens stops the run before costs spiral. |
| Sleep prevention | Keeps your machine awake during overnight runs (macOS / Linux / Windows). |
📝 Writing Specs
Specs are constraint-oriented: define what's off-limits, then make every acceptance criterion a shell command.
# Spec: Extract ValidationError Handling
## Priority: 1
## Requirements
- Extract ~69 repeated `except ValidationError` blocks into
a single Flask `@app.errorhandler(ValidationError)`
## Acceptance Criteria
- [ ] grep -c "except ValidationError" backend/app/api/*.py → ≤ 5
- [ ] uv run ruff check backend/ → 0 errors
- [ ] grep -c "errorhandler" backend/app/__init__.py → ≥ 1
## Exclusions
- Do NOT change API response formats
- Do NOT touch models/, schemas/, services/
## Verification
After each change: uv run ruff check backend/
Output when complete: `<promise>DONE</promise>`
Why this works:
Exclusionsprevent drift. Shell commands verify "done" — no AI judgment needed. One spec = one concern.
Rule of thumb
If you can write a shell command that verifies "done", it's a good owloop task. If "done" requires a human to look and decide, it's not.
Best fit: lint fixes, type annotations, dead code removal, DRY extraction, import cleanup
Poor fit: feature design, architecture decisions, UI/UX, security-sensitive changes
🔄 Compared To
| owloop | /goal |
gnhf | |
|---|---|---|---|
| Completion | grep (deterministic) | Haiku model (probabilistic) | grep |
| Context | Fresh per iteration | Same session | Fresh per iteration |
| Specs | Constraint-oriented | Free-form | Free-form |
| Best for | Backlog of verifiable tasks | One focused task | Multi-agent overnight |
❓ FAQ
When should I use owloop instead of /goal?
/goal is great for one task in one sitting. owloop is for backlogs — a queue of specs, each run in a fresh context, unattended overnight. If you're clearing twenty lint categories or migrating a whole module, loop engineering scales further than one long session.
Is this safe to run on production code?
owloop runs in a separate git worktree with --permission-mode auto. Your main branch stays clean. That said, treat every overnight run as a PR to review in the morning, not a deploy.
Can I use owloop with Codex or OpenCode?
Not directly — owloop is built around claude -p. For multi-agent support, gnhf is the better fit.
🛠️ Development
owloop uses uv for dependency management and ships with ruff, mypy, and pytest-cov as dev tools.
uv sync --group dev # install dev dependencies
uv run pytest -q # run tests with coverage
uv run ruff check src/owloop tests
uv run mypy src/owloop tests
All changes are validated on Linux, macOS, and Windows via GitHub Actions.
🦉 Brand
owloop's identity — Ollie the owl, the night/amber palette, and the "your code evolves while you sleep" story — is documented in .github/BRAND.md.
Credits
Built on Geoffrey Huntley's Ralph Wiggum methodology, forked from Florian Standhartinger's implementation.
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 owloop-0.2.1.tar.gz.
File metadata
- Download URL: owloop-0.2.1.tar.gz
- Upload date:
- Size: 414.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ecc241a3a39897c402c65881dbae2865295f5ff88bc8e9eb410298c1235c49bf
|
|
| MD5 |
5b9adc018bc01feae085488cd3e6e2e9
|
|
| BLAKE2b-256 |
f2309085285807bb6f9068aad08ce81c1eaf58028166d208bbad15eaf4363e24
|
Provenance
The following attestation bundles were made for owloop-0.2.1.tar.gz:
Publisher:
release.yml on caoergou/owloop
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
owloop-0.2.1.tar.gz -
Subject digest:
ecc241a3a39897c402c65881dbae2865295f5ff88bc8e9eb410298c1235c49bf - Sigstore transparency entry: 2058950415
- Sigstore integration time:
-
Permalink:
caoergou/owloop@5033766f7c754e2539d95ac30c867817cd32e935 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/caoergou
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5033766f7c754e2539d95ac30c867817cd32e935 -
Trigger Event:
push
-
Statement type:
File details
Details for the file owloop-0.2.1-py3-none-any.whl.
File metadata
- Download URL: owloop-0.2.1-py3-none-any.whl
- Upload date:
- Size: 54.9 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 |
5d1be2de081d90e6ab1f21a90cbeed52fc0a613d06ff6f0c729be9517c7113f8
|
|
| MD5 |
c342d73eb5d15af84df03f45520e2bfa
|
|
| BLAKE2b-256 |
4151acfa0e0bfd594db6bd135923cc0cf4aef957a0e9327f975e0267aea0c23b
|
Provenance
The following attestation bundles were made for owloop-0.2.1-py3-none-any.whl:
Publisher:
release.yml on caoergou/owloop
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
owloop-0.2.1-py3-none-any.whl -
Subject digest:
5d1be2de081d90e6ab1f21a90cbeed52fc0a613d06ff6f0c729be9517c7113f8 - Sigstore transparency entry: 2058950736
- Sigstore integration time:
-
Permalink:
caoergou/owloop@5033766f7c754e2539d95ac30c867817cd32e935 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/caoergou
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5033766f7c754e2539d95ac30c867817cd32e935 -
Trigger Event:
push
-
Statement type: