ortus 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ortus-0.1.0/.beads/README.md +81 -0
- ortus-0.1.0/.gitignore +29 -0
- ortus-0.1.0/PKG-INFO +187 -0
- ortus-0.1.0/README.md +151 -0
- ortus-0.1.0/pyproject.toml +81 -0
- ortus-0.1.0/src/ortus/__init__.py +3 -0
- ortus-0.1.0/src/ortus/__main__.py +11 -0
- ortus-0.1.0/src/ortus/cli.py +60 -0
- ortus-0.1.0/src/ortus/commands/__init__.py +0 -0
- ortus-0.1.0/src/ortus/commands/_stub.py +17 -0
- ortus-0.1.0/src/ortus/commands/check.py +159 -0
- ortus-0.1.0/src/ortus/commands/grind.py +331 -0
- ortus-0.1.0/src/ortus/commands/human.py +120 -0
- ortus-0.1.0/src/ortus/commands/init.py +85 -0
- ortus-0.1.0/src/ortus/commands/interview.py +87 -0
- ortus-0.1.0/src/ortus/commands/plan.py +94 -0
- ortus-0.1.0/src/ortus/commands/tail.py +485 -0
- ortus-0.1.0/src/ortus/commands/triage.py +47 -0
- ortus-0.1.0/src/ortus/core/__init__.py +0 -0
- ortus-0.1.0/src/ortus/core/bd.py +193 -0
- ortus-0.1.0/src/ortus/core/cache.py +50 -0
- ortus-0.1.0/src/ortus/core/claude.py +137 -0
- ortus-0.1.0/src/ortus/core/config.py +81 -0
- ortus-0.1.0/src/ortus/core/grind_logic.py +175 -0
- ortus-0.1.0/src/ortus/core/grind_loop.py +199 -0
- ortus-0.1.0/src/ortus/core/hooks.py +78 -0
- ortus-0.1.0/src/ortus/core/init_render.py +80 -0
- ortus-0.1.0/src/ortus/core/output.py +42 -0
- ortus-0.1.0/src/ortus/core/prompts.py +100 -0
- ortus-0.1.0/src/ortus/core/repo.py +33 -0
- ortus-0.1.0/src/ortus/core/sandbox.py +82 -0
- ortus-0.1.0/src/ortus/prompts/__init__.py +1 -0
- ortus-0.1.0/src/ortus/prompts/conditions/__init__.py +1 -0
- ortus-0.1.0/src/ortus/prompts/conditions/close-one.txt +16 -0
- ortus-0.1.0/src/ortus/prompts/conditions/queue-zero.txt +11 -0
- ortus-0.1.0/src/ortus/prompts/grind-prompt.md +349 -0
- ortus-0.1.0/src/ortus/prompts/interview-prompt.md +429 -0
- ortus-0.1.0/src/ortus/prompts/plan-prompt.md +50 -0
- ortus-0.1.0/src/ortus/prompts/triage-prompt.md +197 -0
- ortus-0.1.0/src/ortus/templates/.claude/settings.json.jinja +58 -0
- ortus-0.1.0/src/ortus/templates/.gitignore.jinja +43 -0
- ortus-0.1.0/src/ortus/templates/.ortusrc.jinja +5 -0
- ortus-0.1.0/src/ortus/templates/AGENTS.md.jinja +47 -0
- ortus-0.1.0/src/ortus/templates/__init__.py +1 -0
- ortus-0.1.0/template/.beads/README.md +24 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Beads - AI-Native Issue Tracking
|
|
2
|
+
|
|
3
|
+
Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code.
|
|
4
|
+
|
|
5
|
+
## What is Beads?
|
|
6
|
+
|
|
7
|
+
Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git.
|
|
8
|
+
|
|
9
|
+
**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads)
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### Essential Commands
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Create new issues
|
|
17
|
+
bd create "Add user authentication"
|
|
18
|
+
|
|
19
|
+
# View all issues
|
|
20
|
+
bd list
|
|
21
|
+
|
|
22
|
+
# View issue details
|
|
23
|
+
bd show <issue-id>
|
|
24
|
+
|
|
25
|
+
# Update issue status
|
|
26
|
+
bd update <issue-id> --status in_progress
|
|
27
|
+
bd update <issue-id> --status done
|
|
28
|
+
|
|
29
|
+
# Push beads to Dolt remote
|
|
30
|
+
bd dolt push
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Working with Issues
|
|
34
|
+
|
|
35
|
+
Issues in Beads are:
|
|
36
|
+
- **Git-native**: Stored in `.beads/issues.jsonl` and synced like code
|
|
37
|
+
- **AI-friendly**: CLI-first design works perfectly with AI coding agents
|
|
38
|
+
- **Branch-aware**: Issues can follow your branch workflow
|
|
39
|
+
- **Always in sync**: Auto-syncs with your commits
|
|
40
|
+
|
|
41
|
+
## Why Beads?
|
|
42
|
+
|
|
43
|
+
✨ **AI-Native Design**
|
|
44
|
+
- Built specifically for AI-assisted development workflows
|
|
45
|
+
- CLI-first interface works seamlessly with AI coding agents
|
|
46
|
+
- No context switching to web UIs
|
|
47
|
+
|
|
48
|
+
🚀 **Developer Focused**
|
|
49
|
+
- Issues live in your repo, right next to your code
|
|
50
|
+
- Works offline, syncs when you push
|
|
51
|
+
- Fast, lightweight, and stays out of your way
|
|
52
|
+
|
|
53
|
+
🔧 **Git Integration**
|
|
54
|
+
- Automatic sync with git commits
|
|
55
|
+
- Branch-aware issue tracking
|
|
56
|
+
- Intelligent JSONL merge resolution
|
|
57
|
+
|
|
58
|
+
## Get Started with Beads
|
|
59
|
+
|
|
60
|
+
Try Beads in your own projects:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Install Beads
|
|
64
|
+
curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
|
|
65
|
+
|
|
66
|
+
# Initialize in your repo
|
|
67
|
+
bd init
|
|
68
|
+
|
|
69
|
+
# Create your first issue
|
|
70
|
+
bd create "Try out Beads"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Learn More
|
|
74
|
+
|
|
75
|
+
- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs)
|
|
76
|
+
- **Quick Start Guide**: Run `bd quickstart`
|
|
77
|
+
- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples)
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
*Beads: Issue tracking that moves at the speed of thought* ⚡
|
ortus-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
logs/
|
|
2
|
+
|
|
3
|
+
# Human-decision report (regenerated by ortus/human.sh on each run)
|
|
4
|
+
HUMAN-TODO.md
|
|
5
|
+
|
|
6
|
+
# Beads / Dolt files (added by bd init)
|
|
7
|
+
.dolt/
|
|
8
|
+
*.db
|
|
9
|
+
.beads-credential-key
|
|
10
|
+
|
|
11
|
+
# Python build / venv / cache artifacts
|
|
12
|
+
.venv/
|
|
13
|
+
dist/
|
|
14
|
+
build/
|
|
15
|
+
*.egg-info/
|
|
16
|
+
__pycache__/
|
|
17
|
+
*.py[cod]
|
|
18
|
+
.cache/
|
|
19
|
+
.pytest_cache/
|
|
20
|
+
.coverage
|
|
21
|
+
.coverage.*
|
|
22
|
+
htmlcov/
|
|
23
|
+
.tox/
|
|
24
|
+
|
|
25
|
+
# Node detritus that shouldn't be tracked at repo root
|
|
26
|
+
node_modules/
|
|
27
|
+
package-lock.json
|
|
28
|
+
package.json
|
|
29
|
+
|
ortus-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ortus
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Global Python CLI for ortus: bd-driven Claude Code workflows
|
|
5
|
+
Project-URL: Homepage, https://github.com/who/ortus
|
|
6
|
+
Project-URL: Repository, https://github.com/who/ortus
|
|
7
|
+
Project-URL: Issues, https://github.com/who/ortus/issues
|
|
8
|
+
Author-email: who <githubwho@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: ai-coding,bd,beads,claude,cli,ortus
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: MacOS
|
|
16
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Software Development
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: jinja2>=3.1.0
|
|
26
|
+
Requires-Dist: portalocker>=2.0.0
|
|
27
|
+
Requires-Dist: rich>=13.7.0
|
|
28
|
+
Requires-Dist: tomli>=2.0.0; python_version < '3.11'
|
|
29
|
+
Requires-Dist: typer>=0.12.0
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: build>=1.2.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest-subprocess>=1.5.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# Ortus
|
|
38
|
+
|
|
39
|
+
[](https://github.com/who/ortus/actions/workflows/test.yml)
|
|
40
|
+
|
|
41
|
+
*Ortus* (Latin: "rising, origin, birth") — the point from which something springs into being.
|
|
42
|
+
|
|
43
|
+
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.
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
**Requires [uv](https://docs.astral.sh/uv/getting-started/installation/) on PATH.** Ortus is distributed via PyPI and installed by uv; we don't auto-install uv.
|
|
48
|
+
|
|
49
|
+
**One-liner (recommended):**
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
curl -fsSL https://github.com/who/ortus/releases/latest/download/install.sh | sh
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Direct PyPI:**
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
uv tool install ortus
|
|
59
|
+
ortus --version
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**From source / pinned commit:**
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
uv tool install git+https://github.com/who/ortus.git
|
|
66
|
+
# Pin a specific tag/branch:
|
|
67
|
+
uv tool install 'git+https://github.com/who/ortus.git@v0.1.0'
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Troubleshooting:**
|
|
71
|
+
|
|
72
|
+
| Symptom | Fix |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `uv: command not found` | Install uv: `curl -LsSf https://astral.sh/uv/install.sh \| sh` (see [uv docs](https://docs.astral.sh/uv/getting-started/installation/)) |
|
|
75
|
+
| `ortus: command not found` after install | `uv tool update-shell` then open a new shell |
|
|
76
|
+
| `bd: command not found` | `brew install beads` (mac) or grab a release from https://github.com/gastownhall/beads/releases |
|
|
77
|
+
|
|
78
|
+
## Quick start
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Install Ortus globally (system-wide — don't add ortus as a project dependency)
|
|
82
|
+
curl -fsSL https://github.com/who/ortus/releases/latest/download/install.sh | sh
|
|
83
|
+
|
|
84
|
+
# Bootstrap YOUR project
|
|
85
|
+
cd your-project
|
|
86
|
+
ortus init .
|
|
87
|
+
|
|
88
|
+
# Verify prereqs (bd, claude, jq, hooks, sandbox)
|
|
89
|
+
ortus check .
|
|
90
|
+
|
|
91
|
+
# Decompose a PRD into bd issues
|
|
92
|
+
ortus plan . path/to/feature.md
|
|
93
|
+
|
|
94
|
+
# Or run the idea→interview→PRD→tasks flow with no PRD path
|
|
95
|
+
ortus plan .
|
|
96
|
+
|
|
97
|
+
# Drive the bd queue to zero — one task per fresh /goal subprocess
|
|
98
|
+
ortus grind .
|
|
99
|
+
|
|
100
|
+
# Bounded: stop after N tasks
|
|
101
|
+
ortus grind . --tasks 5
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**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.
|
|
105
|
+
|
|
106
|
+
## The eight verbs
|
|
107
|
+
|
|
108
|
+
| Verb | Purpose |
|
|
109
|
+
|---|---|
|
|
110
|
+
| `ortus init <repo>` | Bootstrap a fresh repo with bd + .claude/settings.json + AGENTS.md + .ortusrc + .gitignore |
|
|
111
|
+
| `ortus check <repo>` | Verify bd/claude/jq + sandbox prereq + hook-enabled + settings shape; strictly read-only |
|
|
112
|
+
| `ortus plan <repo> [<PRD>]` | Decompose a PRD into bd issues, or interview-then-PRD-then-decompose if no PRD path |
|
|
113
|
+
| `ortus grind <repo>` | Drive the bd queue, one task per fresh `claude -p '/goal …'` subprocess |
|
|
114
|
+
| `ortus interview <repo> [<feature-id>]` | Interactive PRD-building interview for an open feature |
|
|
115
|
+
| `ortus tail <repo>` | Follow `logs/{grind,goal,ralph}-*.log` with stream-json filtering |
|
|
116
|
+
| `ortus triage <repo>` | Walk the human-flagged bd queue interactively |
|
|
117
|
+
| `ortus human <repo>` | Render `HUMAN-TODO.md` from bd issues flagged for a human decision |
|
|
118
|
+
|
|
119
|
+
Run `ortus <verb> --help` for flags. Run `ortus --version` for the installed version.
|
|
120
|
+
|
|
121
|
+
### Supported platforms
|
|
122
|
+
|
|
123
|
+
| Platform | Status | Notes |
|
|
124
|
+
|---|---|---|
|
|
125
|
+
| Linux (Ubuntu/WSL2) | full | requires `bubblewrap` for `ortus grind` |
|
|
126
|
+
| macOS | full | Seatbelt (`sandbox-exec`) is built-in |
|
|
127
|
+
|
|
128
|
+
**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.
|
|
129
|
+
|
|
130
|
+
## Prerequisites
|
|
131
|
+
|
|
132
|
+
| Tool | Why | Install |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| **uv** | install + run ortus | [docs.astral.sh/uv](https://docs.astral.sh/uv/getting-started/installation/) |
|
|
135
|
+
| **bd** (beads) v1.0.0+ | issue tracking (backed by embedded Dolt) | `brew install beads` or [GH release](https://github.com/gastownhall/beads/releases) |
|
|
136
|
+
| **claude** | the model running inside `ortus grind` | [Claude Code](https://github.com/anthropics/claude-code) |
|
|
137
|
+
| **jq** | bd JSON post-processing | `brew install jq` / `apt install jq` |
|
|
138
|
+
| **bwrap** (Linux) or **sandbox-exec** (Mac) | OS-level sandbox for `ortus grind` | `apt install bubblewrap` / built into macOS |
|
|
139
|
+
|
|
140
|
+
Optional: **[CodeGraph](https://github.com/colbymchenry/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.
|
|
141
|
+
|
|
142
|
+
## Why ortus
|
|
143
|
+
|
|
144
|
+
- **One install, all projects.** `uv tool install ortus` once; every repo uses the same canonical tooling. No more `copier update` chasing N repos.
|
|
145
|
+
- **`bd ready` IS the queue.** No README task lists, no TodoWrite scratchpads. The queue is data.
|
|
146
|
+
- **`/goal` IS the loop.** Termination is a hook decision based on observable bd state, not a sentinel grep.
|
|
147
|
+
- **Sandboxed by default.** `ortus grind` refuses to launch unless bwrap/Seatbelt is available; cache directories are project-local; network is allowlist-only via `.claude/settings.json`.
|
|
148
|
+
|
|
149
|
+
## Configuration
|
|
150
|
+
|
|
151
|
+
Optional `<repo>/.ortusrc` (TOML) overrides `~/.ortusrc`:
|
|
152
|
+
|
|
153
|
+
```toml
|
|
154
|
+
prefix = "myproj" # bd issue-id prefix
|
|
155
|
+
project_type = "python" # python | typescript | go | rust | polyglot
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
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).
|
|
159
|
+
|
|
160
|
+
## Session-close protocol
|
|
161
|
+
|
|
162
|
+
When ending a work session, push your work:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
bd close <id> --reason "..."
|
|
166
|
+
git add -A && git commit -m "..."
|
|
167
|
+
bd dolt push
|
|
168
|
+
git push
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Work is not done until pushed. The generated `AGENTS.md` repeats this in every project.
|
|
172
|
+
|
|
173
|
+
## Development
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Local editable install
|
|
177
|
+
uv pip install -e '.[dev]'
|
|
178
|
+
|
|
179
|
+
# Tests
|
|
180
|
+
pytest # unit + integration (fast)
|
|
181
|
+
pytest -m smoke # end-to-end smoke
|
|
182
|
+
pytest --slow # everything, including real-claude smoke
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## License
|
|
186
|
+
|
|
187
|
+
MIT
|
ortus-0.1.0/README.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Ortus
|
|
2
|
+
|
|
3
|
+
[](https://github.com/who/ortus/actions/workflows/test.yml)
|
|
4
|
+
|
|
5
|
+
*Ortus* (Latin: "rising, origin, birth") — the point from which something springs into being.
|
|
6
|
+
|
|
7
|
+
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.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
**Requires [uv](https://docs.astral.sh/uv/getting-started/installation/) on PATH.** Ortus is distributed via PyPI and installed by uv; we don't auto-install uv.
|
|
12
|
+
|
|
13
|
+
**One-liner (recommended):**
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
curl -fsSL https://github.com/who/ortus/releases/latest/download/install.sh | sh
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Direct PyPI:**
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv tool install ortus
|
|
23
|
+
ortus --version
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**From source / pinned commit:**
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
uv tool install git+https://github.com/who/ortus.git
|
|
30
|
+
# Pin a specific tag/branch:
|
|
31
|
+
uv tool install 'git+https://github.com/who/ortus.git@v0.1.0'
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Troubleshooting:**
|
|
35
|
+
|
|
36
|
+
| Symptom | Fix |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `uv: command not found` | Install uv: `curl -LsSf https://astral.sh/uv/install.sh \| sh` (see [uv docs](https://docs.astral.sh/uv/getting-started/installation/)) |
|
|
39
|
+
| `ortus: command not found` after install | `uv tool update-shell` then open a new shell |
|
|
40
|
+
| `bd: command not found` | `brew install beads` (mac) or grab a release from https://github.com/gastownhall/beads/releases |
|
|
41
|
+
|
|
42
|
+
## Quick start
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Install Ortus globally (system-wide — don't add ortus as a project dependency)
|
|
46
|
+
curl -fsSL https://github.com/who/ortus/releases/latest/download/install.sh | sh
|
|
47
|
+
|
|
48
|
+
# Bootstrap YOUR project
|
|
49
|
+
cd your-project
|
|
50
|
+
ortus init .
|
|
51
|
+
|
|
52
|
+
# Verify prereqs (bd, claude, jq, hooks, sandbox)
|
|
53
|
+
ortus check .
|
|
54
|
+
|
|
55
|
+
# Decompose a PRD into bd issues
|
|
56
|
+
ortus plan . path/to/feature.md
|
|
57
|
+
|
|
58
|
+
# Or run the idea→interview→PRD→tasks flow with no PRD path
|
|
59
|
+
ortus plan .
|
|
60
|
+
|
|
61
|
+
# Drive the bd queue to zero — one task per fresh /goal subprocess
|
|
62
|
+
ortus grind .
|
|
63
|
+
|
|
64
|
+
# Bounded: stop after N tasks
|
|
65
|
+
ortus grind . --tasks 5
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**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.
|
|
69
|
+
|
|
70
|
+
## The eight verbs
|
|
71
|
+
|
|
72
|
+
| Verb | Purpose |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `ortus init <repo>` | Bootstrap a fresh repo with bd + .claude/settings.json + AGENTS.md + .ortusrc + .gitignore |
|
|
75
|
+
| `ortus check <repo>` | Verify bd/claude/jq + sandbox prereq + hook-enabled + settings shape; strictly read-only |
|
|
76
|
+
| `ortus plan <repo> [<PRD>]` | Decompose a PRD into bd issues, or interview-then-PRD-then-decompose if no PRD path |
|
|
77
|
+
| `ortus grind <repo>` | Drive the bd queue, one task per fresh `claude -p '/goal …'` subprocess |
|
|
78
|
+
| `ortus interview <repo> [<feature-id>]` | Interactive PRD-building interview for an open feature |
|
|
79
|
+
| `ortus tail <repo>` | Follow `logs/{grind,goal,ralph}-*.log` with stream-json filtering |
|
|
80
|
+
| `ortus triage <repo>` | Walk the human-flagged bd queue interactively |
|
|
81
|
+
| `ortus human <repo>` | Render `HUMAN-TODO.md` from bd issues flagged for a human decision |
|
|
82
|
+
|
|
83
|
+
Run `ortus <verb> --help` for flags. Run `ortus --version` for the installed version.
|
|
84
|
+
|
|
85
|
+
### Supported platforms
|
|
86
|
+
|
|
87
|
+
| Platform | Status | Notes |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| Linux (Ubuntu/WSL2) | full | requires `bubblewrap` for `ortus grind` |
|
|
90
|
+
| macOS | full | Seatbelt (`sandbox-exec`) is built-in |
|
|
91
|
+
|
|
92
|
+
**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.
|
|
93
|
+
|
|
94
|
+
## Prerequisites
|
|
95
|
+
|
|
96
|
+
| Tool | Why | Install |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| **uv** | install + run ortus | [docs.astral.sh/uv](https://docs.astral.sh/uv/getting-started/installation/) |
|
|
99
|
+
| **bd** (beads) v1.0.0+ | issue tracking (backed by embedded Dolt) | `brew install beads` or [GH release](https://github.com/gastownhall/beads/releases) |
|
|
100
|
+
| **claude** | the model running inside `ortus grind` | [Claude Code](https://github.com/anthropics/claude-code) |
|
|
101
|
+
| **jq** | bd JSON post-processing | `brew install jq` / `apt install jq` |
|
|
102
|
+
| **bwrap** (Linux) or **sandbox-exec** (Mac) | OS-level sandbox for `ortus grind` | `apt install bubblewrap` / built into macOS |
|
|
103
|
+
|
|
104
|
+
Optional: **[CodeGraph](https://github.com/colbymchenry/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.
|
|
105
|
+
|
|
106
|
+
## Why ortus
|
|
107
|
+
|
|
108
|
+
- **One install, all projects.** `uv tool install ortus` once; every repo uses the same canonical tooling. No more `copier update` chasing N repos.
|
|
109
|
+
- **`bd ready` IS the queue.** No README task lists, no TodoWrite scratchpads. The queue is data.
|
|
110
|
+
- **`/goal` IS the loop.** Termination is a hook decision based on observable bd state, not a sentinel grep.
|
|
111
|
+
- **Sandboxed by default.** `ortus grind` refuses to launch unless bwrap/Seatbelt is available; cache directories are project-local; network is allowlist-only via `.claude/settings.json`.
|
|
112
|
+
|
|
113
|
+
## Configuration
|
|
114
|
+
|
|
115
|
+
Optional `<repo>/.ortusrc` (TOML) overrides `~/.ortusrc`:
|
|
116
|
+
|
|
117
|
+
```toml
|
|
118
|
+
prefix = "myproj" # bd issue-id prefix
|
|
119
|
+
project_type = "python" # python | typescript | go | rust | polyglot
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
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).
|
|
123
|
+
|
|
124
|
+
## Session-close protocol
|
|
125
|
+
|
|
126
|
+
When ending a work session, push your work:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
bd close <id> --reason "..."
|
|
130
|
+
git add -A && git commit -m "..."
|
|
131
|
+
bd dolt push
|
|
132
|
+
git push
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Work is not done until pushed. The generated `AGENTS.md` repeats this in every project.
|
|
136
|
+
|
|
137
|
+
## Development
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# Local editable install
|
|
141
|
+
uv pip install -e '.[dev]'
|
|
142
|
+
|
|
143
|
+
# Tests
|
|
144
|
+
pytest # unit + integration (fast)
|
|
145
|
+
pytest -m smoke # end-to-end smoke
|
|
146
|
+
pytest --slow # everything, including real-claude smoke
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## License
|
|
150
|
+
|
|
151
|
+
MIT
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ortus"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Global Python CLI for ortus: bd-driven Claude Code workflows"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "who", email = "githubwho@gmail.com" }]
|
|
13
|
+
keywords = ["claude", "beads", "bd", "cli", "ortus", "ai-coding"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: MacOS",
|
|
20
|
+
"Operating System :: POSIX :: Linux",
|
|
21
|
+
"Operating System :: Microsoft :: Windows",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Software Development",
|
|
27
|
+
"Topic :: Utilities",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"typer>=0.12.0",
|
|
31
|
+
"rich>=13.7.0",
|
|
32
|
+
"jinja2>=3.1.0",
|
|
33
|
+
"tomli>=2.0.0; python_version < '3.11'",
|
|
34
|
+
"portalocker>=2.0.0",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
dev = [
|
|
39
|
+
"pytest>=8.0.0",
|
|
40
|
+
"pytest-cov>=5.0.0",
|
|
41
|
+
"pytest-subprocess>=1.5.0",
|
|
42
|
+
"build>=1.2.0",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[project.scripts]
|
|
46
|
+
ortus = "ortus.__main__:main"
|
|
47
|
+
|
|
48
|
+
[project.urls]
|
|
49
|
+
Homepage = "https://github.com/who/ortus"
|
|
50
|
+
Repository = "https://github.com/who/ortus"
|
|
51
|
+
Issues = "https://github.com/who/ortus/issues"
|
|
52
|
+
|
|
53
|
+
[tool.hatch.build.targets.sdist]
|
|
54
|
+
include = [
|
|
55
|
+
"src/ortus",
|
|
56
|
+
"README.md",
|
|
57
|
+
"pyproject.toml",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[tool.hatch.build.targets.wheel]
|
|
61
|
+
packages = ["src/ortus"]
|
|
62
|
+
# hatchling skips dotfiles by default; force-include only the dot-prefixed
|
|
63
|
+
# leaf files (the .claude/ subtree is picked up by `packages` already since
|
|
64
|
+
# it contains a .jinja file, so re-listing it duplicates entries).
|
|
65
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
66
|
+
"src/ortus/templates/.ortusrc.jinja" = "ortus/templates/.ortusrc.jinja"
|
|
67
|
+
"src/ortus/templates/.gitignore.jinja" = "ortus/templates/.gitignore.jinja"
|
|
68
|
+
|
|
69
|
+
[tool.hatch.build.targets.sdist.force-include]
|
|
70
|
+
"src/ortus/templates/.ortusrc.jinja" = "src/ortus/templates/.ortusrc.jinja"
|
|
71
|
+
"src/ortus/templates/.gitignore.jinja" = "src/ortus/templates/.gitignore.jinja"
|
|
72
|
+
|
|
73
|
+
[tool.pytest.ini_options]
|
|
74
|
+
testpaths = ["tests"]
|
|
75
|
+
addopts = "-ra --strict-markers"
|
|
76
|
+
markers = [
|
|
77
|
+
"integration: tests that shell out to real external binaries (bd, claude, etc.)",
|
|
78
|
+
"regression: regression tests guarding against specific past bugs (e.g., ortus-6q8v stream-leak)",
|
|
79
|
+
"smoke: end-to-end smoke tests against seeded fixtures + canned claude responses",
|
|
80
|
+
"slow: tests that exceed ~5s (gated behind --slow in CI; on by default locally)",
|
|
81
|
+
]
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Top-level typer app + 8-verb registration (FR-001, FR-002, FR-004, FR-005)."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version as _pkg_version
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from ortus.commands.check import check
|
|
8
|
+
from ortus.commands.grind import grind
|
|
9
|
+
from ortus.commands.human import human
|
|
10
|
+
from ortus.commands.init import init
|
|
11
|
+
from ortus.commands.interview import interview
|
|
12
|
+
from ortus.commands.plan import plan
|
|
13
|
+
from ortus.commands.tail import tail
|
|
14
|
+
from ortus.commands.triage import triage
|
|
15
|
+
|
|
16
|
+
app = typer.Typer(
|
|
17
|
+
name="ortus",
|
|
18
|
+
help="Global CLI for bd-driven Claude Code workflows.",
|
|
19
|
+
no_args_is_help=True,
|
|
20
|
+
add_completion=False,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _resolve_version() -> str:
|
|
25
|
+
try:
|
|
26
|
+
return _pkg_version("ortus")
|
|
27
|
+
except PackageNotFoundError:
|
|
28
|
+
from ortus import __version__
|
|
29
|
+
|
|
30
|
+
return __version__
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _version_callback(value: bool) -> None:
|
|
34
|
+
if value:
|
|
35
|
+
typer.echo(f"ortus {_resolve_version()}")
|
|
36
|
+
raise typer.Exit()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@app.callback()
|
|
40
|
+
def main(
|
|
41
|
+
version: bool = typer.Option(
|
|
42
|
+
False,
|
|
43
|
+
"--version",
|
|
44
|
+
callback=_version_callback,
|
|
45
|
+
is_eager=True,
|
|
46
|
+
help="Show ortus version and exit.",
|
|
47
|
+
),
|
|
48
|
+
) -> None:
|
|
49
|
+
"""ortus: global CLI for bd-driven Claude Code workflows."""
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# FR-002: exactly 8 verbs. Order here drives --help listing order.
|
|
53
|
+
app.command(name="init", help="Bootstrap a fresh repo (bd + .claude + AGENTS.md).")(init)
|
|
54
|
+
app.command(name="plan", help="Decompose a PRD (or freeform idea) into bd issues.")(plan)
|
|
55
|
+
app.command(name="grind", help="Drive the bd queue via a subprocess-per-task claude /goal loop.")(grind)
|
|
56
|
+
app.command(name="interview", help="Interactive PRD-building interview.")(interview)
|
|
57
|
+
app.command(name="tail", help="Tail orchestrator log files (grind-*, goal-*, ralph-*).")(tail)
|
|
58
|
+
app.command(name="triage", help="Triage open bd issues interactively.")(triage)
|
|
59
|
+
app.command(name="human", help="Emit HUMAN-TODO.md for items needing a human decision.")(human)
|
|
60
|
+
app.command(name="check", help="Verify bd/claude/sandbox prereqs.")(check)
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Shared 'not implemented' helper for Phase 1 stub verbs."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
|
|
8
|
+
_err = Console(stderr=True)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def not_implemented(verb: str, phase: str) -> None:
|
|
12
|
+
"""Print a clear unimplemented-stub message and exit 2."""
|
|
13
|
+
_err.print(
|
|
14
|
+
f"[yellow]ortus {verb}:[/yellow] not implemented in this phase "
|
|
15
|
+
f"(lands in {phase})."
|
|
16
|
+
)
|
|
17
|
+
raise typer.Exit(code=2)
|