Global Python CLI for ortus: bd-driven Claude Code workflows
Project description
Ortus
Ortus (Latin: "rising, origin, birth") — the point from which something springs into being.
Ortus autonomously closes a backlog of bd-tracked issues using Claude Code, one fresh subprocess per task. Inspired by the Ralph Loop concept: fresh window per task, drive the queue to zero, no context drift.
Install
Requires uv on PATH. Ortus is distributed via PyPI and installed by uv; we don't auto-install uv.
One-liner (recommended):
curl -fsSL https://github.com/who/ortus/releases/latest/download/install.sh | sh
Direct PyPI:
uv tool install ortus
ortus --version
From source / pinned commit:
uv tool install git+https://github.com/who/ortus.git
# Pin a specific tag/branch:
uv tool install 'git+https://github.com/who/ortus.git@v0.1.0'
Troubleshooting:
| Symptom | Fix |
|---|---|
uv: command not found |
Install uv: curl -LsSf https://astral.sh/uv/install.sh | sh (see uv docs) |
ortus: command not found after install |
uv tool update-shell then open a new shell |
bd: command not found |
brew install beads (mac) or grab a release from https://github.com/gastownhall/beads/releases |
Quick start
# Install Ortus globally (system-wide — don't add ortus as a project dependency)
curl -fsSL https://github.com/who/ortus/releases/latest/download/install.sh | sh
# Bootstrap YOUR project
cd your-project
ortus init .
# Verify prereqs (bd, claude, jq, hooks, sandbox)
ortus check .
# Decompose a PRD into bd issues
ortus plan . path/to/feature.md
# Or run the idea→interview→PRD→tasks flow with no PRD path
ortus plan .
# Drive the bd queue to zero — one task per fresh /goal subprocess
ortus grind .
# Bounded: stop after N tasks
ortus grind . --tasks 5
Note: Ortus is a global CLI you install once and use everywhere. You don't clone this repository into your project — ortus init only adds a small set of per-project files (.beads/, .claude/settings.json, AGENTS.md, .ortusrc, .gitignore) to an existing directory. It is not a Python dependency.
The eight verbs
| Verb | Purpose |
|---|---|
ortus init <repo> |
Bootstrap a fresh repo with bd + .claude/settings.json + AGENTS.md + .ortusrc + .gitignore |
ortus check <repo> |
Verify bd/claude/jq + sandbox prereq + hook-enabled + settings shape; strictly read-only |
ortus plan <repo> [<PRD>] |
Decompose a PRD into bd issues, or interview-then-PRD-then-decompose if no PRD path |
ortus grind <repo> |
Drive the bd queue, one task per fresh claude -p '/goal …' subprocess |
ortus interview <repo> [<feature-id>] |
Interactive PRD-building interview for an open feature |
ortus tail <repo> |
Follow logs/{grind,goal,ralph}-*.log with stream-json filtering |
ortus triage <repo> |
Walk the human-flagged bd queue interactively |
ortus human <repo> |
Render HUMAN-TODO.md from bd issues flagged for a human decision |
Run ortus <verb> --help for flags. Run ortus --version for the installed version.
Supported platforms
| Platform | Status | Notes |
|---|---|---|
| Linux (Ubuntu/WSL2) | full | requires bubblewrap for ortus grind |
| macOS | full | Seatbelt (sandbox-exec) is built-in |
Windows is not supported (decision 2026-05-17). Windows users should run ortus inside WSL2 (Windows Subsystem for Linux), where ortus runs as a normal Linux process.
Prerequisites
| Tool | Why | Install |
|---|---|---|
| uv | install + run ortus | docs.astral.sh/uv |
| bd (beads) v1.0.0+ | issue tracking (backed by embedded Dolt) | brew install beads or GH release |
| claude | the model running inside ortus grind |
Claude Code |
| jq | bd JSON post-processing | brew install jq / apt install jq |
| bwrap (Linux) or sandbox-exec (Mac) | OS-level sandbox for ortus grind |
apt install bubblewrap / built into macOS |
Optional: CodeGraph. If .codegraph/ exists in a project, ortus grind's prompts use it for faster symbol/caller/callee lookups; otherwise the loop falls back to grep + Read.
Why ortus
- One install, all projects.
uv tool install ortusonce; every repo uses the same canonical tooling. No morecopier updatechasing N repos. bd readyIS the queue. No README task lists, no TodoWrite scratchpads. The queue is data./goalIS the loop. Termination is a hook decision based on observable bd state, not a sentinel grep.- Sandboxed by default.
ortus grindrefuses to launch unless bwrap/Seatbelt is available; cache directories are project-local; network is allowlist-only via.claude/settings.json.
Configuration
Optional <repo>/.ortusrc (TOML) overrides ~/.ortusrc:
prefix = "myproj" # bd issue-id prefix
project_type = "python" # python | typescript | go | rust | polyglot
Per-repo or user-wide prompt overrides live at <repo>/.ortus/prompts/<name>.md or ~/.ortus/prompts/<name>.md; the bundled defaults under src/ortus/prompts/ are the fallback (FR-025).
Session-close protocol
When ending a work session, push your work:
bd close <id> --reason "..."
git add -A && git commit -m "..."
bd dolt push
git push
Work is not done until pushed. The generated AGENTS.md repeats this in every project.
Development
# Local editable install
uv pip install -e '.[dev]'
# Tests
pytest # unit + integration (fast)
pytest -m smoke # end-to-end smoke
pytest --slow # everything, including real-claude smoke
License
MIT
Project details
Release history Release notifications | RSS feed
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 ortus-0.1.2.tar.gz.
File metadata
- Download URL: ortus-0.1.2.tar.gz
- Upload date:
- Size: 54.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a508c1c20dcc4cc7876aaa89e241b1df73e63200e886c922aa566bda7b35b95d
|
|
| MD5 |
51966a0abd61a70f748426150a1824d0
|
|
| BLAKE2b-256 |
84a967ba3b1615c10e673fb6be21e470bbf144626ebcb2081beb11a34865628b
|
Provenance
The following attestation bundles were made for ortus-0.1.2.tar.gz:
Publisher:
release.yml on who/ortus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ortus-0.1.2.tar.gz -
Subject digest:
a508c1c20dcc4cc7876aaa89e241b1df73e63200e886c922aa566bda7b35b95d - Sigstore transparency entry: 1564050310
- Sigstore integration time:
-
Permalink:
who/ortus@231825c6a47922e41bd8fe50cb7cb4a13b380f41 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/who
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@231825c6a47922e41bd8fe50cb7cb4a13b380f41 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ortus-0.1.2-py3-none-any.whl.
File metadata
- Download URL: ortus-0.1.2-py3-none-any.whl
- Upload date:
- Size: 69.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 |
ed10452aca6587b255cf6af5b80959aa986642bb24134fa927cde39b232315f9
|
|
| MD5 |
25c6c0a061b0e4f5b5c99295fa000007
|
|
| BLAKE2b-256 |
6f8924936da009a33b30ae5c45906d955a2fb3184cf3daa8f4db079d4c819c2f
|
Provenance
The following attestation bundles were made for ortus-0.1.2-py3-none-any.whl:
Publisher:
release.yml on who/ortus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ortus-0.1.2-py3-none-any.whl -
Subject digest:
ed10452aca6587b255cf6af5b80959aa986642bb24134fa927cde39b232315f9 - Sigstore transparency entry: 1564050669
- Sigstore integration time:
-
Permalink:
who/ortus@231825c6a47922e41bd8fe50cb7cb4a13b380f41 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/who
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@231825c6a47922e41bd8fe50cb7cb4a13b380f41 -
Trigger Event:
push
-
Statement type: