troupe 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.
- troupe-0.1.0/.claude-plugin/plugin.json +11 -0
- troupe-0.1.0/.gitattributes +3 -0
- troupe-0.1.0/.github/workflows/ci.yml +53 -0
- troupe-0.1.0/.github/workflows/release.yml +50 -0
- troupe-0.1.0/.gitignore +18 -0
- troupe-0.1.0/CHANGELOG.md +24 -0
- troupe-0.1.0/LICENSE +21 -0
- troupe-0.1.0/PKG-INFO +167 -0
- troupe-0.1.0/PROJECT-BRIEF.md +172 -0
- troupe-0.1.0/README.md +143 -0
- troupe-0.1.0/pyproject.toml +68 -0
- troupe-0.1.0/scripts/check_wheel.py +51 -0
- troupe-0.1.0/skills/troupe/SKILL.md +39 -0
- troupe-0.1.0/src/troupe/__init__.py +3 -0
- troupe-0.1.0/src/troupe/casting/__init__.py +1 -0
- troupe-0.1.0/src/troupe/casting/names.json +126 -0
- troupe-0.1.0/src/troupe/casting/registry.py +70 -0
- troupe-0.1.0/src/troupe/casting/roles.py +135 -0
- troupe-0.1.0/src/troupe/charters/__init__.py +1 -0
- troupe-0.1.0/src/troupe/charters/compiler.py +47 -0
- troupe-0.1.0/src/troupe/cli.py +51 -0
- troupe-0.1.0/src/troupe/commands/__init__.py +1 -0
- troupe-0.1.0/src/troupe/commands/doctor.py +249 -0
- troupe-0.1.0/src/troupe/commands/init.py +64 -0
- troupe-0.1.0/src/troupe/commands/upgrade.py +38 -0
- troupe-0.1.0/src/troupe/commands/watch.py +145 -0
- troupe-0.1.0/src/troupe/governance/__init__.py +1 -0
- troupe-0.1.0/src/troupe/governance/wiring.py +91 -0
- troupe-0.1.0/src/troupe/reeve/__init__.py +26 -0
- troupe-0.1.0/src/troupe/reeve/context.py +105 -0
- troupe-0.1.0/src/troupe/reeve/cycle.py +123 -0
- troupe-0.1.0/src/troupe/reeve/poller.py +96 -0
- troupe-0.1.0/src/troupe/reeve/runner.py +179 -0
- troupe-0.1.0/src/troupe/reeve/state.py +124 -0
- troupe-0.1.0/src/troupe/scaffold.py +226 -0
- troupe-0.1.0/src/troupe/templates/agent.md +28 -0
- troupe-0.1.0/src/troupe/templates/charter.md +24 -0
- troupe-0.1.0/src/troupe/templates/decisions.md +13 -0
- troupe-0.1.0/src/troupe/templates/directives.md +7 -0
- troupe-0.1.0/src/troupe/templates/history.md +10 -0
- troupe-0.1.0/src/troupe/templates/hooks/troupe_decision_log.py +96 -0
- troupe-0.1.0/src/troupe/templates/hooks/troupe_file_guard.py +84 -0
- troupe-0.1.0/src/troupe/templates/hooks/troupe_idle_nudge.py +95 -0
- troupe-0.1.0/src/troupe/templates/hooks/troupe_pii_scrub.py +109 -0
- troupe-0.1.0/src/troupe/templates/hooks/troupe_review_gate.py +86 -0
- troupe-0.1.0/src/troupe/templates/hooks/troupe_session_context.py +120 -0
- troupe-0.1.0/src/troupe/templates/policy.json +31 -0
- troupe-0.1.0/src/troupe/templates/team.md +15 -0
- troupe-0.1.0/src/troupe/upgrade.py +103 -0
- troupe-0.1.0/tests/conftest.py +55 -0
- troupe-0.1.0/tests/test_casting.py +46 -0
- troupe-0.1.0/tests/test_cli.py +17 -0
- troupe-0.1.0/tests/test_doctor_upgrade.py +149 -0
- troupe-0.1.0/tests/test_governance.py +219 -0
- troupe-0.1.0/tests/test_hooks.py +185 -0
- troupe-0.1.0/tests/test_init.py +92 -0
- troupe-0.1.0/tests/test_packaging.py +25 -0
- troupe-0.1.0/tests/test_reeve.py +452 -0
- troupe-0.1.0/uv.lock +211 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "troupe",
|
|
3
|
+
"description": "A persistent, governed AI team for Claude Code - named cast, enforced governance hooks, shared decision log, and an autonomous issue watch (Reeve).",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Kevin"
|
|
7
|
+
},
|
|
8
|
+
"homepage": "https://github.com/KevinIssaDev/troupe",
|
|
9
|
+
"repository": "https://github.com/KevinIssaDev/troupe",
|
|
10
|
+
"license": "MIT"
|
|
11
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
name: ${{ matrix.os }} / py${{ matrix.python }}
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
16
|
+
python: ["3.11", "3.13"]
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- uses: astral-sh/setup-uv@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python }}
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: uv sync --dev
|
|
26
|
+
|
|
27
|
+
- name: Lint
|
|
28
|
+
run: uv run ruff check .
|
|
29
|
+
|
|
30
|
+
- name: Format check
|
|
31
|
+
run: uv run ruff format --check .
|
|
32
|
+
|
|
33
|
+
- name: Type check
|
|
34
|
+
run: uv run pyright
|
|
35
|
+
|
|
36
|
+
- name: Test
|
|
37
|
+
run: uv run pytest
|
|
38
|
+
|
|
39
|
+
build:
|
|
40
|
+
name: build & package data
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
|
|
45
|
+
- uses: astral-sh/setup-uv@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: "3.12"
|
|
48
|
+
|
|
49
|
+
- name: Build distributions
|
|
50
|
+
run: uv build
|
|
51
|
+
|
|
52
|
+
- name: Verify wheel contains package data
|
|
53
|
+
run: uv run --no-project python scripts/check_wheel.py dist
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
|
|
13
|
+
- uses: astral-sh/setup-uv@v5
|
|
14
|
+
with:
|
|
15
|
+
python-version: "3.12"
|
|
16
|
+
|
|
17
|
+
- name: Install dependencies
|
|
18
|
+
run: uv sync --dev
|
|
19
|
+
|
|
20
|
+
- name: Quality gate
|
|
21
|
+
run: |
|
|
22
|
+
uv run ruff check .
|
|
23
|
+
uv run ruff format --check .
|
|
24
|
+
uv run pyright
|
|
25
|
+
uv run pytest
|
|
26
|
+
|
|
27
|
+
- name: Build distributions
|
|
28
|
+
run: uv build
|
|
29
|
+
|
|
30
|
+
- name: Verify wheel contains package data
|
|
31
|
+
run: uv run python scripts/check_wheel.py dist
|
|
32
|
+
|
|
33
|
+
- uses: actions/upload-artifact@v4
|
|
34
|
+
with:
|
|
35
|
+
name: dist
|
|
36
|
+
path: dist/
|
|
37
|
+
|
|
38
|
+
publish:
|
|
39
|
+
needs: build
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
environment: pypi
|
|
42
|
+
permissions:
|
|
43
|
+
id-token: write # OIDC for PyPI Trusted Publishing — no API tokens
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/download-artifact@v4
|
|
46
|
+
with:
|
|
47
|
+
name: dist
|
|
48
|
+
path: dist/
|
|
49
|
+
|
|
50
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
troupe-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (2026-07-06)
|
|
4
|
+
|
|
5
|
+
Initial release. Reeve's execute path was rehearsed live against a sandbox
|
|
6
|
+
repo before this release: one governed cycle fixed a README typo and
|
|
7
|
+
commented its outcome on the issue for $0.55 of a $2.00 budget.
|
|
8
|
+
|
|
9
|
+
- `troupe init` — casts a persistent, named AI team (craft-surname pool with
|
|
10
|
+
role affinities) into `.troupe/` + `.claude/`; idempotent, never overwrites
|
|
11
|
+
team state
|
|
12
|
+
- Compiled agent definitions in `.claude/agents/` work both as Agent Teams
|
|
13
|
+
teammate types and as plain subagents (no experimental flag required)
|
|
14
|
+
- Six enforced governance hooks, emitted as self-contained stdlib-only
|
|
15
|
+
scripts: file-write guard, PII scrub (redact-in-place), decision logger,
|
|
16
|
+
opt-in human review gate, bounded idle nudge, session context injection
|
|
17
|
+
- `troupe doctor` — setup diagnosis; `troupe upgrade` — refreshes
|
|
18
|
+
troupe-owned files without touching team state
|
|
19
|
+
- Reeve (`troupe watch`) — autonomous GitHub issue watch: triage-only by
|
|
20
|
+
default, `--execute` opt-in, turn/budget/wall-clock ceilings per run,
|
|
21
|
+
per-cycle and per-day cost caps, per-issue failure backoff with human
|
|
22
|
+
escalation, `reeve-stop` sentinel
|
|
23
|
+
- Claude Code plugin manifest + skill wrapping the CLI
|
|
24
|
+
- CI across Ubuntu/macOS/Windows; PyPI publishing via Trusted Publishing
|
troupe-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kevin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
troupe-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: troupe
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A persistent, governed AI team for Claude Code — a named cast of specialists, enforced governance hooks, a shared decision log, and an autonomous issue-triage loop.
|
|
5
|
+
Project-URL: Homepage, https://github.com/KevinIssaDev/troupe
|
|
6
|
+
Project-URL: Repository, https://github.com/KevinIssaDev/troupe
|
|
7
|
+
Project-URL: Changelog, https://github.com/KevinIssaDev/troupe/blob/main/CHANGELOG.md
|
|
8
|
+
Author: Kevin
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agent-teams,ai-agents,claude-code,cli,governance
|
|
12
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: typer>=0.12
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# Troupe
|
|
26
|
+
|
|
27
|
+
**A persistent, governed AI team for Claude Code.**
|
|
28
|
+
|
|
29
|
+
Troupe gives your repository a named cast of AI specialists — a lead, a backend dev, a frontend dev, a tester — that **live in your repo as files**. They keep their names, charters, and accumulated knowledge across sessions, share an append-only architectural decision log, work under governance rules enforced by real Claude Code hooks (not polite prompt suggestions), and can optionally triage your GitHub issues overnight.
|
|
30
|
+
|
|
31
|
+
> ⚠️ **Alpha software.** Interfaces may change between releases. Reeve (the autonomous watch) spends real money when you pass `--execute` — read [its safety model](#reeve--the-autonomous-issue-watch) first.
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
$ uvx troupe init
|
|
35
|
+
|
|
36
|
+
Cast:
|
|
37
|
+
Wright Lead
|
|
38
|
+
Mason Backend
|
|
39
|
+
Webster Frontend
|
|
40
|
+
Sawyer Tester
|
|
41
|
+
Created 24 file(s), left 0 untouched.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Why Troupe when Agent Teams exists
|
|
45
|
+
|
|
46
|
+
Claude Code's experimental [Agent Teams](https://code.claude.com/docs/en/agent-teams) already does orchestration well: a team lead, parallel teammates with their own context windows, a shared task list, inter-agent messaging. **Troupe builds none of that.** It fills the gaps that are file-shaped — the things that vanish when the session ends:
|
|
47
|
+
|
|
48
|
+
| | Agent Teams (native) | Troupe adds |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| **Team identity** | Session-scoped; teams are named `session-…` and dissolve on exit | A persistent cast with names, charters, and per-member history, committed to the repo |
|
|
51
|
+
| **Rules & memory** | Task list persists per session, holds ephemeral work items | `decisions.md` (append-only decision log) + `directives.md` (standing rules), injected into every session |
|
|
52
|
+
| **Governance** | Permission modes and hook *capability* | Enforced policy content: file-write guard, PII scrub, reviewer lockout, bounded idle nudge — emitted as working hooks |
|
|
53
|
+
| **Unattended work** | — | Reeve: a schedulable issue watch with hard cost/turn/time ceilings |
|
|
54
|
+
|
|
55
|
+
Compared to its prior art, [Squad](https://github.com/bradygaster/squad) (which pioneered this model for GitHub Copilot CLI): Troupe is Python-native, targets Claude Code, and leans on Agent Teams for all orchestration instead of shipping its own coordinator. Compared to orchestrators like Gas Town or Multiclaude, Troupe doesn't compete on spawn mechanics at all — it's the persistence and governance layer underneath whatever does the orchestrating.
|
|
56
|
+
|
|
57
|
+
Works with the Agent Teams flag on (cast members become teammate types); degrades gracefully to plain subagents when it's off. Both paths use the same `.claude/agents/` definitions.
|
|
58
|
+
|
|
59
|
+
## Quick start
|
|
60
|
+
|
|
61
|
+
Requirements: Python 3.11+, [uv](https://docs.astral.sh/uv/) (or pip), Claude Code. `gh` CLI only if you use Reeve.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
cd your-project
|
|
65
|
+
uvx troupe init # default cast: lead, backend, frontend, tester
|
|
66
|
+
uvx troupe init --roles lead,backend,frontend,tester,security,devops,docs
|
|
67
|
+
git add .troupe .claude && git commit -m "cast the troupe"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Then open Claude Code in the project. The `SessionStart` hook injects the roster, standing rules, and recent decisions into every session automatically. Spawn cast members as subagents (or, with `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`, as teammates) by their agent type:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
Spawn a teammate using the mason agent type to build the API endpoints,
|
|
74
|
+
and sawyer to write tests for them.
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Check or repair a setup any time:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
uvx troupe doctor # diagnoses scaffold, hooks, wiring, environment
|
|
81
|
+
uvx troupe upgrade # refreshes troupe-owned files; never touches team state
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## What gets created
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
.troupe/
|
|
88
|
+
├── team.md # roster
|
|
89
|
+
├── decisions.md # append-only decision log (auto-fed by hook)
|
|
90
|
+
├── directives.md # standing rules, edit in place
|
|
91
|
+
├── policy.json # governance policy: protected paths, PII, gates
|
|
92
|
+
├── config.json · casting-state.json
|
|
93
|
+
└── agents/{name}/
|
|
94
|
+
├── charter.md # role definition — yours to edit
|
|
95
|
+
└── history.md # accumulated knowledge — the agent appends
|
|
96
|
+
.claude/
|
|
97
|
+
├── settings.json # hook wiring (merged non-destructively)
|
|
98
|
+
├── hooks/ # six self-contained governance scripts (stdlib-only)
|
|
99
|
+
└── agents/{name}.md # compiled definitions: teammate types AND subagents
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Commit `.troupe/` and `.claude/`. Anyone who clones gets the team — same names, same knowledge, same rules.
|
|
103
|
+
|
|
104
|
+
### The cast
|
|
105
|
+
|
|
106
|
+
Names come from English occupational surnames, chosen so the etymology quietly maps to the role: **Wright** (master builder) leads, **Mason** (foundations) takes backend, **Webster** (weaver — of webs) takes frontend, **Sawyer** (cuts things open) tests, **Ward** (watchman) does security, **Piper** (keeps pipes flowing) does DevOps, **Page** does docs. A 24-name pool with role affinities backs larger casts; names are never reused within a project, even after a member retires.
|
|
107
|
+
|
|
108
|
+
## Governance — enforced, not suggested
|
|
109
|
+
|
|
110
|
+
`troupe init` emits six hook scripts into `.claude/hooks/` — self-contained, stdlib-only Python, so they run on any machine with no troupe install on the per-tool-call hot path:
|
|
111
|
+
|
|
112
|
+
| Hook | Event | What it enforces |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| File guard | `PreToolUse` | Blocks agent writes to protected paths (casting state, charters, policy itself, hooks, `.env*`, keys) per `policy.json` |
|
|
115
|
+
| PII scrub | `PreToolUse` | Redacts email addresses *in place* before content is written; allowlist for intentional ones |
|
|
116
|
+
| Decision log | `TaskCompleted` | Appends a structured entry to `decisions.md` for every completed task |
|
|
117
|
+
| Review gate | `TaskCompleted` | Opt-in: blocks completion until a human drops a marker in `.troupe/approvals/` — which is itself write-protected, so agents can't self-approve |
|
|
118
|
+
| Idle nudge | `TeammateIdle` | Sends idling teammates back for a final sweep — strictly bounded (2 nudges/agent/session), so no infinite keep-alive |
|
|
119
|
+
| Session context | `SessionStart` | Injects roster + directives + recent decisions into every session |
|
|
120
|
+
|
|
121
|
+
Policy lives in `.troupe/policy.json` — patterns, allowlists, and toggles are yours to edit; the file guard protects the file itself from agents.
|
|
122
|
+
|
|
123
|
+
## Reeve — the autonomous issue watch
|
|
124
|
+
|
|
125
|
+
A *reeve* was the manorial overseer: the one who made sure the estate's work actually got done. Reeve polls GitHub issues labeled `troupe` and, only when explicitly told, dispatches headless Claude Code sessions to work them.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
uvx troupe watch --once # one read-only triage cycle (cron-friendly)
|
|
129
|
+
uvx troupe watch # poll every 10 min, still read-only
|
|
130
|
+
uvx troupe watch --execute # actually work issues (costs money)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Safety model, in order of the walls you'd hit:**
|
|
134
|
+
|
|
135
|
+
- **Triage-only by default.** No `--execute` → no writes, no agent runs, no cost. Ever.
|
|
136
|
+
- **Reeve itself never writes to GitHub.** Comments happen inside the governed Claude session, under its permission rules (`acceptEdits` + a narrow `gh`/`git`-read allowlist). `--skip-permissions` exists but is refused without `--execute`.
|
|
137
|
+
- **Governance stays on during unattended work.** Runs are non-bare and pass `--settings` explicitly, so the file guard and PII scrub fire exactly when nobody's watching.
|
|
138
|
+
- **Three independent ceilings per run**: `--max-turns` (30), `--max-budget-usd` (native cost cap), and `--timeout-minutes` (30, hard wall-clock kill for hangs).
|
|
139
|
+
- **Two accumulating ceilings**: `--max-cost-per-cycle` ($2) and `--max-cost-per-day` ($10), tracked from the JSON output's `total_cost_usd`.
|
|
140
|
+
- **Per-issue backoff**: a failing issue cools down 2 cycles per failure and escalates to humans after 3 failures (`--reset-backoff` clears the ledger).
|
|
141
|
+
- **Clean shutdown**: `touch .troupe/reeve-stop` — Reeve finishes the cycle and exits. The sentinel is write-protected from agents; only you can stop the overseer.
|
|
142
|
+
|
|
143
|
+
Run it from cron, a systemd timer, or Task Scheduler with `--once`. **Point it at a throwaway repo first.**
|
|
144
|
+
|
|
145
|
+
## Upgrading
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
uv tool upgrade troupe # or: pip install -U troupe
|
|
149
|
+
uvx troupe upgrade # refresh hook scripts, agent definitions, policy sections
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`troupe upgrade` never touches team state (charters, histories, decisions, directives, casting) and never modifies policy keys you've edited — it only adds missing sections.
|
|
153
|
+
|
|
154
|
+
## Development
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
git clone https://github.com/KevinIssaDev/troupe && cd troupe
|
|
158
|
+
uv sync --dev
|
|
159
|
+
uv run pytest # 86 tests; gh and claude are stubbed throughout
|
|
160
|
+
uv run ruff check . && uv run pyright
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
CI runs the suite on Ubuntu, macOS, and Windows (cross-platform is a first-class concern — paths via `pathlib`, subprocess in list form, no shell strings). Releases publish to PyPI via Trusted Publishing on version tags.
|
|
164
|
+
|
|
165
|
+
## License
|
|
166
|
+
|
|
167
|
+
MIT — see [LICENSE](LICENSE). Squad (MIT, by [@bradygaster](https://github.com/bradygaster)) is gratefully acknowledged as prior art for the architecture and conventions; Troupe shares no code, name, or cast with it.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Cadre — a persistent, governed AI team for Claude Code
|
|
2
|
+
|
|
3
|
+
**Status:** pre-implementation planning document
|
|
4
|
+
**Working name:** Cadre (placeholder — rename freely; avoid "Squad"/"Team" for trademark/collision reasons)
|
|
5
|
+
**Author:** Kevin, with Claude (Anthropic) assisting on design
|
|
6
|
+
**Reference implementation (prior art, MIT licensed, Node/TypeScript):** local clone at `E:\squad` — https://github.com/bradygaster/squad
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. What this is
|
|
11
|
+
|
|
12
|
+
Cadre gives a Claude Code user a **persistent, named AI team that lives in their repo as files** — a roster of specialists (lead, frontend, backend, tester, etc.) with real names, individual charters, a shared architectural decision log, enforced governance rules, and (optionally) an autonomous loop that triages GitHub issues overnight.
|
|
13
|
+
|
|
14
|
+
It is a Python-native, PyPI-packaged CLI + hook set for **Claude Code**, directly analogous to what `squad` (bradygaster/squad) built for **GitHub Copilot CLI**.
|
|
15
|
+
|
|
16
|
+
## 2. What this explicitly is NOT
|
|
17
|
+
|
|
18
|
+
Do not rebuild multi-agent orchestration. Claude Code already ships this natively as **Agent Teams** (experimental, flag `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS`): a team lead, independent teammates each with their own context window, a shared task list, and direct mailbox messaging between agents. There are also at least two existing third-party orchestrators built on top of it (Gas Town, Multiclaude) plus a large cross-harness plugin marketplace (wshobson/agents).
|
|
19
|
+
|
|
20
|
+
**Non-goals:**
|
|
21
|
+
- Do not write a custom task-list/mailbox/parallel-spawn engine. Use Agent Teams for that.
|
|
22
|
+
- Do not try to out-feature Gas Town/Multiclaude on raw orchestration mechanics.
|
|
23
|
+
- Do not port Squad's Node code line-for-line. Squad is prior art for *architecture and conventions*, not a codebase to translate.
|
|
24
|
+
|
|
25
|
+
**The actual gap Cadre fills** (confirmed not covered by Agent Teams or the other orchestrators as of this writing):
|
|
26
|
+
1. A **persistent named roster** that survives across sessions *and* across projects (a thematic casting/naming system), rather than anonymous "teammate-1"-style instances.
|
|
27
|
+
2. A **governance layer with real enforcement** — file-write guards, PII scrubbing, reviewer lockout — implemented as actual Claude Code hooks, not just instructions in a prompt.
|
|
28
|
+
3. A **shared decisions/directives log** (`decisions.md`, `directives.md`) that persists architectural choices and permanent team rules across sessions, distinct from the ephemeral task list Agent Teams already provides.
|
|
29
|
+
4. **Ralph** — an autonomous, schedulable loop that polls GitHub issues, builds context, invokes Claude Code headlessly, and applies tiered escalation/backoff — for unattended overnight work.
|
|
30
|
+
|
|
31
|
+
If, during planning, you find Agent Teams already covers #3 adequately (e.g. its task list already persists per-team at `~/.claude/tasks/{team-name}/` in a way that's good enough), say so and shrink scope rather than building redundant machinery.
|
|
32
|
+
|
|
33
|
+
## 3. Reference material to study first
|
|
34
|
+
|
|
35
|
+
Before writing any code, read through `E:\squad` (already added as a working directory) for:
|
|
36
|
+
- `README.md` (root and `dev` branch) — full command surface, `.squad/` directory layout, `squad.config.ts` SDK-first mode
|
|
37
|
+
- `packages/squad-cli` — CLI structure, `init`/`watch`/`doctor`/`upgrade` command implementations
|
|
38
|
+
- `packages/squad-sdk` — hook pipeline design (file-write guards, PII scrubbing, reviewer lockout, event-driven monitoring)
|
|
39
|
+
- `.github/agents/squad.agent.md` (generated by `squad init` if you run it in a scratch dir) — the coordinator persona/governance prompt
|
|
40
|
+
- Docs site content (`bradygaster.github.io/squad` if mirrored, or `docs/` in the repo) — casting system, ceremonies, skills packaging, Ralph's escalation tiers and state backends (`git-notes`, `orphan-branch`)
|
|
41
|
+
|
|
42
|
+
Treat this as **architectural reference only**. Squad is MIT-licensed so borrowing concepts and even file-naming conventions is fine; do not copy verbatim text/code, and do not reuse Squad's name, mascots, or branding.
|
|
43
|
+
|
|
44
|
+
Also read current Anthropic documentation before implementing anything hook- or Agent-Teams-related, since this is a fast-moving experimental feature:
|
|
45
|
+
- `https://code.claude.com/docs/en/agent-teams` — Agent Teams architecture, hook events (`TeammateIdle`, `TaskCreated`, `TaskCompleted`), limitations
|
|
46
|
+
- `https://docs.claude.com` and `https://support.claude.com` — hooks reference, skills/plugins packaging, MCP configuration (`.mcp.json`)
|
|
47
|
+
|
|
48
|
+
Do not assume specifics (minimum model version, exact flag behavior, session-resume support) from memory or from third-party blog posts — verify against the official docs above, since this feature has changed multiple times in recent months.
|
|
49
|
+
|
|
50
|
+
## 4. Target platform assumptions
|
|
51
|
+
|
|
52
|
+
- Claude Code, with **Agent Teams** enabled (`CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS`) as the orchestration substrate.
|
|
53
|
+
- Claude Code **hooks** (`.claude/settings.json`) as the enforcement substrate — `PreToolUse`, `TaskCreated`, `TaskCompleted`, `TeammateIdle` at minimum.
|
|
54
|
+
- Claude Code **skills** (`~/.claude/skills/` or project-local) for reusable team knowledge, mirroring Squad's `.copilot/skills/`.
|
|
55
|
+
- Optional: project-scoped MCP config (`.mcp.json`) if a task genuinely needs a stateful tool server rather than a file + hook. Default to files + hooks first; only reach for an MCP server if file-based state proves insufficient during implementation.
|
|
56
|
+
- This is an experimental Claude Code feature. Build with a fallback path in mind: if Agent Teams is unavailable/disabled, Cadre should degrade gracefully to plain Claude Code **subagents** (Task tool) for parallel work, even without teammate-to-teammate messaging.
|
|
57
|
+
|
|
58
|
+
## 5. Tech stack
|
|
59
|
+
|
|
60
|
+
- **Language:** Python 3.11+
|
|
61
|
+
- **CLI framework:** Typer (preferred) or Click
|
|
62
|
+
- **Packaging:** `pyproject.toml`, PEP 621 metadata, `hatchling` build backend
|
|
63
|
+
- **Dev workflow / zero-install run:** `uv` — `uvx cadre init` should work with no pre-install, same ergonomics as `npx @bradygaster/squad-cli init`
|
|
64
|
+
- **Templates:** shipped as package data, extracted via `importlib.resources`
|
|
65
|
+
- **GitHub integration (for Ralph):** `PyGithub`, or shelling out to the `gh` CLI — decide during implementation based on which gives cleaner auth handling
|
|
66
|
+
- **Testing:** `pytest`, plus an end-to-end test that runs `cadre init` into a temp dir and asserts the resulting file tree (mirrors Squad's own `doctor` self-check)
|
|
67
|
+
- **Lint/type-check:** `ruff`, `pyright` (or `mypy`)
|
|
68
|
+
- **CI/CD:** GitHub Actions — lint + type-check + test matrix across ubuntu/macos/windows (Squad's own changelog has multiple Windows-escaping bugs — treat cross-platform as a first-class concern, not an afterthought; always use `pathlib` and list-form `subprocess` args, never `shell=True` string concatenation)
|
|
69
|
+
- **Release:** PyPI via **Trusted Publishers** (GitHub Actions OIDC — no long-lived API tokens)
|
|
70
|
+
- **Discoverability inside Claude Code:** a `plugin.json`/manifest at repo root so Cadre is installable through Claude Code's own plugin mechanism, thinly wrapping the same `cadre` CLI commands
|
|
71
|
+
|
|
72
|
+
## 6. Proposed repo layout (the tool's own source)
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
cadre/
|
|
76
|
+
├── pyproject.toml
|
|
77
|
+
├── README.md
|
|
78
|
+
├── LICENSE (MIT, matching Squad's license choice)
|
|
79
|
+
├── src/cadre/
|
|
80
|
+
│ ├── cli.py # Typer app, subcommand registration
|
|
81
|
+
│ ├── commands/
|
|
82
|
+
│ │ ├── init.py # scaffolds .cadre/ in target repo
|
|
83
|
+
│ │ ├── watch.py # Ralph: the polling/triage loop
|
|
84
|
+
│ │ ├── doctor.py # health check, mirrors `squad doctor`
|
|
85
|
+
│ │ └── upgrade.py # refreshes templates without touching state
|
|
86
|
+
│ ├── casting/
|
|
87
|
+
│ │ ├── registry.py # persistent name-pool logic
|
|
88
|
+
│ │ └── names.json # thematic name pool (own theme, not Squad's)
|
|
89
|
+
│ ├── governance/
|
|
90
|
+
│ │ ├── file_guard.py # PreToolUse hook: blocked paths/patterns
|
|
91
|
+
│ │ ├── pii_scrub.py # scans content before write
|
|
92
|
+
│ │ └── reviewer_lockout.py # enforces human-approval gates
|
|
93
|
+
│ ├── decisions/
|
|
94
|
+
│ │ └── log.py # append/rotate decisions.md, directives.md
|
|
95
|
+
│ ├── ralph/
|
|
96
|
+
│ │ ├── poller.py # GitHub issue polling
|
|
97
|
+
│ │ ├── context.py # builds the work-context prompt scaffold
|
|
98
|
+
│ │ ├── runner.py # headless `claude -p` invocation
|
|
99
|
+
│ │ └── state_backend.py # in-memory / git-notes / orphan-branch
|
|
100
|
+
│ └── templates/ # package data: charter.md, team.md, etc.
|
|
101
|
+
├── tests/
|
|
102
|
+
└── .github/workflows/ci.yml, release.yml
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## 7. Proposed scaffolded output (what `cadre init` creates in a user's project)
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
.cadre/
|
|
109
|
+
├── team.md # roster: names, roles
|
|
110
|
+
├── decisions.md # append-only architectural decision log
|
|
111
|
+
├── directives.md # permanent team rules
|
|
112
|
+
├── casting-state.json # this project's assigned names/theme
|
|
113
|
+
├── config.json
|
|
114
|
+
├── agents/
|
|
115
|
+
│ └── <name>/
|
|
116
|
+
│ ├── charter.md # role definition, expertise, tools
|
|
117
|
+
│ └── history.md # accumulated knowledge
|
|
118
|
+
└── skills/ # optional reusable knowledge files
|
|
119
|
+
.claude/
|
|
120
|
+
├── settings.json # wires up hooks (file guard, PII scrub, decision logging)
|
|
121
|
+
└── agents/ # optional subagent fallback definitions
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## 8. Governance hooks — mapped to real Claude Code hook events
|
|
125
|
+
|
|
126
|
+
| Cadre concern | Claude Code hook | Behavior |
|
|
127
|
+
|---|---|---|
|
|
128
|
+
| File-write guard | `PreToolUse` on write-capable tools | Exit non-zero / code 2 to block writes to protected paths |
|
|
129
|
+
| PII scrubbing | `PreToolUse` | Scan content about to be written; block or redact |
|
|
130
|
+
| Reviewer lockout | `TaskCompleted` | Exit code 2 to prevent completion until a human-approval marker is present |
|
|
131
|
+
| Decision logging | `TaskCompleted` | Append a structured entry to `.cadre/decisions.md` |
|
|
132
|
+
| Idle nudge / anti-stall | `TeammateIdle` | Exit code 2 with feedback to keep a teammate working, mirroring Squad's "escalation" ethos |
|
|
133
|
+
|
|
134
|
+
Verify exact hook payload shapes and exit-code semantics against current docs before implementing — these have changed across Claude Code versions.
|
|
135
|
+
|
|
136
|
+
## 9. Ralph (autonomous watch loop) — design sketch
|
|
137
|
+
|
|
138
|
+
- Polls GitHub issues on an interval (configurable), similar to `squad watch --execute --interval N`
|
|
139
|
+
- Builds a "work context" prompt: prioritized issue list + relevant decision-log excerpts, mirroring Squad's context scaffold
|
|
140
|
+
- Invokes Claude Code **headlessly** (`claude -p "<prompt>" --output-format json`) rather than reimplementing an agent loop
|
|
141
|
+
- Tiered escalation/backoff on repeated failures (avoid infinite retry storms against the same issue)
|
|
142
|
+
- Pluggable state backend: start with a simple local state file/SQLite; consider `git-notes` or an orphan branch later if cross-machine durability matters
|
|
143
|
+
- A stop sentinel file (e.g. `.cadre/ralph-stop`) for clean shutdown, mirroring Squad's pattern
|
|
144
|
+
- Should be runnable standalone as a scheduled task/cron/systemd timer/GitHub Action — do not assume the user is watching a terminal
|
|
145
|
+
|
|
146
|
+
## 10. Suggested build order
|
|
147
|
+
|
|
148
|
+
1. **M0** — repo scaffolding, `pyproject.toml`, CI skeleton, license, empty `cadre --version`
|
|
149
|
+
2. **M1** — `cadre init`: `.cadre/` + `.claude/` directory generation, charter templates, casting/naming
|
|
150
|
+
3. **M2** — governance hooks: file guard + decision logging (the two with clearest, testable behavior)
|
|
151
|
+
4. **M3** — remaining hooks: PII scrub, reviewer lockout, idle nudge
|
|
152
|
+
5. **M4** — `cadre doctor` health check
|
|
153
|
+
6. **M5** — Ralph: polling loop, headless invocation, one state backend, stop sentinel
|
|
154
|
+
7. **M6** — packaging polish: `uvx` zero-install path, Claude Code plugin manifest, PyPI trusted-publisher release workflow
|
|
155
|
+
8. **M7** — docs (README, quickstart, comparison table vs. Agent Teams/Gas Town/Multiclaude), initial public release
|
|
156
|
+
|
|
157
|
+
## 11. Open decisions (flag these back to the human, don't guess silently)
|
|
158
|
+
|
|
159
|
+
- Final project name (avoid collision with Squad, Gas Town, Multiclaude)
|
|
160
|
+
- License (MIT recommended, matching the ecosystem norm and the reference project)
|
|
161
|
+
- Whether Ralph auth uses a GitHub App or a personal access token by default
|
|
162
|
+
- Whether to require Agent Teams' experimental flag as a hard dependency, or ship a subagent-only fallback mode from day one
|
|
163
|
+
- Naming theme for the casting/name pool (pick something distinct from Squad's)
|
|
164
|
+
|
|
165
|
+
## 12. Definition of done for v1
|
|
166
|
+
|
|
167
|
+
- `uvx cadre init` scaffolds a working `.cadre/` + `.claude/settings.json` in under 10 seconds
|
|
168
|
+
- At least one governance hook (file guard) demonstrably blocks a disallowed write in a test
|
|
169
|
+
- `decisions.md` accumulates entries automatically after a completed task, without manual prompting
|
|
170
|
+
- Ralph can run one full poll → context-build → headless-invoke → comment-back cycle against a real test repo
|
|
171
|
+
- CI green on ubuntu/macos/windows
|
|
172
|
+
- Published on PyPI, installable and documented for a stranger with no prior context
|