claude-tempo 0.22.0 → 0.22.1
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.
- package/CLAUDE.md +3 -6
- package/README.md +98 -752
- package/dist/tui/client.js +1 -1
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -96,6 +96,8 @@ src/
|
|
|
96
96
|
│ │ ├── Picker.tsx # Full-screen interactive picker (players, ensembles)
|
|
97
97
|
│ │ ├── PlayerDetailView.tsx # Player metadata + scrollable message history (zero Yoga nodes)
|
|
98
98
|
│ │ ├── StatusOverlay.tsx # Dismissible overlay showing ensemble player cards (/status)
|
|
99
|
+
│ │ ├── CommandOverlay.tsx # Generic dismissible overlay for data-display commands (/gates, /stages, /recall, /search)
|
|
100
|
+
│ │ ├── ScheduleOverlay.tsx # Dismissible overlay showing active schedules with timing details (/schedule)
|
|
99
101
|
│ │ ├── ConversationStream.tsx # Live message area merging server conversation + optimistic echo
|
|
100
102
|
│ │ ├── CreateEnsembleWizard.tsx # Step-by-step wizard for creating new ensembles (name → workDir → lineup → confirm)
|
|
101
103
|
│ │ ├── ScheduleWizard.tsx # Step-by-step wizard for /schedule create
|
|
@@ -168,7 +170,7 @@ npm test
|
|
|
168
170
|
- **Quality Gate**: A named checklist of criteria a conductor tracks to verify a task is complete. Created via `quality_gate` (conductor only), evaluated via `evaluate_gate`, and listed via `gates`. Each criterion has a `pending` → `passed` | `failed` status; the gate's aggregate status is derived automatically (all passed → `passed`, any failed → `failed`, else `open`). Gates are stored in the conductor workflow and survive `continueAsNew`.
|
|
169
171
|
- **Worktree**: A git worktree provisioned by the conductor for a player, giving them an isolated checkout on a separate branch. Managed via the `worktree` tool (conductor only): `create` provisions the worktree and notifies the player, `remove` cleans up after the task, `list` shows all active worktrees. Worktree assignments are stored in the conductor workflow (`WorktreeEntry` records: player, path, branch, gitRoot, createdAt, createdBy).
|
|
170
172
|
- **Stage**: A fan-out/fan-in tracking primitive for the conductor. Created via `stage` (conductor only), listing via `stages`, cancelled via `cancel_stage`. Each stage tracks a set of players; when a tracked player sends a `report`, their stage status updates automatically (`waiting` → `reported` or `blocked`). When all players have reported, the conductor is notified that the stage is complete. If `failurePolicy` is `'halt'` (default), a blocker from any player fails the entire stage. Stages are stored in the conductor workflow and survive `continueAsNew`.
|
|
171
|
-
- **Maestro**: Two Maestro workflow variants exist. The **per-ensemble** `claudeMaestroWorkflow` (ID: `claude-maestro-{ensemble}`) monitors a single ensemble — maintains a player snapshot, ring-buffer event log (max 200 entries), an aggregated ensemble chat cache (max 500 entries, refreshed every ~10s via `fetchEnsembleChat` activity), and queues commands for relay to the conductor via `maestroSendCommand`. The ensemble chat cache merges maestro + conductor traffic and is served via the `maestroEnsembleChat` query. The **global** `claudeGlobalMaestroWorkflow` (ID: `claude-maestro-global`) spans all ensembles — aggregates players by ensemble, maintains a cross-ensemble message ring buffer (max 500 entries), and exposes on-demand player/conductor history via `maestroFetchPlayerMessages` and `maestroFetchConductorHistory` updates.
|
|
173
|
+
- **Maestro**: Two Maestro workflow variants exist. The **per-ensemble** `claudeMaestroWorkflow` (ID: `claude-maestro-{ensemble}`) monitors a single ensemble — maintains a player snapshot, ring-buffer event log (max 200 entries), an aggregated ensemble chat cache (max 500 entries, refreshed every ~10s via `fetchEnsembleChat` activity), and queues commands for relay to the conductor via `maestroSendCommand`. The ensemble chat cache merges maestro + conductor traffic and is served via the `maestroEnsembleChat` query. The **global** `claudeGlobalMaestroWorkflow` (ID: `claude-maestro-global`) spans all ensembles — aggregates players by ensemble, maintains a cross-ensemble message ring buffer (max 500 entries), and exposes on-demand player/conductor history via `maestroFetchPlayerMessages` and `maestroFetchConductorHistory` updates. Both are implemented in `src/workflows/maestro.ts` with activities in `src/activities/maestro.ts`.
|
|
172
174
|
- **TempoClient**: The TUI's API layer (`src/tui/client.ts`) — a TypeScript interface and implementation that wraps Temporal queries to the Maestro and conductor workflows. Provides `discoverEnsembles`, `getPlayers`, `getMessages`, `getConductorHistory`, `sendMessage`, `sendCommand`, `getEnsembleChat`, `getGates`, `getStages`, `getWorktrees`, and `terminatePlayer`. Uses Global Maestro as the primary source with graceful fallback to per-ensemble Maestro and direct workflow list queries.
|
|
173
175
|
- **Wire protocol**: All Temporal signal, query, update, and workflow names are documented in [`docs/WIRE-PROTOCOL.md`](docs/WIRE-PROTOCOL.md). These names are stable as of v0.10 — renaming or removing any is a breaking change requiring a major version bump.
|
|
174
176
|
- **Daemon**: A standalone background process (`src/daemon.ts`) that runs all Temporal workers. Auto-started by any claude-tempo command if not already running. PID stored at `~/.claude-tempo/daemon.pid`; logs at `~/.claude-tempo/daemon.log`. Sessions are now pure MCP clients — they no longer run in-process workers. Managed via `claude-tempo daemon start|stop|status|logs`.
|
|
@@ -196,11 +198,6 @@ Hard-won lessons from debugging input lag in the TUI (#58). Apply these whenever
|
|
|
196
198
|
- **Debugging approach**: When diagnosing Ink lag, create minimal test apps (`.mjs`) adding one factor at a time (fullscreen, Temporal, InkProvider, real components) to isolate the cause. If the minimal app is fast but the real app is slow, the component tree is the culprit — not the infrastructure.
|
|
197
199
|
- **Cap live message counts**: ChatView and similar message lists must limit visible messages (~20). Rendering hundreds of messages in the live Yoga tree creates 1000+ React elements that slow reconciliation and output generation. Show a "↑ N earlier messages" indicator when truncated. Future: adopt Ink's `<Static>` pattern (render-once, exit Yoga tree) like Claude Code does for scroll history.
|
|
198
200
|
|
|
199
|
-
## Dashboard
|
|
200
|
-
|
|
201
|
-
The ensemble dashboard (Maestro) lives in a separate repository: [vinceblank/maestro](https://github.com/vinceblank/maestro)
|
|
202
|
-
|
|
203
|
-
It provides a web UI for managing ensembles, communicating with conductors, and monitoring player activity.
|
|
204
201
|
|
|
205
202
|
## Commit Convention
|
|
206
203
|
|
package/README.md
CHANGED
|
@@ -16,23 +16,27 @@
|
|
|
16
16
|
|
|
17
17
|
Multiple Claude Code sessions discover each other, exchange messages in real time, and coordinate work — across machines, not just localhost.
|
|
18
18
|
|
|
19
|
-
Each
|
|
19
|
+
Each session registers as a **player** in Temporal. Players discover each other with `ensemble`, send messages with `cue`, and coordinate via a **conductor** that connects to external interfaces like Discord, Telegram, or the built-in TUI.
|
|
20
|
+
|
|
21
|
+
📖 **[Full documentation](docs/README.md)**
|
|
20
22
|
|
|
21
23
|
## Why claude-tempo?
|
|
22
24
|
|
|
23
|
-
- **Crash-safe durability** — Sessions are Temporal workflows. Crashes, restarts, and network blips don't lose messages or drop coordination state.
|
|
25
|
+
- **Crash-safe durability** — Sessions are Temporal workflows. Crashes, restarts, and network blips don't lose messages or drop coordination state.
|
|
24
26
|
- **Instant signaling** — Temporal signals deliver messages with no polling. Players receive cues the moment they're sent, regardless of which machine they're on.
|
|
25
|
-
- **Built-in scheduling** —
|
|
26
|
-
- **Extensible agent types** — Define reusable player roles as `.md` files. Ship lineups that assemble entire teams in one command.
|
|
27
|
+
- **Built-in scheduling** — One-shot and recurring message schedules without any external infrastructure.
|
|
28
|
+
- **Extensible agent types** — Define reusable player roles as `.md` files. Ship lineups that assemble entire teams in one command.
|
|
27
29
|
|
|
28
30
|
## Features
|
|
29
31
|
|
|
30
32
|
| | |
|
|
31
33
|
|---|---|
|
|
32
|
-
| 🔁 **Ensemble Lineups** | YAML configs that define a full team
|
|
33
|
-
| ⏰ **Scheduling** | One-shot and recurring message schedules with fan-out
|
|
34
|
-
| 🎭 **Player Types** | Reusable agent definitions
|
|
34
|
+
| 🔁 **Ensemble Lineups** | YAML configs that define a full team and recruit them all in one command |
|
|
35
|
+
| ⏰ **Scheduling** | One-shot and recurring message schedules with fan-out and failure notifications |
|
|
36
|
+
| 🎭 **Player Types** | Reusable agent definitions with 8 shipped types and three-tier lookup |
|
|
37
|
+
| 🖥️ **Terminal UI** | Chat-focused TUI with slash commands, overlays, and interactive wizards |
|
|
35
38
|
| 🌐 **Cross-machine** | Any session that can reach your Temporal server can join the ensemble |
|
|
39
|
+
| 🤖 **Copilot bridge** | Mix Claude Code and GitHub Copilot CLI sessions in the same ensemble |
|
|
36
40
|
|
|
37
41
|
## Installation
|
|
38
42
|
|
|
@@ -40,13 +44,9 @@ Each Claude Code session registers as a **player** in Temporal. Players discover
|
|
|
40
44
|
npm install -g claude-tempo
|
|
41
45
|
```
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- [Node.js](https://nodejs.org/) 18+
|
|
46
|
-
- [Temporal CLI](https://docs.temporal.io/cli) (for local dev server)
|
|
47
|
-
- [Claude Code](https://claude.ai/code)
|
|
47
|
+
**Prerequisites**: [Node.js](https://nodejs.org/) 18+, [Temporal CLI](https://docs.temporal.io/cli), [Claude Code](https://claude.ai/code)
|
|
48
48
|
|
|
49
|
-
## Quick
|
|
49
|
+
## Quick Start
|
|
50
50
|
|
|
51
51
|
One command handles everything:
|
|
52
52
|
|
|
@@ -55,231 +55,90 @@ cd your-project
|
|
|
55
55
|
claude-tempo up
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
This
|
|
59
|
-
|
|
60
|
-
1. Check that Temporal CLI is installed
|
|
61
|
-
2. Start the Temporal dev server (data persists in `~/.claude-tempo/`)
|
|
62
|
-
3. Register required search attributes
|
|
63
|
-
4. Register the claude-tempo MCP server (globally by default)
|
|
64
|
-
5. Start the worker daemon in the background
|
|
65
|
-
6. Launch a conductor session in a new terminal window
|
|
66
|
-
|
|
67
|
-
Then add players:
|
|
58
|
+
This starts Temporal, registers the MCP server, launches the daemon, and opens a conductor session. Then add players:
|
|
68
59
|
|
|
69
60
|
```bash
|
|
70
61
|
claude-tempo start # open a player session
|
|
71
62
|
claude-tempo status # see who's active
|
|
72
63
|
```
|
|
73
64
|
|
|
74
|
-
Or ask the conductor to `recruit` players
|
|
65
|
+
Or ask the conductor to `recruit` players from inside Claude Code.
|
|
75
66
|
|
|
76
67
|
### Manual setup
|
|
77
68
|
|
|
78
|
-
For more control, run each step individually:
|
|
79
|
-
|
|
80
69
|
```bash
|
|
81
|
-
#
|
|
82
|
-
claude-tempo server
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
claude-tempo init
|
|
87
|
-
|
|
88
|
-
# Verify everything is ready
|
|
89
|
-
claude-tempo preflight
|
|
90
|
-
|
|
91
|
-
# Start a conductor
|
|
92
|
-
claude-tempo conduct
|
|
93
|
-
|
|
94
|
-
# Add players
|
|
95
|
-
claude-tempo start
|
|
70
|
+
claude-tempo server # start Temporal dev server
|
|
71
|
+
claude-tempo init # register MCP server globally
|
|
72
|
+
claude-tempo preflight # verify environment
|
|
73
|
+
claude-tempo conduct # start a conductor
|
|
74
|
+
claude-tempo start # start a player
|
|
96
75
|
```
|
|
97
76
|
|
|
98
77
|
## Upgrading
|
|
99
78
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
1. **Stop everything:**
|
|
105
|
-
|
|
106
|
-
```bash
|
|
107
|
-
claude-tempo down --all
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
2. **Install the new version:**
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
npm install -g claude-tempo@latest
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
3. **Fix MCP registration (if you previously used `npx`):**
|
|
117
|
-
|
|
118
|
-
If you registered with `npx` (e.g. via `claude-tempo init` before v0.19.0):
|
|
119
|
-
|
|
120
|
-
```bash
|
|
121
|
-
# Remove old registration
|
|
122
|
-
claude mcp remove claude-tempo -s user
|
|
123
|
-
|
|
124
|
-
# Re-register with the direct binary
|
|
125
|
-
claude mcp add claude-tempo -s user -- claude-tempo-server
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
If you have a project-level `.mcp.json` with `"command": "npx"`, either delete it or change the entry:
|
|
129
|
-
|
|
130
|
-
```json
|
|
131
|
-
{ "command": "claude-tempo-server", "args": [] }
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
4. **Start fresh:**
|
|
135
|
-
|
|
136
|
-
```bash
|
|
137
|
-
claude-tempo up <ensemble>
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
The daemon starts automatically — no manual daemon management needed.
|
|
79
|
+
```bash
|
|
80
|
+
claude-tempo upgrade
|
|
81
|
+
```
|
|
141
82
|
|
|
142
|
-
|
|
83
|
+
Stops the daemon, installs the latest version, and restarts automatically. To upgrade to a specific version:
|
|
143
84
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
| Sessions not responding to messages | Run `claude-tempo daemon status` — ensure the daemon is running |
|
|
148
|
-
| `.mcp.json` keeps being recreated with `npx` | Delete `.mcp.json` and use user-level registration: `claude-tempo init` |
|
|
85
|
+
```bash
|
|
86
|
+
claude-tempo upgrade 0.22.0
|
|
87
|
+
```
|
|
149
88
|
|
|
150
89
|
---
|
|
151
90
|
|
|
152
|
-
## Core
|
|
91
|
+
## Core Concepts
|
|
153
92
|
|
|
154
93
|
- **Player** — A Claude Code session registered as a Temporal workflow
|
|
155
|
-
- **Conductor** — An optional orchestration hub
|
|
156
|
-
- **Ensemble** — A named group of players
|
|
94
|
+
- **Conductor** — An optional orchestration hub (one per ensemble); receives `report` calls and connects to external interfaces
|
|
95
|
+
- **Ensemble** — A named group of players isolated from other ensembles; defaults to `default`
|
|
157
96
|
- **Cue** — A message sent to a player by name via Temporal signal
|
|
97
|
+
- **Lineup** — A YAML file that defines a full team and recruits them in one step
|
|
98
|
+
- **Player Type** — A reusable agent definition (`.md` with YAML frontmatter) that gives a player a named role
|
|
158
99
|
|
|
159
|
-
Players in one ensemble cannot see or message players in another
|
|
100
|
+
Players in one ensemble cannot see or message players in another:
|
|
160
101
|
|
|
161
102
|
```bash
|
|
162
|
-
claude-tempo conduct frontend
|
|
163
|
-
claude-tempo start backend
|
|
164
|
-
claude-tempo conduct # conduct the "default" ensemble
|
|
103
|
+
claude-tempo conduct frontend # conduct the "frontend" ensemble
|
|
104
|
+
claude-tempo start backend # join the "backend" ensemble
|
|
165
105
|
```
|
|
166
106
|
|
|
167
|
-
## MCP
|
|
107
|
+
## MCP Tools
|
|
168
108
|
|
|
169
|
-
|
|
109
|
+
Tools available inside Claude Code sessions connected to claude-tempo:
|
|
170
110
|
|
|
171
111
|
| Tool | Description |
|
|
172
112
|
|------|-------------|
|
|
173
|
-
| `ensemble` | Discover active sessions
|
|
174
|
-
| `cue` | Send a message to a player by name
|
|
175
|
-
| `
|
|
176
|
-
| `
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `stop` | Stop a player session by name. |
|
|
181
|
-
| `schedule` | Create a one-shot or recurring schedule to cue a player. |
|
|
182
|
-
| `unschedule` | Cancel a named schedule. |
|
|
183
|
-
| `schedules` | List all active schedules. |
|
|
184
|
-
| `who_am_i` | Get your identity, role, player type, and session details. |
|
|
185
|
-
| `agent_types` | List available player types with name, description, and source. |
|
|
186
|
-
| `save_lineup` | Save the current ensemble as a YAML lineup (conductor only). |
|
|
187
|
-
| `load_lineup` | Load a lineup to recruit players and create schedules. |
|
|
188
|
-
| `broadcast` | Send a message to all active players. Optional `type` filter limits to a specific player type. |
|
|
189
|
-
| `encore` | Revive a stale player session — restarts the process and reconnects to the existing workflow with context restored. |
|
|
190
|
-
| `recall` | Read your own message history. Shows received messages by default; pass `includeSent: true` for the full timeline. |
|
|
191
|
-
| `worktree` | Manage git worktrees for player isolation. Actions: `create`, `remove`, `list`. Conductor only. |
|
|
192
|
-
| `quality_gate` | Define or replace a quality gate for a task — a named checklist of criteria that must pass. Conductor only. |
|
|
193
|
-
| `evaluate_gate` | Mark one or more criteria on a quality gate as passed or failed. Conductor only. |
|
|
194
|
-
| `gates` | List quality gates and their status. Filter by task name or status (`open`, `passed`, `failed`). Conductor only. |
|
|
195
|
-
| `stage` | Define a stage — tracks a set of players doing parallel work and auto-notifies when all report. Conductor only. |
|
|
196
|
-
| `stages` | List stages and their status. Conductor only. |
|
|
197
|
-
| `cancel_stage` | Cancel an active stage by name. Conductor only. |
|
|
198
|
-
|
|
199
|
-
## Scheduling
|
|
113
|
+
| `ensemble` | Discover active sessions |
|
|
114
|
+
| `cue` | Send a message to a player by name |
|
|
115
|
+
| `recruit` | Spawn a new Claude Code session |
|
|
116
|
+
| `report` | Send updates to the conductor |
|
|
117
|
+
| `broadcast` | Send a message to all active players |
|
|
118
|
+
| `recall` | Read your own message history |
|
|
119
|
+
| `who_am_i` | Get your identity, role, and player type |
|
|
200
120
|
|
|
201
|
-
|
|
121
|
+
📖 [Full tools reference → docs/tools.md](docs/tools.md) (includes `schedule`, `stage`, `quality_gate`, `worktree`, and all others)
|
|
202
122
|
|
|
203
|
-
|
|
204
|
-
- **`schedule`** — Create a named schedule (one-shot or recurring)
|
|
205
|
-
- **`unschedule`** — Remove a schedule by name
|
|
206
|
-
- **`schedules`** — List all active schedules
|
|
123
|
+
## CLI
|
|
207
124
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
-
|
|
213
|
-
-
|
|
214
|
-
-
|
|
215
|
-
-
|
|
216
|
-
|
|
217
|
-
- *"Show me all active schedules"*
|
|
218
|
-
|
|
219
|
-
Schedules support four timing modes — all accept optional bounds (`count` max fires, `until` end time):
|
|
220
|
-
|
|
221
|
-
| Mode | Parameter | Example |
|
|
222
|
-
|------|-----------|---------|
|
|
223
|
-
| One-shot delay | `delay` | `"10m"`, `"2h"`, `"1d"` |
|
|
224
|
-
| Fixed time | `at` | `"2026-04-03T20:00:00Z"` |
|
|
225
|
-
| Recurring interval | `every` | `"5m"`, `"1h"` |
|
|
226
|
-
| Cron expression | `cron` + optional `timezone` | `"0 9 * * 1-5"` (weekdays 9am) |
|
|
227
|
-
|
|
228
|
-
The `timezone` parameter accepts any IANA timezone (e.g. `"America/New_York"`, `"Europe/London"`). Defaults to UTC when omitted.
|
|
229
|
-
|
|
230
|
-
### How it works
|
|
231
|
-
|
|
232
|
-
- Scheduled messages arrive with a `[scheduled: name]` prefix so recipients can distinguish them from direct cues
|
|
233
|
-
- The `from` field is set to the schedule creator, so replies go to the right person
|
|
234
|
-
- If the target player is gone when a schedule fires, the creator is notified so they can re-recruit if needed. Falls back to notifying the conductor if the creator is also unavailable
|
|
235
|
-
- Messages include `isScheduled` metadata for dashboard integrations
|
|
236
|
-
- `claude-tempo status` shows active schedules alongside sessions
|
|
237
|
-
- A single durable scheduler workflow per ensemble manages all schedules using Temporal timers
|
|
238
|
-
|
|
239
|
-
## Quality Gates
|
|
240
|
-
|
|
241
|
-
Conductors can define named checklists of criteria to verify task completion. Three conductor-only tools are available: `quality_gate` (create or replace a gate), `evaluate_gate` (mark criteria as passed or failed), and `gates` (list all gates with optional filters).
|
|
242
|
-
|
|
243
|
-
### Examples
|
|
244
|
-
|
|
245
|
-
Tell your conductor things like:
|
|
246
|
-
|
|
247
|
-
- *"Set a quality gate 'pr-ready' with criteria: tests pass, no lint errors, code reviewed"*
|
|
248
|
-
- *"Mark criteria 0 and 1 on 'pr-ready' as passed"*
|
|
249
|
-
- *"Show me all open quality gates"*
|
|
250
|
-
- *"Check whether 'deploy-staging' has passed"*
|
|
251
|
-
|
|
252
|
-
### How it works
|
|
253
|
-
|
|
254
|
-
- Gate status is derived from criteria: all passed → `passed`; any failed → `failed`; otherwise `open`
|
|
255
|
-
- Gates survive `continueAsNew` for the conductor workflow's lifetime
|
|
256
|
-
|
|
257
|
-
## Pipeline Stages
|
|
258
|
-
|
|
259
|
-
Conductors can track fan-out/fan-in of parallel work using stages. Define a stage with a set of players, cue them to work, and the conductor is automatically notified when all players have reported — without polling.
|
|
260
|
-
|
|
261
|
-
Three conductor-only tools: `stage` (create a stage), `stages` (list all stages), `cancel_stage` (cancel an active stage).
|
|
262
|
-
|
|
263
|
-
### Examples
|
|
264
|
-
|
|
265
|
-
Tell your conductor things like:
|
|
266
|
-
|
|
267
|
-
- *"Create a stage called 'review' with players: critic-1, critic-2, critic-3"*
|
|
268
|
-
- *"Show me the status of all pipeline stages"*
|
|
269
|
-
- *"Cancel the 'deploy' stage"*
|
|
125
|
+
```bash
|
|
126
|
+
claude-tempo up [ensemble] # first-time setup
|
|
127
|
+
claude-tempo conduct [ensemble] # start a conductor
|
|
128
|
+
claude-tempo start [ensemble] # start a player
|
|
129
|
+
claude-tempo status [ensemble] # list active sessions
|
|
130
|
+
claude-tempo tui # open the terminal UI
|
|
131
|
+
claude-tempo daemon <sub> # manage the worker daemon
|
|
132
|
+
claude-tempo upgrade # update to latest
|
|
133
|
+
```
|
|
270
134
|
|
|
271
|
-
|
|
135
|
+
Run `claude-tempo --help` or `claude-tempo <command> --help` for all flags.
|
|
272
136
|
|
|
273
|
-
|
|
274
|
-
- When all players have reported, the conductor is notified that the stage is complete
|
|
275
|
-
- Two failure policies: `halt` (default — fail the stage on first blocker) and `continue` (keep the stage active until all players report)
|
|
276
|
-
- Stages survive `continueAsNew` for the conductor workflow's lifetime
|
|
137
|
+
📖 [Full CLI reference → docs/cli.md](docs/cli.md)
|
|
277
138
|
|
|
278
139
|
## Ensemble Lineups
|
|
279
140
|
|
|
280
|
-
Define reusable
|
|
281
|
-
|
|
282
|
-
### Example lineup
|
|
141
|
+
Define reusable team configurations as YAML files and load them in one command:
|
|
283
142
|
|
|
284
143
|
```yaml
|
|
285
144
|
name: my-project
|
|
@@ -287,75 +146,31 @@ conductor:
|
|
|
287
146
|
instructions: "Coordinate the frontend and backend teams"
|
|
288
147
|
players:
|
|
289
148
|
- name: frontend
|
|
149
|
+
type: tempo-soloist
|
|
290
150
|
workDir: /repos/my-app
|
|
291
|
-
instructions: "Build the React dashboard
|
|
151
|
+
instructions: "Build the React dashboard"
|
|
292
152
|
- name: backend
|
|
153
|
+
type: tempo-soloist
|
|
293
154
|
workDir: /repos/my-api
|
|
294
|
-
instructions: "Implement the REST endpoints
|
|
295
|
-
- name: ops
|
|
296
|
-
workDir: /repos/infra
|
|
297
|
-
agent: agents/ops-agent.md
|
|
298
|
-
instructions: "Monitor deployments and run health checks"
|
|
155
|
+
instructions: "Implement the REST endpoints"
|
|
299
156
|
schedules:
|
|
300
157
|
- name: status-check
|
|
301
|
-
message: "Report your current progress
|
|
158
|
+
message: "Report your current progress"
|
|
302
159
|
target: all
|
|
303
160
|
every: 30m
|
|
304
|
-
- name: deploy-reminder
|
|
305
|
-
message: "Check if the staging deploy succeeded"
|
|
306
|
-
target: ops
|
|
307
|
-
delay: 10m
|
|
308
161
|
```
|
|
309
162
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
1. **From the CLI** — load a lineup when starting an ensemble:
|
|
313
|
-
|
|
314
|
-
```bash
|
|
315
|
-
claude-tempo up --lineup my-lineup.yaml
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
2. **From inside a session** — use the `load_lineup` tool:
|
|
319
|
-
|
|
320
|
-
*"Load the lineup from ~/.claude-tempo/ensembles/my-project.yaml"*
|
|
321
|
-
|
|
322
|
-
3. **Save the current state** — snapshot a running ensemble as a lineup (conductor only):
|
|
323
|
-
|
|
324
|
-
*"Save this ensemble as a lineup called my-project"*
|
|
325
|
-
|
|
326
|
-
### Natural language examples
|
|
327
|
-
|
|
328
|
-
Tell your session things like:
|
|
329
|
-
|
|
330
|
-
- *"Load the my-project lineup"*
|
|
331
|
-
- *"Save this ensemble as a lineup"*
|
|
332
|
-
- *"Load the lineup from /repos/configs/team.yaml"*
|
|
333
|
-
|
|
334
|
-
### Fan-out schedules
|
|
335
|
-
|
|
336
|
-
Use `target: "all"` in a schedule to deliver a message to every active player (excluding the conductor). This is useful for periodic status checks or broadcast announcements:
|
|
337
|
-
|
|
338
|
-
- *"Schedule a message every 30 minutes to all players asking for a progress update"*
|
|
339
|
-
|
|
340
|
-
### Custom agents
|
|
341
|
-
|
|
342
|
-
The `agent` field on a player can be a path to a `.md` file that will be used as the session's system prompt via `--system-prompt`. This lets you create specialized agents with domain-specific instructions:
|
|
343
|
-
|
|
344
|
-
```yaml
|
|
345
|
-
players:
|
|
346
|
-
- name: security-reviewer
|
|
347
|
-
workDir: /repos/my-app
|
|
348
|
-
agent: agents/security-review.md
|
|
349
|
-
instructions: "Review the latest PR for security issues"
|
|
163
|
+
```bash
|
|
164
|
+
claude-tempo up --lineup my-project.yaml # load from CLI
|
|
350
165
|
```
|
|
351
166
|
|
|
352
|
-
|
|
167
|
+
Or from inside a session: *"Load the my-project lineup"*
|
|
353
168
|
|
|
354
|
-
|
|
169
|
+
📖 [Lineups, player types, and shipped examples → docs/ensembles.md](docs/ensembles.md)
|
|
355
170
|
|
|
356
|
-
|
|
171
|
+
## Player Types
|
|
357
172
|
|
|
358
|
-
Reference
|
|
173
|
+
Player types are reusable agent definitions — `.md` files with YAML frontmatter. Reference them by name in lineups:
|
|
359
174
|
|
|
360
175
|
```yaml
|
|
361
176
|
players:
|
|
@@ -365,535 +180,66 @@ players:
|
|
|
365
180
|
type: tempo-soloist
|
|
366
181
|
```
|
|
367
182
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
### Tool restrictions (`allowedTools`)
|
|
371
|
-
|
|
372
|
-
Agent type frontmatter may include an `allowedTools` array to restrict which tools the spawned session can use. When present, it is passed to the Claude Code session via `--allowedTools` and overrides any lineup-level setting.
|
|
373
|
-
|
|
374
|
-
```yaml
|
|
375
|
-
---
|
|
376
|
-
name: tempo-reviewer
|
|
377
|
-
description: Read-only code reviewer
|
|
378
|
-
allowedTools:
|
|
379
|
-
- Read
|
|
380
|
-
- Glob
|
|
381
|
-
- Grep
|
|
382
|
-
---
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
This is useful for security-sensitive roles (read-only reviewers, auditors) or to prevent specific players from making changes outside their scope. Sessions launched without a type, or with a type that omits `allowedTools`, receive no tool restrictions.
|
|
386
|
-
|
|
387
|
-
### Three-tier lookup
|
|
388
|
-
|
|
389
|
-
Player types are resolved in order (first match wins):
|
|
390
|
-
|
|
391
|
-
1. **Project** — `.claude/agents/` in the project directory
|
|
392
|
-
2. **User** — `~/.claude/agents/` in the user's home directory
|
|
393
|
-
3. **Shipped** — `examples/agents/` bundled with claude-tempo
|
|
394
|
-
|
|
395
|
-
Project and user types are resolved natively by Claude Code via `--agent <name>`. Shipped types fall back to `--system-prompt <path>`.
|
|
396
|
-
|
|
397
|
-
### Shipped player types
|
|
398
|
-
|
|
399
|
-
| Type | Description |
|
|
400
|
-
|------|-------------|
|
|
401
|
-
| `tempo-conductor` | Orchestrates the ensemble — breaks down tasks, delegates to players, tracks progress |
|
|
402
|
-
| `tempo-composer` | Software architect — designs system structure, defines interfaces, makes technology decisions |
|
|
403
|
-
| `tempo-soloist` | Senior engineer — implements features, fixes bugs, writes tests, delivers working code |
|
|
404
|
-
| `tempo-tuner` | QA engineer — designs test strategies, finds bugs, validates edge cases |
|
|
405
|
-
| `tempo-critic` | Code reviewer — evaluates changes for correctness, security, performance, maintainability |
|
|
406
|
-
| `tempo-roadie` | DevOps engineer — manages CI/CD, deployments, infrastructure, environment configuration |
|
|
407
|
-
| `tempo-improv` | Researcher and explorer — investigates unknowns, runs spikes, evaluates options |
|
|
408
|
-
| `tempo-liner` | Documentation specialist — owns README, CHANGELOG, CLAUDE.md, and PR descriptions |
|
|
409
|
-
|
|
410
|
-
### Shipped lineups
|
|
411
|
-
|
|
412
|
-
| Lineup | Description |
|
|
413
|
-
|--------|-------------|
|
|
414
|
-
| `tempo-big-band` | Full-lifecycle ensemble with all 8 player types — design, implement, test, review, and ship |
|
|
415
|
-
| `tempo-dev-team` | Feature development — conductor, composer, two soloists, and a tuner |
|
|
416
|
-
| `tempo-review-squad` | Three critics with different focus areas for thorough parallel code review |
|
|
417
|
-
| `tempo-jam-session` | Exploratory ensemble for spikes, research, and problems where the path is unclear |
|
|
418
|
-
|
|
419
|
-
### Discovery
|
|
420
|
-
|
|
421
|
-
Use the `agent_types` MCP tool inside a session or the CLI:
|
|
422
|
-
|
|
423
|
-
```bash
|
|
424
|
-
claude-tempo agent-types list # show available types
|
|
425
|
-
claude-tempo agent-types show <name> # print full definition
|
|
426
|
-
claude-tempo agent-types init # copy shipped examples to ~/.claude/agents/
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
## Conductors
|
|
430
|
-
|
|
431
|
-
A **conductor** is an optional special player that acts as an orchestration hub. Use one when you want:
|
|
432
|
-
|
|
433
|
-
- A single session coordinating work across multiple players
|
|
434
|
-
- External access to the ensemble via Discord, Telegram, or any Temporal client
|
|
435
|
-
- A central point for players to `report` progress, blockers, and questions
|
|
436
|
-
|
|
437
|
-
Without a conductor, players work fine peer-to-peer — they discover each other via `ensemble` and communicate via `cue`.
|
|
438
|
-
|
|
439
|
-
```bash
|
|
440
|
-
claude-tempo conduct # default ensemble
|
|
441
|
-
claude-tempo conduct my-project # named ensemble
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
### External access
|
|
445
|
-
|
|
446
|
-
The conductor's Temporal workflow exposes a signal/query API:
|
|
447
|
-
|
|
448
|
-
```typescript
|
|
449
|
-
import { Client } from '@temporalio/client';
|
|
450
|
-
|
|
451
|
-
const client = new Client();
|
|
452
|
-
const conductor = client.workflow.getHandle('claude-session-default-conductor');
|
|
453
|
-
|
|
454
|
-
// Send a command
|
|
455
|
-
await conductor.signal('command', {
|
|
456
|
-
text: 'recruit /repos/api and run tests',
|
|
457
|
-
source: 'cli',
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
// Check history
|
|
461
|
-
const history = await conductor.query('history');
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
Connect external channel plugins (e.g., Discord):
|
|
465
|
-
|
|
466
|
-
```bash
|
|
467
|
-
CLAUDE_TEMPO_CONDUCTOR=true claude \
|
|
468
|
-
--channels plugin:discord@claude-plugins-official \
|
|
469
|
-
--dangerously-skip-permissions --dangerously-load-development-channels server:claude-tempo
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
## Players
|
|
473
|
-
|
|
474
|
-
### Starting players
|
|
475
|
-
|
|
476
|
-
```bash
|
|
477
|
-
# Terminal 1 — conductor
|
|
478
|
-
claude-tempo conduct my-project
|
|
479
|
-
|
|
480
|
-
# Terminal 2 — frontend
|
|
481
|
-
claude-tempo start my-project -n frontend
|
|
482
|
-
|
|
483
|
-
# Terminal 3 — backend
|
|
484
|
-
claude-tempo start my-project -n backend
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
Or let the conductor `recruit` players — this spawns new terminal windows automatically.
|
|
488
|
-
|
|
489
|
-
Inside a session, try:
|
|
490
|
-
- "Show me the ensemble" — discovers other sessions
|
|
491
|
-
- "Set your name to 'frontend'" — human-readable name
|
|
492
|
-
- "Cue frontend: what are you working on?" — sends a message
|
|
493
|
-
|
|
494
|
-
### Session naming
|
|
495
|
-
|
|
496
|
-
Sessions start with a random 8-character hex ID. Set a name at launch with `-n` or use `set_name` inside a session.
|
|
497
|
-
|
|
498
|
-
- Names are stored in workflow metadata and discoverable via metadata queries. Search attributes are also set for Temporal UI visibility.
|
|
499
|
-
- Other players use names to send messages via `cue`
|
|
500
|
-
- `recruit` automatically tells new sessions to set their name
|
|
501
|
-
- Names must be unique within an ensemble
|
|
502
|
-
- Names must contain only letters, numbers, hyphens, and underscores
|
|
503
|
-
- The name "conductor" is reserved for conductor sessions
|
|
504
|
-
|
|
505
|
-
### Session status lifecycle
|
|
506
|
-
|
|
507
|
-
Each session has a status that tracks its connection state:
|
|
508
|
-
|
|
509
|
-
| Status | Meaning |
|
|
510
|
-
|--------|---------|
|
|
511
|
-
| `pending` | Workflow created by `recruit`, but the Claude Code process hasn't connected yet |
|
|
512
|
-
| `active` | Session is running and responsive |
|
|
513
|
-
| `stale` | Messages have gone undelivered for 3+ minutes — the session is likely disconnected |
|
|
514
|
-
| `blocked` | Messages are being delivered but the session has produced no outbound activity for 5+ minutes — it may be stuck or spinning |
|
|
515
|
-
|
|
516
|
-
Status transitions:
|
|
517
|
-
- **`pending` → `active`** — when the spawned session connects and sends its `updateMetadata` signal
|
|
518
|
-
- **`active` → `stale`** — when undelivered messages exceed the stale threshold (3 minutes)
|
|
519
|
-
- **`active` → `blocked`** — when delivered messages produce no outbound response for 5+ minutes; auto-recovers to `active` on next outbound activity
|
|
520
|
-
- Any status → **terminated** — on graceful shutdown or `stop`
|
|
521
|
-
|
|
522
|
-
`claude-tempo status` shows `(pending)` and `(stale)` indicators next to player names. The `ClaudeTempoStatus` search attribute is also set, so you can filter sessions by status in the Temporal UI (e.g., `ClaudeTempoStatus = "stale"`).
|
|
523
|
-
|
|
524
|
-
### Terminal support
|
|
525
|
-
|
|
526
|
-
`recruit` and the CLI detect your terminal automatically:
|
|
527
|
-
|
|
528
|
-
| Terminal | macOS | Linux | Windows |
|
|
529
|
-
|----------|-------|-------|---------|
|
|
530
|
-
| Ghostty | ✓ | — | — |
|
|
531
|
-
| iTerm2 | ✓ | — | — |
|
|
532
|
-
| Terminal.app | ✓ | — | — |
|
|
533
|
-
| gnome-terminal | — | ✓ | — |
|
|
534
|
-
| konsole / xterm | — | ✓ | — |
|
|
535
|
-
| Windows Terminal | — | — | ✓ (tabs) |
|
|
536
|
-
| cmd.exe / PowerShell | — | — | ✓ |
|
|
537
|
-
|
|
538
|
-
macOS terminals preserve the full shell environment (fish, zsh, bash) including node version managers (fnm, nvm).
|
|
539
|
-
|
|
540
|
-
Windows Terminal is detected automatically via the `WT_SESSION` environment variable. When running inside Windows Terminal, recruited sessions open as new tabs (with the player name as the tab title) instead of separate cmd.exe windows.
|
|
541
|
-
|
|
542
|
-
## CLI reference
|
|
543
|
-
|
|
544
|
-
```
|
|
545
|
-
claude-tempo <command> [options]
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
### Commands
|
|
549
|
-
|
|
550
|
-
| Command | Description |
|
|
551
|
-
|---------|-------------|
|
|
552
|
-
| `up [ensemble]` | First-time setup: start Temporal, configure MCP, launch conductor. Use `--lineup` to load a lineup. |
|
|
553
|
-
| `down` | Stop Temporal, terminate sessions, remove MCP config. Use `--keep-mcp` to preserve MCP config. |
|
|
554
|
-
| `server` | Start the Temporal dev server and register search attributes |
|
|
555
|
-
| `conduct [ensemble]` | Start a conductor session (one per ensemble). Use `--resume` or `--replace` if one exists. |
|
|
556
|
-
| `start [ensemble]` | Start a player session |
|
|
557
|
-
| `status [ensemble]` | Show active sessions and Temporal health |
|
|
558
|
-
| `config` | Configure Temporal connection settings (interactive or `set`/`show`) |
|
|
559
|
-
| `stop [ensemble]` | Stop sessions (`-n <name>` for one, `--all` for everything) |
|
|
560
|
-
| `init` | Register claude-tempo MCP server globally (`--project` for per-directory) |
|
|
561
|
-
| `preflight` | Run environment checks |
|
|
562
|
-
| `broadcast <msg>` | Send a message to all active players. Use `--type` to filter by player type, `--include-stale` to include stale sessions. |
|
|
563
|
-
| `encore <name>` | Revive a stale player session by name. Use `--host` to target a remote machine. |
|
|
564
|
-
| `ensemble <sub>` | Manage saved lineups (`save`, `list`, `show`) |
|
|
565
|
-
| `agent-types <sub>` | Manage player types (`list`, `show <name>`, `init`) |
|
|
566
|
-
| `daemon <sub>` | Manage the worker daemon (`start`, `stop`, `status`, `logs`) |
|
|
567
|
-
| `tui [--ensemble <name>]` | Launch the interactive TUI — chat-focused shell with slash commands for managing players and ensembles |
|
|
568
|
-
| `version` | Print the installed version |
|
|
569
|
-
| `help` | Show usage info |
|
|
570
|
-
|
|
571
|
-
### Global options
|
|
572
|
-
|
|
573
|
-
```
|
|
574
|
-
--temporal-address <addr> Temporal server address (default: localhost:7233)
|
|
575
|
-
--temporal-namespace <ns> Temporal namespace (default: default)
|
|
576
|
-
--temporal-api-key <key> Temporal Cloud API key
|
|
577
|
-
--temporal-tls-cert <path> mTLS client certificate path
|
|
578
|
-
--temporal-tls-key <path> mTLS client key path
|
|
579
|
-
-n, --name <name> Set the player name (start/conduct/up)
|
|
580
|
-
--agent <claude|copilot> Agent backend to use (default: claude)
|
|
581
|
-
--skip-preflight Skip preflight checks (start/conduct)
|
|
582
|
-
-d, --dir <path> Target directory (default: cwd)
|
|
583
|
-
--background Run Temporal in background (server only)
|
|
584
|
-
--keep-mcp Preserve MCP config when tearing down (down only)
|
|
585
|
-
--lineup <name|file> Load an ensemble lineup by name or file path (up only)
|
|
586
|
-
--resume Resume an existing conductor session (conduct only)
|
|
587
|
-
--replace Stop existing conductor and start fresh (conduct only)
|
|
588
|
-
-v, --version Print version and exit
|
|
589
|
-
```
|
|
590
|
-
|
|
591
|
-
### `claude-tempo up`
|
|
592
|
-
|
|
593
|
-
The recommended way to get started:
|
|
594
|
-
|
|
595
|
-
```
|
|
596
|
-
$ claude-tempo up myband
|
|
597
|
-
|
|
598
|
-
claude-tempo setup
|
|
599
|
-
✓ temporal CLI installed
|
|
600
|
-
… Starting Temporal dev server...
|
|
601
|
-
✓ Temporal started (pid 12345, data in ~/.claude-tempo/)
|
|
602
|
-
✓ Registered search attributes
|
|
603
|
-
✓ .mcp.json created
|
|
604
|
-
|
|
605
|
-
Launching conductor in ensemble myband...
|
|
606
|
-
|
|
607
|
-
✓ You're all set!
|
|
608
|
-
Conductor launched (pid 12346)
|
|
609
|
-
Ensemble: myband
|
|
610
|
-
|
|
611
|
-
What next?
|
|
612
|
-
claude-tempo start myband Add a player session
|
|
613
|
-
claude-tempo status myband See who's active
|
|
614
|
-
Or ask the conductor to recruit players for you
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
### `claude-tempo server`
|
|
618
|
-
|
|
619
|
-
Starts the Temporal dev server with automatic search attribute registration:
|
|
620
|
-
|
|
621
|
-
```bash
|
|
622
|
-
claude-tempo server # foreground (Ctrl+C to stop)
|
|
623
|
-
claude-tempo server --background # daemonize
|
|
624
|
-
```
|
|
625
|
-
|
|
626
|
-
Data persists in `~/.claude-tempo/temporal-data.db`. If Temporal is already running, registers attributes and exits.
|
|
627
|
-
|
|
628
|
-
### `claude-tempo status`
|
|
629
|
-
|
|
630
|
-
Shows all active sessions:
|
|
631
|
-
|
|
632
|
-
```
|
|
633
|
-
Ensemble: myband
|
|
634
|
-
3 active sessions
|
|
635
|
-
|
|
636
|
-
conductor (conductor)
|
|
637
|
-
Orchestrating the team
|
|
638
|
-
/Users/me/projects/app main my-machine.local
|
|
639
|
-
|
|
640
|
-
alice
|
|
641
|
-
Building the REST endpoints
|
|
642
|
-
/Users/me/projects/app feat/api my-machine.local
|
|
643
|
-
|
|
644
|
-
bob (pending)
|
|
645
|
-
Working on the dashboard
|
|
646
|
-
/Users/me/projects/app feat/ui my-machine.local
|
|
647
|
-
|
|
648
|
-
1 active schedule
|
|
649
|
-
deploy-watch → ops | every 1h | next: 3:00:00 PM
|
|
650
|
-
```
|
|
651
|
-
|
|
652
|
-
### `claude-tempo preflight`
|
|
653
|
-
|
|
654
|
-
Verifies your environment: Node.js >= 18, Temporal reachable, `claude` on PATH, `claude-tempo-server` on PATH, `.mcp.json` configured.
|
|
655
|
-
|
|
656
|
-
### `claude-tempo init`
|
|
657
|
-
|
|
658
|
-
Registers the claude-tempo MCP server globally so it's available in every Claude Code session:
|
|
183
|
+
Eight types ship out of the box: `tempo-conductor`, `tempo-composer`, `tempo-soloist`, `tempo-tuner`, `tempo-critic`, `tempo-roadie`, `tempo-improv`, `tempo-liner`. Four lineup presets are included: `tempo-big-band`, `tempo-dev-team`, `tempo-review-squad`, `tempo-jam-session`.
|
|
659
184
|
|
|
660
185
|
```bash
|
|
661
|
-
claude-tempo
|
|
662
|
-
claude-tempo init
|
|
186
|
+
claude-tempo agent-types list # discover available types
|
|
187
|
+
claude-tempo agent-types init # copy shipped types to ~/.claude/agents/
|
|
663
188
|
```
|
|
664
189
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
### `claude-tempo down`
|
|
668
|
-
|
|
669
|
-
Stops Temporal, terminates all sessions, and removes MCP config:
|
|
670
|
-
|
|
671
|
-
```bash
|
|
672
|
-
claude-tempo down # full teardown
|
|
673
|
-
claude-tempo down --keep-mcp # stop Temporal and sessions, but preserve MCP config
|
|
674
|
-
```
|
|
190
|
+
📖 [Player types deep dive → docs/ensembles.md](docs/ensembles.md)
|
|
675
191
|
|
|
676
192
|
## Configuration
|
|
677
193
|
|
|
678
|
-
Run `claude-tempo config` to save Temporal connection settings so you don't need flags or env vars every time:
|
|
679
|
-
|
|
680
|
-
```
|
|
681
|
-
$ claude-tempo config
|
|
682
|
-
|
|
683
|
-
? Temporal address (localhost:7233): my-ns.tmprl.cloud:7233
|
|
684
|
-
? Temporal namespace (default): my-ns.abc123
|
|
685
|
-
? Auth method: (None / API key / mTLS)
|
|
686
|
-
? API key: ****
|
|
687
|
-
Saved to ~/.claude-tempo/config.json
|
|
688
|
-
✓ Connected successfully
|
|
689
|
-
```
|
|
690
|
-
|
|
691
|
-
Settings are stored in `~/.claude-tempo/config.json`. You can also set values non-interactively:
|
|
692
|
-
|
|
693
194
|
```bash
|
|
694
|
-
claude-tempo config
|
|
695
|
-
claude-tempo config set temporalNamespace my-ns.abc123
|
|
696
|
-
claude-tempo config set temporalApiKey tcl_...
|
|
697
|
-
claude-tempo config show
|
|
195
|
+
claude-tempo config # interactive setup (Temporal address, namespace, API key)
|
|
698
196
|
```
|
|
699
197
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
Settings are resolved in this order (first match wins):
|
|
703
|
-
|
|
704
|
-
1. CLI flags (`--temporal-address`, `--temporal-namespace`, etc.)
|
|
705
|
-
2. Environment variables (`TEMPORAL_ADDRESS`, `TEMPORAL_NAMESPACE`, etc.)
|
|
706
|
-
3. claude-tempo config file (`~/.claude-tempo/config.json`)
|
|
707
|
-
4. Temporal CLI config (`~/.config/temporalio/temporal.yaml`) — if you've already configured the Temporal CLI, claude-tempo reads it automatically
|
|
708
|
-
5. Defaults (`localhost:7233`, `default` namespace)
|
|
198
|
+
Settings persist in `~/.claude-tempo/config.json`. Resolution order: CLI flags → env vars → config file → Temporal CLI config → defaults.
|
|
709
199
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
For Temporal Cloud, run `claude-tempo config` and provide your cloud address, namespace, and API key. Or set them as environment variables in CI:
|
|
713
|
-
|
|
714
|
-
```bash
|
|
715
|
-
export TEMPORAL_ADDRESS=my-ns.abc123.tmprl.cloud:7233
|
|
716
|
-
export TEMPORAL_NAMESPACE=my-ns.abc123
|
|
717
|
-
export TEMPORAL_API_KEY=tcl_...
|
|
718
|
-
```
|
|
719
|
-
|
|
720
|
-
## Environment variables
|
|
200
|
+
Key environment variables:
|
|
721
201
|
|
|
722
202
|
| Variable | Default | Description |
|
|
723
203
|
|----------|---------|-------------|
|
|
724
204
|
| `TEMPORAL_ADDRESS` | `localhost:7233` | Temporal server address |
|
|
725
205
|
| `TEMPORAL_NAMESPACE` | `default` | Temporal namespace |
|
|
726
206
|
| `TEMPORAL_API_KEY` | *(none)* | Temporal Cloud API key |
|
|
727
|
-
| `TEMPORAL_TLS_CERT_PATH` | *(none)* | mTLS client certificate path |
|
|
728
|
-
| `TEMPORAL_TLS_KEY_PATH` | *(none)* | mTLS client key path |
|
|
729
|
-
| `CLAUDE_TEMPO_TASK_QUEUE` | `claude-tempo` | Task queue name |
|
|
730
207
|
| `CLAUDE_TEMPO_ENSEMBLE` | `default` | Ensemble name |
|
|
731
|
-
| `CLAUDE_TEMPO_CONDUCTOR` | `false` | Enable conductor mode |
|
|
732
|
-
| `CLAUDE_TEMPO_PLAYER_NAME` | *(random hex)* | Player name on startup |
|
|
733
|
-
| `CLAUDE_TEMPO_DEFAULT_AGENT` | `claude` | Default agent type (`claude` or `copilot`) |
|
|
734
|
-
|
|
735
|
-
## Stale session cleanup
|
|
736
|
-
|
|
737
|
-
When a session crashes or closes without graceful shutdown, Temporal detects it automatically:
|
|
738
|
-
|
|
739
|
-
- If a message to a dead session remains undelivered for **3 minutes**, the workflow self-completes
|
|
740
|
-
- Before exiting, it notifies the conductor with the undelivered message so work can be reassigned
|
|
741
|
-
- Idle sessions with no pending messages are probed after 1 hour of inactivity via a heartbeat ping; if the ping goes undelivered, the session self-completes
|
|
742
|
-
|
|
743
|
-
No manual cleanup needed — `cue` a dead player and the system handles the rest.
|
|
744
|
-
|
|
745
|
-
## Copilot CLI integration (experimental)
|
|
746
208
|
|
|
747
|
-
|
|
209
|
+
📖 [Full configuration reference → docs/configuration.md](docs/configuration.md)
|
|
748
210
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
<details>
|
|
752
|
-
<summary>Setup and usage</summary>
|
|
753
|
-
|
|
754
|
-
### Prerequisites
|
|
755
|
-
|
|
756
|
-
- [GitHub Copilot CLI](https://docs.github.com/en/copilot/github-copilot-in-the-cli) installed and authenticated
|
|
757
|
-
- An active GitHub Copilot subscription
|
|
758
|
-
- Node.js 20+
|
|
759
|
-
- Install the Copilot SDK: `npm install @github/copilot-sdk`
|
|
760
|
-
|
|
761
|
-
### Starting Copilot sessions
|
|
762
|
-
|
|
763
|
-
Use `--agent copilot` with any session-launching command:
|
|
211
|
+
## Terminal UI
|
|
764
212
|
|
|
765
213
|
```bash
|
|
766
|
-
claude-tempo
|
|
767
|
-
claude-tempo
|
|
768
|
-
claude-tempo up myband --agent copilot # full setup
|
|
214
|
+
claude-tempo tui # multi-ensemble home screen
|
|
215
|
+
claude-tempo tui --ensemble my-ensemble # direct ensemble mode
|
|
769
216
|
```
|
|
770
217
|
|
|
771
|
-
|
|
218
|
+
The TUI provides a chat-focused shell for managing your ensemble:
|
|
772
219
|
|
|
773
|
-
|
|
220
|
+
- **Ensemble chat feed** — live aggregated view of conductor + player traffic; type bare text to message the conductor, `@player message` to message directly
|
|
221
|
+
- **Slash commands** — `/recruit`, `/status`, `/schedule`, `/gates`, `/stages`, `/worktree`, and more; type `/help` for the full list
|
|
222
|
+
- **Interactive overlays and wizards** — step-by-step flows for recruiting players, creating schedules, and managing ensembles
|
|
774
223
|
|
|
775
|
-
|
|
224
|
+
📖 [TUI reference → docs/dashboard.md](docs/dashboard.md)
|
|
776
225
|
|
|
777
|
-
|
|
226
|
+
## Copilot Integration
|
|
778
227
|
|
|
779
|
-
|
|
780
|
-
claude-tempo config set default-agent copilot
|
|
781
|
-
```
|
|
228
|
+
> **Experimental** — subject to breaking changes.
|
|
782
229
|
|
|
783
|
-
|
|
230
|
+
GitHub Copilot CLI sessions can join an ensemble using `--agent copilot`:
|
|
784
231
|
|
|
785
232
|
```bash
|
|
786
|
-
|
|
233
|
+
claude-tempo start myband --agent copilot -n copilot-1
|
|
787
234
|
```
|
|
788
235
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
### Model override
|
|
792
|
-
|
|
793
|
-
Set `COPILOT_BRIDGE_MODEL` to use a specific model for Copilot sessions:
|
|
794
|
-
|
|
795
|
-
```bash
|
|
796
|
-
COPILOT_BRIDGE_MODEL=gpt-4o claude-tempo start myband --agent copilot
|
|
797
|
-
```
|
|
798
|
-
|
|
799
|
-
### Limitations
|
|
800
|
-
|
|
801
|
-
- Headless only — bridge sessions respond to cues, no interactive terminal
|
|
802
|
-
- ~2-second polling latency (vs instant for Claude Code sessions)
|
|
803
|
-
- `@github/copilot-sdk` adds ~243MB to node_modules
|
|
804
|
-
- Node 20+ required (rest of claude-tempo works on Node 18+)
|
|
805
|
-
|
|
806
|
-
</details>
|
|
807
|
-
|
|
808
|
-
## TUI Dashboard
|
|
809
|
-
|
|
810
|
-
The built-in terminal UI provides a chat-focused shell for managing your ensemble without leaving the terminal.
|
|
811
|
-
|
|
812
|
-
### Launching
|
|
813
|
-
|
|
814
|
-
```bash
|
|
815
|
-
# Default — bare command launches TUI in multi-ensemble mode
|
|
816
|
-
claude-tempo
|
|
817
|
-
|
|
818
|
-
# Explicit TUI launch
|
|
819
|
-
claude-tempo tui
|
|
820
|
-
|
|
821
|
-
# Direct ensemble mode — connects straight to a named ensemble
|
|
822
|
-
claude-tempo tui --ensemble my-ensemble
|
|
823
|
-
```
|
|
824
|
-
|
|
825
|
-
### Interface
|
|
826
|
-
|
|
827
|
-
The TUI has a persistent layout:
|
|
828
|
-
|
|
829
|
-
- **TitleBar** (pinned top) — shows the current ensemble, player count, and connection state; in chat mode shows the target player and their status
|
|
830
|
-
- **Scroll area** — command output and sent messages accumulate here as scrollback history; navigate with **Page Up / Page Down / Home / End**
|
|
831
|
-
- **StatusBar** — persistent one-line summary of player counts by status, schedule count, and connection health
|
|
832
|
-
- **Live view** — aggregated ensemble chat feed (maestro + conductor traffic); bare text routes to the conductor, `@player message` routes directly to a named player
|
|
833
|
-
- **PromptArea** (pinned bottom) — type slash commands, bare text (routes to conductor), or `@player <message>` (routes to a specific player); use **↑ / ↓** to navigate persistent command history (saved to `~/.claude-tempo/tui-history.json`)
|
|
834
|
-
|
|
835
|
-
> Screenshot placeholder — will be added once the feature lands on `main`.
|
|
836
|
-
|
|
837
|
-
### Slash commands
|
|
838
|
-
|
|
839
|
-
| Command | Description |
|
|
840
|
-
|---|---|
|
|
841
|
-
| `/broadcast <message>` | Send a message to all active players across all ensembles |
|
|
842
|
-
| `/recruit [name]` | Launch the recruit wizard to spawn a new player session |
|
|
843
|
-
| `/recruit-conductor` | Recruit a conductor for the current ensemble (one-shot, no wizard) |
|
|
844
|
-
| `/stop <player>` | Terminate a player session |
|
|
845
|
-
| `/disband` | Tear down the current ensemble (all sessions + scheduler) |
|
|
846
|
-
| `/encore <player>` | Revive a stale player session |
|
|
847
|
-
| `/recall [player]` | Show recent message history (optionally filtered to one player) |
|
|
848
|
-
| `/search <term>` | Search message history across all ensembles |
|
|
849
|
-
| `/status` | Show an overlay with all players and their current status |
|
|
850
|
-
| `/player [name]` | Show detailed player info; no args opens the interactive picker |
|
|
851
|
-
| `/schedule` | List active schedules across all ensembles |
|
|
852
|
-
| `/schedule create` | Launch the interactive schedule creation wizard |
|
|
853
|
-
| `/unschedule <name>` | Cancel a named schedule |
|
|
854
|
-
| `/lineup load <file> \| save [file]` | Load or save an ensemble lineup |
|
|
855
|
-
| `/ensemble [name]` | Switch to a named ensemble; no args opens the ensemble picker with an option to create a new one |
|
|
856
|
-
| `/gates` | List quality gates and their criteria status |
|
|
857
|
-
| `/stages` | List stages and per-player report status |
|
|
858
|
-
| `/worktree [list]` | List active git worktrees |
|
|
859
|
-
| `/back` | Exit chat mode or navigate back to the ensemble list |
|
|
860
|
-
| `/help` | Show all available commands with usage |
|
|
861
|
-
| `/quit` | Exit the TUI |
|
|
862
|
-
|
|
863
|
-
In the ensemble view, bare text routes to the conductor; prefix with `@player` to message a specific player directly (e.g. `@frontend check your tests`). If no conductor is running, a prompt suggests using `@player` or `/recruit`. Press `Ctrl+C` to exit at any time.
|
|
864
|
-
|
|
865
|
-
## Maestro Dashboard
|
|
866
|
-
|
|
867
|
-
The **Maestro** workflow runs alongside the conductor, monitoring ensemble state in real time — tracking player joins/leaves, status changes, and part updates. It also accepts commands from external sources for relay to the conductor.
|
|
868
|
-
|
|
869
|
-
The [Maestro dashboard](https://github.com/vinceblank/maestro) is a web UI that connects to this workflow and provides a live view of your ensemble:
|
|
870
|
-
|
|
871
|
-
- Player list with status, part, host, and git branch
|
|
872
|
-
- Event log of recent ensemble activity
|
|
873
|
-
- Command input to interact with the conductor
|
|
874
|
-
|
|
875
|
-
The Maestro workflow starts automatically with the conductor and requires no additional setup. Connect the dashboard to your Temporal server's address and namespace to get started.
|
|
236
|
+
📖 [Copilot bridge setup and limitations → docs/copilot.md](docs/copilot.md)
|
|
876
237
|
|
|
877
238
|
## Worker Daemon
|
|
878
239
|
|
|
879
|
-
The
|
|
880
|
-
|
|
881
|
-
The daemon auto-starts the first time any claude-tempo command needs it. You can also manage it explicitly:
|
|
882
|
-
|
|
883
|
-
```bash
|
|
884
|
-
claude-tempo daemon start # start the daemon (no-op if already running)
|
|
885
|
-
claude-tempo daemon stop # stop the daemon
|
|
886
|
-
claude-tempo daemon status # show running state and PID
|
|
887
|
-
claude-tempo daemon logs # tail daemon logs
|
|
888
|
-
```
|
|
889
|
-
|
|
890
|
-
### How it works
|
|
240
|
+
The daemon runs Temporal workers as a background process — it starts automatically on first use. Manage it explicitly with `claude-tempo daemon start|stop|status|logs`.
|
|
891
241
|
|
|
892
|
-
|
|
893
|
-
- The daemon runs detached — it survives terminal closes and session restarts
|
|
894
|
-
- All Temporal worker duties (workflow execution, activity dispatch) run in the daemon
|
|
895
|
-
- Logs are written to `~/.claude-tempo/daemon.log`
|
|
896
|
-
- On Linux/macOS, the daemon is stopped via `SIGTERM`; on Windows, the process is killed directly
|
|
242
|
+
📖 [Daemon reference → docs/daemon.md](docs/daemon.md)
|
|
897
243
|
|
|
898
244
|
## Development
|
|
899
245
|
|
|
@@ -901,20 +247,20 @@ claude-tempo daemon logs # tail daemon logs
|
|
|
901
247
|
git clone https://github.com/vinceblank/claude-tempo.git
|
|
902
248
|
cd claude-tempo && npm install
|
|
903
249
|
|
|
904
|
-
npm run build
|
|
905
|
-
npm test
|
|
906
|
-
npm link
|
|
250
|
+
npm run build # compile TypeScript + pre-bundle workflows
|
|
251
|
+
npm test # run tests
|
|
252
|
+
npm link # link CLI for local testing
|
|
907
253
|
```
|
|
908
254
|
|
|
909
255
|
> **Important**: Run `npm run build` after changing workflow code (`src/workflows/`). The build pre-bundles workflows into `workflow-bundle.js` so all workers use identical code.
|
|
910
256
|
|
|
911
257
|
## Contributing
|
|
912
258
|
|
|
913
|
-
See [CLAUDE.md](CLAUDE.md) for project structure,
|
|
259
|
+
See [CLAUDE.md](CLAUDE.md) for project structure, conventions, and development setup. Pull requests welcome — run `npm test` before submitting.
|
|
914
260
|
|
|
915
|
-
## Known
|
|
261
|
+
## Known Limitations
|
|
916
262
|
|
|
917
|
-
- **`recruit` requires manual acknowledgment** — Recruited sessions
|
|
263
|
+
- **`recruit` requires manual acknowledgment** — Recruited sessions show a Claude Code confirmation prompt that must be acknowledged in the spawned terminal. This will be resolved once claude-tempo is a published approved channel plugin. Copilot bridge sessions are not affected.
|
|
918
264
|
|
|
919
265
|
## License
|
|
920
266
|
|
package/dist/tui/client.js
CHANGED
|
@@ -161,7 +161,7 @@ function createTempoClient(client) {
|
|
|
161
161
|
const query = `WorkflowType = "claudeSessionWorkflow" AND ExecutionStatus = "Running" AND ClaudeTempoEnsemble = "${sanitizeQueryValue(ensemble)}" AND ClaudeTempoPlayerId = "${sanitizeQueryValue(playerId)}"`;
|
|
162
162
|
for await (const wf of client.workflow.list({ query })) {
|
|
163
163
|
const h = handle(wf.workflowId);
|
|
164
|
-
return await h.query('
|
|
164
|
+
return await h.query('getMetadata');
|
|
165
165
|
}
|
|
166
166
|
return null;
|
|
167
167
|
}
|