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.
Files changed (45) hide show
  1. ortus-0.1.0/.beads/README.md +81 -0
  2. ortus-0.1.0/.gitignore +29 -0
  3. ortus-0.1.0/PKG-INFO +187 -0
  4. ortus-0.1.0/README.md +151 -0
  5. ortus-0.1.0/pyproject.toml +81 -0
  6. ortus-0.1.0/src/ortus/__init__.py +3 -0
  7. ortus-0.1.0/src/ortus/__main__.py +11 -0
  8. ortus-0.1.0/src/ortus/cli.py +60 -0
  9. ortus-0.1.0/src/ortus/commands/__init__.py +0 -0
  10. ortus-0.1.0/src/ortus/commands/_stub.py +17 -0
  11. ortus-0.1.0/src/ortus/commands/check.py +159 -0
  12. ortus-0.1.0/src/ortus/commands/grind.py +331 -0
  13. ortus-0.1.0/src/ortus/commands/human.py +120 -0
  14. ortus-0.1.0/src/ortus/commands/init.py +85 -0
  15. ortus-0.1.0/src/ortus/commands/interview.py +87 -0
  16. ortus-0.1.0/src/ortus/commands/plan.py +94 -0
  17. ortus-0.1.0/src/ortus/commands/tail.py +485 -0
  18. ortus-0.1.0/src/ortus/commands/triage.py +47 -0
  19. ortus-0.1.0/src/ortus/core/__init__.py +0 -0
  20. ortus-0.1.0/src/ortus/core/bd.py +193 -0
  21. ortus-0.1.0/src/ortus/core/cache.py +50 -0
  22. ortus-0.1.0/src/ortus/core/claude.py +137 -0
  23. ortus-0.1.0/src/ortus/core/config.py +81 -0
  24. ortus-0.1.0/src/ortus/core/grind_logic.py +175 -0
  25. ortus-0.1.0/src/ortus/core/grind_loop.py +199 -0
  26. ortus-0.1.0/src/ortus/core/hooks.py +78 -0
  27. ortus-0.1.0/src/ortus/core/init_render.py +80 -0
  28. ortus-0.1.0/src/ortus/core/output.py +42 -0
  29. ortus-0.1.0/src/ortus/core/prompts.py +100 -0
  30. ortus-0.1.0/src/ortus/core/repo.py +33 -0
  31. ortus-0.1.0/src/ortus/core/sandbox.py +82 -0
  32. ortus-0.1.0/src/ortus/prompts/__init__.py +1 -0
  33. ortus-0.1.0/src/ortus/prompts/conditions/__init__.py +1 -0
  34. ortus-0.1.0/src/ortus/prompts/conditions/close-one.txt +16 -0
  35. ortus-0.1.0/src/ortus/prompts/conditions/queue-zero.txt +11 -0
  36. ortus-0.1.0/src/ortus/prompts/grind-prompt.md +349 -0
  37. ortus-0.1.0/src/ortus/prompts/interview-prompt.md +429 -0
  38. ortus-0.1.0/src/ortus/prompts/plan-prompt.md +50 -0
  39. ortus-0.1.0/src/ortus/prompts/triage-prompt.md +197 -0
  40. ortus-0.1.0/src/ortus/templates/.claude/settings.json.jinja +58 -0
  41. ortus-0.1.0/src/ortus/templates/.gitignore.jinja +43 -0
  42. ortus-0.1.0/src/ortus/templates/.ortusrc.jinja +5 -0
  43. ortus-0.1.0/src/ortus/templates/AGENTS.md.jinja +47 -0
  44. ortus-0.1.0/src/ortus/templates/__init__.py +1 -0
  45. 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
+ [![test](https://github.com/who/ortus/actions/workflows/test.yml/badge.svg?branch=main)](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
+ [![test](https://github.com/who/ortus/actions/workflows/test.yml/badge.svg?branch=main)](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,3 @@
1
+ """ortus: global Python CLI for bd-driven Claude Code workflows."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,11 @@
1
+ """Entry point for `python -m ortus` and the `ortus` console script."""
2
+
3
+ from ortus.cli import app
4
+
5
+
6
+ def main() -> None:
7
+ app()
8
+
9
+
10
+ if __name__ == "__main__":
11
+ main()
@@ -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)