claude-tempo 0.2.5-beta.1 → 0.3.0-beta.2
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/README.md +223 -240
- package/dist/cli/commands.d.ts +6 -10
- package/dist/cli/commands.js +95 -36
- package/dist/cli/config-command.d.ts +8 -0
- package/dist/cli/config-command.js +229 -0
- package/dist/cli/preflight.d.ts +3 -3
- package/dist/cli/preflight.js +8 -6
- package/dist/cli.js +37 -11
- package/dist/config.d.ts +64 -1
- package/dist/config.js +207 -4
- package/dist/connection.d.ts +7 -0
- package/dist/connection.js +39 -0
- package/dist/copilot-bridge.js +5 -3
- package/dist/server.js +2 -3
- package/dist/spawn.d.ts +4 -0
- package/dist/spawn.js +5 -0
- package/dist/tools/recruit.js +15 -2
- package/dist/worker.js +2 -3
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -1,82 +1,18 @@
|
|
|
1
1
|
# claude-tempo
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Multi-session [Claude Code](https://claude.ai/code) coordination via [Temporal](https://temporal.io).
|
|
4
4
|
|
|
5
5
|
Multiple Claude Code sessions discover each other, exchange messages in real time, and coordinate work — across machines, not just localhost.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Each Claude Code session registers as a **player** in Temporal. Players discover each other with `ensemble`, exchange messages with `cue`, and coordinate work — across machines, not just localhost. An optional **conductor** orchestrates the group and connects to external interfaces like Discord, Telegram, or a dashboard.
|
|
8
8
|
|
|
9
|
-
##
|
|
10
|
-
|
|
11
|
-
**claude-tempo** uses Temporal workflows as the coordination layer:
|
|
12
|
-
|
|
13
|
-
- Each Claude Code session registers as a **player** (a Temporal workflow)
|
|
14
|
-
- Players belong to an **ensemble** — a named group of sessions that can see and message each other
|
|
15
|
-
- Players discover each other via `ensemble`, message via `cue`, and spawn new sessions via `recruit`
|
|
16
|
-
- Players can interact directly (peer-to-peer) — no central hub required
|
|
17
|
-
- An optional **conductor** player acts as an orchestration hub for the ensemble, connected to external interfaces like Discord or Telegram
|
|
18
|
-
|
|
19
|
-
### Ensembles
|
|
20
|
-
|
|
21
|
-
An **ensemble** is an isolated group of players identified by name (e.g., `frontend`, `backend`, `default`). Players in one ensemble cannot see or message players in another — they are completely independent.
|
|
22
|
-
|
|
23
|
-
Each ensemble can have:
|
|
24
|
-
- Any number of **players** working on tasks
|
|
25
|
-
- One optional **conductor** coordinating work and connected to external interfaces
|
|
26
|
-
|
|
27
|
-
By default, all sessions join the `default` ensemble. Pass an ensemble name when starting a session to create or join a different one:
|
|
9
|
+
## Installation
|
|
28
10
|
|
|
29
11
|
```bash
|
|
30
|
-
claude-tempo
|
|
31
|
-
claude-tempo start backend # join the "backend" ensemble
|
|
32
|
-
claude-tempo conduct # conduct the "default" ensemble
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
This lets you run separate groups of sessions for different projects or concerns without interference.
|
|
36
|
-
|
|
37
|
-
```mermaid
|
|
38
|
-
graph TD
|
|
39
|
-
You["You (Discord / Telegram / CLI / Claude Code)"]
|
|
40
|
-
You -->|signal / query| Conductor
|
|
41
|
-
|
|
42
|
-
subgraph Temporal["Temporal Server"]
|
|
43
|
-
Conductor["Conductor Workflow"]
|
|
44
|
-
PA["Player A Workflow"]
|
|
45
|
-
PB["Player B Workflow"]
|
|
46
|
-
PC["Player C Workflow"]
|
|
47
|
-
Conductor -->|cue| PA
|
|
48
|
-
Conductor -->|cue| PB
|
|
49
|
-
Conductor -->|cue| PC
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
subgraph Host1["Host 1"]
|
|
53
|
-
S1["Claude Session A"]
|
|
54
|
-
S2["Claude Session B"]
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
subgraph Host2["Host 2"]
|
|
58
|
-
S3["Claude Session C"]
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
PA -.-> S1
|
|
62
|
-
PB -.-> S2
|
|
63
|
-
PC -.-> S3
|
|
12
|
+
npm install -g claude-tempo
|
|
64
13
|
```
|
|
65
14
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
| Tool | Description |
|
|
69
|
-
|------|-------------|
|
|
70
|
-
| `ensemble` | Discover active sessions in your ensemble. Scope: `machine`, `repo`, `all`. |
|
|
71
|
-
| `cue` | Send a message to any session by player name. Instant via Temporal signal. |
|
|
72
|
-
| `set_name` | Set a human-readable name for this session. Used by other players to message you. |
|
|
73
|
-
| `set_part` | Describe what you're working on. Visible to others via `ensemble`. |
|
|
74
|
-
| `listen` | Manual fallback for checking pending messages. |
|
|
75
|
-
| `recruit` | Start a named Claude Code session in a directory. Opens a new terminal window automatically. |
|
|
76
|
-
| `report` | Send updates to the conductor (surfaces to Discord/Telegram). No-op if no conductor. |
|
|
77
|
-
| `terminate` | Terminate a player session by name. Use to clean up orphaned sessions. |
|
|
78
|
-
|
|
79
|
-
## Prerequisites
|
|
15
|
+
### Prerequisites
|
|
80
16
|
|
|
81
17
|
- [Node.js](https://nodejs.org/) 18+
|
|
82
18
|
- [Temporal CLI](https://docs.temporal.io/cli) (for local dev server)
|
|
@@ -84,25 +20,22 @@ graph TD
|
|
|
84
20
|
|
|
85
21
|
## Quick start
|
|
86
22
|
|
|
87
|
-
|
|
23
|
+
One command handles everything:
|
|
88
24
|
|
|
89
25
|
```bash
|
|
90
|
-
# Install
|
|
91
|
-
npm install -g claude-tempo
|
|
92
|
-
|
|
93
|
-
# Go to your project and run `up`
|
|
94
26
|
cd your-project
|
|
95
27
|
claude-tempo up
|
|
96
28
|
```
|
|
97
29
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
30
|
+
This will:
|
|
31
|
+
|
|
32
|
+
1. Check that Temporal CLI is installed
|
|
33
|
+
2. Start the Temporal dev server (data persists in `~/.claude-tempo/`)
|
|
34
|
+
3. Register required search attributes
|
|
35
|
+
4. Create `.mcp.json` in your project
|
|
103
36
|
5. Launch a conductor session in a new terminal window
|
|
104
37
|
|
|
105
|
-
|
|
38
|
+
Then add players:
|
|
106
39
|
|
|
107
40
|
```bash
|
|
108
41
|
claude-tempo start # open a player session
|
|
@@ -113,10 +46,10 @@ Or ask the conductor to `recruit` players for you from inside Claude Code.
|
|
|
113
46
|
|
|
114
47
|
### Manual setup
|
|
115
48
|
|
|
116
|
-
|
|
49
|
+
For more control, run each step individually:
|
|
117
50
|
|
|
118
51
|
```bash
|
|
119
|
-
# Start Temporal dev server (keep
|
|
52
|
+
# Start Temporal dev server (keep running)
|
|
120
53
|
claude-tempo server
|
|
121
54
|
|
|
122
55
|
# In your project directory, create .mcp.json
|
|
@@ -133,9 +66,26 @@ claude-tempo conduct
|
|
|
133
66
|
claude-tempo start
|
|
134
67
|
```
|
|
135
68
|
|
|
136
|
-
##
|
|
69
|
+
## Core concepts
|
|
137
70
|
|
|
138
|
-
|
|
71
|
+
- **Player** — A Claude Code session registered as a Temporal workflow
|
|
72
|
+
- **Conductor** — An optional orchestration hub connected to external interfaces (one per ensemble)
|
|
73
|
+
- **Ensemble** — A named group of players that can see and message each other, isolated from other ensembles
|
|
74
|
+
- **Cue** — A message sent to a player by name via Temporal signal
|
|
75
|
+
|
|
76
|
+
Players in one ensemble cannot see or message players in another. By default, sessions join the `default` ensemble:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
claude-tempo conduct frontend # conduct the "frontend" ensemble
|
|
80
|
+
claude-tempo start backend # join the "backend" ensemble
|
|
81
|
+
claude-tempo conduct # conduct the "default" ensemble
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## CLI reference
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
claude-tempo <command> [options]
|
|
88
|
+
```
|
|
139
89
|
|
|
140
90
|
### Commands
|
|
141
91
|
|
|
@@ -147,40 +97,42 @@ The `claude-tempo` CLI handles setup, session management, and diagnostics.
|
|
|
147
97
|
| `conduct [ensemble]` | Start a conductor session (one per ensemble) |
|
|
148
98
|
| `start [ensemble]` | Start a player session |
|
|
149
99
|
| `status [ensemble]` | Show active sessions and Temporal health |
|
|
100
|
+
| `config` | Configure Temporal connection settings (interactive or `set`/`show`) |
|
|
150
101
|
| `init` | Create `.mcp.json` config in the current directory |
|
|
151
|
-
| `preflight` | Run environment checks
|
|
102
|
+
| `preflight` | Run environment checks |
|
|
152
103
|
| `help` | Show usage info |
|
|
153
104
|
|
|
154
|
-
###
|
|
105
|
+
### Global options
|
|
155
106
|
|
|
156
107
|
```
|
|
157
|
-
--temporal-address <addr>
|
|
158
|
-
-
|
|
159
|
-
--
|
|
160
|
-
--
|
|
161
|
-
--
|
|
108
|
+
--temporal-address <addr> Temporal server address (default: localhost:7233)
|
|
109
|
+
--temporal-namespace <ns> Temporal namespace (default: default)
|
|
110
|
+
--temporal-api-key <key> Temporal Cloud API key
|
|
111
|
+
--temporal-tls-cert <path> mTLS client certificate path
|
|
112
|
+
--temporal-tls-key <path> mTLS client key path
|
|
113
|
+
-n, --name <name> Set the player name (start/conduct/up)
|
|
114
|
+
--skip-preflight Skip preflight checks (start/conduct)
|
|
115
|
+
-d, --dir <path> Target directory (default: cwd)
|
|
116
|
+
--background Run Temporal in background (server only)
|
|
162
117
|
```
|
|
163
118
|
|
|
164
|
-
### `up`
|
|
119
|
+
### `claude-tempo up`
|
|
165
120
|
|
|
166
|
-
|
|
121
|
+
The recommended way to get started:
|
|
167
122
|
|
|
168
123
|
```
|
|
169
124
|
$ claude-tempo up myband
|
|
170
125
|
|
|
171
126
|
claude-tempo setup
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
ok Registered search attribute: ClaudeTempoEnsemble
|
|
178
|
-
ok Registered search attribute: ClaudeTempoPlayerId
|
|
179
|
-
pass .mcp.json created
|
|
127
|
+
✓ temporal CLI installed
|
|
128
|
+
… Starting Temporal dev server...
|
|
129
|
+
✓ Temporal started (pid 12345, data in ~/.claude-tempo/)
|
|
130
|
+
✓ Registered search attributes
|
|
131
|
+
✓ .mcp.json created
|
|
180
132
|
|
|
181
133
|
Launching conductor in ensemble myband...
|
|
182
134
|
|
|
183
|
-
|
|
135
|
+
✓ You're all set!
|
|
184
136
|
Conductor launched (pid 12346)
|
|
185
137
|
Ensemble: myband
|
|
186
138
|
|
|
@@ -190,40 +142,20 @@ ok You're all set!
|
|
|
190
142
|
Or ask the conductor to recruit players for you
|
|
191
143
|
```
|
|
192
144
|
|
|
193
|
-
### `server`
|
|
145
|
+
### `claude-tempo server`
|
|
194
146
|
|
|
195
|
-
|
|
147
|
+
Starts the Temporal dev server with automatic search attribute registration:
|
|
196
148
|
|
|
197
149
|
```bash
|
|
198
150
|
claude-tempo server # foreground (Ctrl+C to stop)
|
|
199
151
|
claude-tempo server --background # daemonize
|
|
200
|
-
claude-tempo server -d # shorthand
|
|
201
152
|
```
|
|
202
153
|
|
|
203
|
-
|
|
204
|
-
- Registers all required search attributes automatically
|
|
205
|
-
- If Temporal is already running, just registers attributes and exits
|
|
154
|
+
Data persists in `~/.claude-tempo/temporal-data.db`. If Temporal is already running, registers attributes and exits.
|
|
206
155
|
|
|
207
|
-
### `
|
|
156
|
+
### `claude-tempo status`
|
|
208
157
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
```json
|
|
212
|
-
{
|
|
213
|
-
"mcpServers": {
|
|
214
|
-
"claude-tempo": {
|
|
215
|
-
"command": "npx",
|
|
216
|
-
"args": ["claude-tempo-server"]
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
Uses `npx` to resolve the server binary, so it works regardless of PATH configuration.
|
|
223
|
-
|
|
224
|
-
### `status` — ensemble overview
|
|
225
|
-
|
|
226
|
-
`claude-tempo status` shows all active sessions:
|
|
158
|
+
Shows all active sessions:
|
|
227
159
|
|
|
228
160
|
```
|
|
229
161
|
Ensemble: myband
|
|
@@ -242,42 +174,63 @@ Ensemble: myband
|
|
|
242
174
|
/Users/me/projects/app feat/ui my-machine.local
|
|
243
175
|
```
|
|
244
176
|
|
|
245
|
-
### `preflight`
|
|
177
|
+
### `claude-tempo preflight`
|
|
178
|
+
|
|
179
|
+
Verifies your environment: Node.js >= 18, Temporal reachable, `claude` on PATH, `claude-tempo-server` on PATH, `.mcp.json` configured.
|
|
180
|
+
|
|
181
|
+
### `claude-tempo init`
|
|
182
|
+
|
|
183
|
+
Creates `.mcp.json` in the current directory (or merges into an existing one):
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"mcpServers": {
|
|
188
|
+
"claude-tempo": {
|
|
189
|
+
"command": "npx",
|
|
190
|
+
"args": ["claude-tempo-server"]
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## MCP tools
|
|
246
197
|
|
|
247
|
-
|
|
198
|
+
These tools are available inside Claude Code sessions connected to claude-tempo:
|
|
248
199
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
200
|
+
| Tool | Description |
|
|
201
|
+
|------|-------------|
|
|
202
|
+
| `ensemble` | Discover active sessions. Scope: `machine`, `repo`, or `all`. |
|
|
203
|
+
| `cue` | Send a message to a player by name. Delivered instantly via Temporal signal. |
|
|
204
|
+
| `set_name` | Set a human-readable name for this session. |
|
|
205
|
+
| `set_part` | Describe what you're working on. Visible to others via `ensemble`. |
|
|
206
|
+
| `listen` | Manually check for pending messages. |
|
|
207
|
+
| `recruit` | Spawn a new Claude Code session in a directory. Opens a new terminal window. |
|
|
208
|
+
| `report` | Send updates to the conductor. No-op if no conductor exists. |
|
|
209
|
+
| `terminate` | Terminate a player session by name. |
|
|
254
210
|
|
|
255
|
-
##
|
|
211
|
+
## Conductors
|
|
256
212
|
|
|
257
|
-
A **conductor** is an optional special player that acts as an orchestration hub
|
|
213
|
+
A **conductor** is an optional special player that acts as an orchestration hub. Use one when you want:
|
|
258
214
|
|
|
259
215
|
- A single session coordinating work across multiple players
|
|
260
216
|
- External access to the ensemble via Discord, Telegram, or any Temporal client
|
|
261
217
|
- A central point for players to `report` progress, blockers, and questions
|
|
262
218
|
|
|
263
|
-
Without a conductor, players
|
|
264
|
-
|
|
265
|
-
There is one conductor per ensemble. Start one with:
|
|
219
|
+
Without a conductor, players work fine peer-to-peer — they discover each other via `ensemble` and communicate via `cue`.
|
|
266
220
|
|
|
267
221
|
```bash
|
|
268
|
-
claude-tempo conduct #
|
|
269
|
-
claude-tempo conduct my-project #
|
|
222
|
+
claude-tempo conduct # default ensemble
|
|
223
|
+
claude-tempo conduct my-project # named ensemble
|
|
270
224
|
```
|
|
271
225
|
|
|
272
226
|
### External access
|
|
273
227
|
|
|
274
|
-
The conductor's Temporal workflow exposes a signal/query API
|
|
228
|
+
The conductor's Temporal workflow exposes a signal/query API:
|
|
275
229
|
|
|
276
230
|
```typescript
|
|
277
231
|
import { Client } from '@temporalio/client';
|
|
278
232
|
|
|
279
233
|
const client = new Client();
|
|
280
|
-
// Conductor workflow ID: claude-session-{ensemble}-conductor
|
|
281
234
|
const conductor = client.workflow.getHandle('claude-session-default-conductor');
|
|
282
235
|
|
|
283
236
|
// Send a command
|
|
@@ -286,11 +239,11 @@ await conductor.signal('command', {
|
|
|
286
239
|
source: 'cli',
|
|
287
240
|
});
|
|
288
241
|
|
|
289
|
-
// Check history
|
|
242
|
+
// Check history
|
|
290
243
|
const history = await conductor.query('history');
|
|
291
244
|
```
|
|
292
245
|
|
|
293
|
-
|
|
246
|
+
Connect external channel plugins (e.g., Discord):
|
|
294
247
|
|
|
295
248
|
```bash
|
|
296
249
|
CLAUDE_TEMPO_CONDUCTOR=true claude \
|
|
@@ -298,170 +251,200 @@ CLAUDE_TEMPO_CONDUCTOR=true claude \
|
|
|
298
251
|
--dangerously-skip-permissions --dangerously-load-development-channels server:claude-tempo
|
|
299
252
|
```
|
|
300
253
|
|
|
301
|
-
##
|
|
254
|
+
## Players
|
|
302
255
|
|
|
303
|
-
|
|
256
|
+
### Starting players
|
|
304
257
|
|
|
305
258
|
```bash
|
|
306
259
|
# Terminal 1 — conductor
|
|
307
260
|
claude-tempo conduct my-project
|
|
308
261
|
|
|
309
|
-
# Terminal 2 — frontend
|
|
262
|
+
# Terminal 2 — frontend
|
|
310
263
|
claude-tempo start my-project -n frontend
|
|
311
264
|
|
|
312
|
-
# Terminal 3 — backend
|
|
265
|
+
# Terminal 3 — backend
|
|
313
266
|
claude-tempo start my-project -n backend
|
|
314
267
|
```
|
|
315
268
|
|
|
316
|
-
Or let the conductor `recruit` players
|
|
269
|
+
Or let the conductor `recruit` players — this spawns new terminal windows automatically.
|
|
317
270
|
|
|
318
|
-
|
|
271
|
+
Inside a session, try:
|
|
319
272
|
- "Show me the ensemble" — discovers other sessions
|
|
320
|
-
- "Set your name to 'frontend'" —
|
|
321
|
-
- "Cue frontend: what are you working on?" — sends a message
|
|
273
|
+
- "Set your name to 'frontend'" — human-readable name
|
|
274
|
+
- "Cue frontend: what are you working on?" — sends a message
|
|
322
275
|
|
|
323
|
-
###
|
|
276
|
+
### Session naming
|
|
324
277
|
|
|
325
|
-
|
|
278
|
+
Sessions start with a random 8-character hex ID. Set a name at launch with `-n` or use `set_name` inside a session.
|
|
326
279
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
| gnome-terminal | — | `--` flag | — |
|
|
333
|
-
| konsole / xterm | — | `-e` flag | — |
|
|
334
|
-
| cmd.exe / PowerShell | — | — | `start` command |
|
|
280
|
+
- Names are stored as Temporal search attributes (`ClaudeTempoPlayerId`)
|
|
281
|
+
- Other players use names to send messages via `cue`
|
|
282
|
+
- `recruit` automatically tells new sessions to set their name
|
|
283
|
+
- Names must be unique within an ensemble
|
|
284
|
+
- Names must contain only letters, numbers, hyphens, and underscores
|
|
335
285
|
|
|
336
|
-
|
|
286
|
+
### Terminal support
|
|
337
287
|
|
|
338
|
-
|
|
288
|
+
`recruit` and the CLI detect your terminal automatically:
|
|
339
289
|
|
|
340
|
-
|
|
290
|
+
| Terminal | macOS | Linux | Windows |
|
|
291
|
+
|----------|-------|-------|---------|
|
|
292
|
+
| Ghostty | ✓ | — | — |
|
|
293
|
+
| iTerm2 | ✓ | — | — |
|
|
294
|
+
| Terminal.app | ✓ | — | — |
|
|
295
|
+
| gnome-terminal | — | ✓ | — |
|
|
296
|
+
| konsole / xterm | — | ✓ | — |
|
|
297
|
+
| cmd.exe / PowerShell | — | — | ✓ |
|
|
341
298
|
|
|
342
|
-
|
|
343
|
-
- Other players use the name to send messages via `cue` and discover sessions via `ensemble`
|
|
344
|
-
- `recruit` automatically tells the new session to set its name
|
|
345
|
-
- Names must be unique within an ensemble — `set_name` rejects duplicates
|
|
346
|
-
- Names must contain only letters, numbers, hyphens, and underscores
|
|
299
|
+
macOS terminals preserve the full shell environment (fish, zsh, bash) including node version managers (fnm, nvm).
|
|
347
300
|
|
|
348
301
|
## Configuration
|
|
349
302
|
|
|
350
|
-
|
|
351
|
-
|---------------------|---------|-------------|
|
|
352
|
-
| `TEMPORAL_ADDRESS` | `localhost:7233` | Temporal server address |
|
|
353
|
-
| `TEMPORAL_NAMESPACE` | `default` | Temporal namespace |
|
|
354
|
-
| `CLAUDE_TEMPO_TASK_QUEUE` | `claude-tempo` | Task queue name |
|
|
355
|
-
| `CLAUDE_TEMPO_ENSEMBLE` | `default` | Ensemble name (isolates groups of players) |
|
|
356
|
-
| `CLAUDE_TEMPO_CONDUCTOR` | `false` | Set to `true` to enable conductor mode |
|
|
357
|
-
| `CLAUDE_TEMPO_PLAYER_NAME` | *(random hex)* | Set a player name on startup (used by `-n` flag) |
|
|
303
|
+
Run `claude-tempo config` to save Temporal connection settings so you don't need flags or env vars every time:
|
|
358
304
|
|
|
359
|
-
|
|
305
|
+
```
|
|
306
|
+
$ claude-tempo config
|
|
307
|
+
|
|
308
|
+
? Temporal address (localhost:7233): my-ns.tmprl.cloud:7233
|
|
309
|
+
? Temporal namespace (default): my-ns.abc123
|
|
310
|
+
? Auth method: (None / API key / mTLS)
|
|
311
|
+
? API key: ****
|
|
312
|
+
Saved to ~/.claude-tempo/config.json
|
|
313
|
+
✓ Connected successfully
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Settings are stored in `~/.claude-tempo/config.json`. You can also set values non-interactively:
|
|
360
317
|
|
|
361
318
|
```bash
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
319
|
+
claude-tempo config set temporalAddress my-ns.tmprl.cloud:7233
|
|
320
|
+
claude-tempo config set temporalNamespace my-ns.abc123
|
|
321
|
+
claude-tempo config set temporalApiKey tcl_...
|
|
322
|
+
claude-tempo config show
|
|
323
|
+
```
|
|
365
324
|
|
|
366
|
-
|
|
367
|
-
npm run build
|
|
325
|
+
### Resolution order
|
|
368
326
|
|
|
369
|
-
|
|
370
|
-
npx ts-node src/server.ts
|
|
327
|
+
Settings are resolved in this order (first match wins):
|
|
371
328
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
329
|
+
1. CLI flags (`--temporal-address`, `--temporal-namespace`, etc.)
|
|
330
|
+
2. Environment variables (`TEMPORAL_ADDRESS`, `TEMPORAL_NAMESPACE`, etc.)
|
|
331
|
+
3. claude-tempo config file (`~/.claude-tempo/config.json`)
|
|
332
|
+
4. Temporal CLI config (`~/.config/temporalio/temporal.yaml`) — if you've already configured the Temporal CLI, claude-tempo reads it automatically
|
|
333
|
+
5. Defaults (`localhost:7233`, `default` namespace)
|
|
375
334
|
|
|
376
|
-
|
|
335
|
+
### Temporal Cloud
|
|
377
336
|
|
|
378
|
-
|
|
337
|
+
For Temporal Cloud, run `claude-tempo config` and provide your cloud address, namespace, and API key. Or set them as environment variables in CI:
|
|
379
338
|
|
|
380
|
-
|
|
381
|
-
-
|
|
382
|
-
-
|
|
383
|
-
|
|
384
|
-
|
|
339
|
+
```bash
|
|
340
|
+
export TEMPORAL_ADDRESS=my-ns.abc123.tmprl.cloud:7233
|
|
341
|
+
export TEMPORAL_NAMESPACE=my-ns.abc123
|
|
342
|
+
export TEMPORAL_API_KEY=tcl_...
|
|
343
|
+
```
|
|
385
344
|
|
|
386
|
-
##
|
|
345
|
+
## Environment variables
|
|
387
346
|
|
|
388
|
-
|
|
347
|
+
| Variable | Default | Description |
|
|
348
|
+
|----------|---------|-------------|
|
|
349
|
+
| `TEMPORAL_ADDRESS` | `localhost:7233` | Temporal server address |
|
|
350
|
+
| `TEMPORAL_NAMESPACE` | `default` | Temporal namespace |
|
|
351
|
+
| `TEMPORAL_API_KEY` | *(none)* | Temporal Cloud API key |
|
|
352
|
+
| `TEMPORAL_TLS_CERT_PATH` | *(none)* | mTLS client certificate path |
|
|
353
|
+
| `TEMPORAL_TLS_KEY_PATH` | *(none)* | mTLS client key path |
|
|
354
|
+
| `CLAUDE_TEMPO_TASK_QUEUE` | `claude-tempo` | Task queue name |
|
|
355
|
+
| `CLAUDE_TEMPO_ENSEMBLE` | `default` | Ensemble name |
|
|
356
|
+
| `CLAUDE_TEMPO_CONDUCTOR` | `false` | Enable conductor mode |
|
|
357
|
+
| `CLAUDE_TEMPO_PLAYER_NAME` | *(random hex)* | Player name on startup |
|
|
389
358
|
|
|
390
|
-
|
|
391
|
-
- Before exiting, it notifies the conductor with the undelivered message content so work can be reassigned
|
|
392
|
-
- Idle sessions with no pending messages remain running (they aren't hurting anyone) until the 24-hour execution timeout
|
|
359
|
+
## Stale session cleanup
|
|
393
360
|
|
|
394
|
-
|
|
361
|
+
When a session crashes or closes without graceful shutdown, Temporal detects it automatically:
|
|
395
362
|
|
|
396
|
-
|
|
363
|
+
- If a message to a dead session remains undelivered for **3 minutes**, the workflow self-completes
|
|
364
|
+
- Before exiting, it notifies the conductor with the undelivered message so work can be reassigned
|
|
365
|
+
- Idle sessions with no pending messages remain running until the 24-hour timeout
|
|
397
366
|
|
|
398
|
-
|
|
367
|
+
No manual cleanup needed — `cue` a dead player and the system handles the rest.
|
|
399
368
|
|
|
400
369
|
## Copilot CLI integration (experimental)
|
|
401
370
|
|
|
402
|
-
> **Warning:** Copilot bridge support is
|
|
371
|
+
> **Warning:** Copilot bridge support is experimental and subject to breaking changes.
|
|
403
372
|
|
|
404
|
-
GitHub Copilot CLI sessions can join an ensemble via the
|
|
373
|
+
GitHub Copilot CLI sessions can join an ensemble via the Copilot bridge. Bridge sessions are headless — they require a Claude conductor or custom Temporal client to receive work via `cue`.
|
|
405
374
|
|
|
406
|
-
|
|
375
|
+
<details>
|
|
376
|
+
<summary>Setup and usage</summary>
|
|
407
377
|
|
|
408
|
-
|
|
378
|
+
### Prerequisites
|
|
409
379
|
|
|
410
380
|
```bash
|
|
411
|
-
npm install @github/copilot-sdk
|
|
381
|
+
npm install @github/copilot-sdk # optional dependency (~243MB)
|
|
412
382
|
```
|
|
413
383
|
|
|
414
|
-
|
|
415
|
-
- [GitHub Copilot CLI](https://docs.github.com/en/copilot/github-copilot-in-the-cli) installed and authenticated
|
|
416
|
-
- An active GitHub Copilot subscription
|
|
384
|
+
Also requires [GitHub Copilot CLI](https://docs.github.com/en/copilot/github-copilot-in-the-cli) installed, authenticated, with an active subscription. Node 20+ required for Copilot features.
|
|
417
385
|
|
|
418
386
|
### Starting a Copilot player
|
|
419
387
|
|
|
420
|
-
The easiest way
|
|
388
|
+
The easiest way is via `recruit` from any active session:
|
|
421
389
|
|
|
422
390
|
> "Recruit a copilot session named 'copilot-dev' in /repos/my-project with agent copilot"
|
|
423
391
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
<details>
|
|
427
|
-
<summary>Advanced: running the bridge directly</summary>
|
|
428
|
-
|
|
429
|
-
You can also start the bridge manually with environment variables:
|
|
392
|
+
Or start the bridge directly:
|
|
430
393
|
|
|
431
394
|
```bash
|
|
432
|
-
# Linux/macOS
|
|
433
395
|
CLAUDE_TEMPO_ENSEMBLE=default COPILOT_BRIDGE_NAME=copilot-dev npx ts-node src/copilot-bridge.ts
|
|
434
|
-
|
|
435
|
-
# Windows PowerShell
|
|
436
|
-
$env:TEMPORAL_ADDRESS="localhost:7233"; $env:CLAUDE_TEMPO_ENSEMBLE="default"; $env:COPILOT_BRIDGE_NAME="copilot-dev"; npx ts-node src/copilot-bridge.ts
|
|
437
396
|
```
|
|
438
397
|
|
|
439
|
-
</details>
|
|
440
|
-
|
|
441
398
|
### How it works
|
|
442
399
|
|
|
443
|
-
1.
|
|
444
|
-
2.
|
|
445
|
-
3.
|
|
446
|
-
4.
|
|
447
|
-
5.
|
|
448
|
-
6. The Copilot session can use all claude-tempo tools (`ensemble`, `cue`, `report`, etc.)
|
|
400
|
+
1. Bridge spawns a Copilot CLI session via the SDK with claude-tempo as MCP server
|
|
401
|
+
2. MCP server registers the session as a Temporal workflow
|
|
402
|
+
3. Bridge polls for pending messages every 2 seconds
|
|
403
|
+
4. Messages are injected as prompts via `session.sendAndWait()`
|
|
404
|
+
5. The Copilot session can use all claude-tempo tools
|
|
449
405
|
|
|
450
|
-
###
|
|
406
|
+
### Copilot environment variables
|
|
451
407
|
|
|
452
408
|
| Variable | Default | Description |
|
|
453
409
|
|----------|---------|-------------|
|
|
454
|
-
| `COPILOT_BRIDGE_NAME` | *(none)* | Player name
|
|
455
|
-
| `COPILOT_BRIDGE_MODEL` | *(Copilot default)* | Model override
|
|
410
|
+
| `COPILOT_BRIDGE_NAME` | *(none)* | Player name |
|
|
411
|
+
| `COPILOT_BRIDGE_MODEL` | *(Copilot default)* | Model override |
|
|
456
412
|
| `GITHUB_TOKEN` | *(logged-in user)* | GitHub auth token |
|
|
457
413
|
|
|
458
414
|
### Limitations
|
|
459
415
|
|
|
460
|
-
-
|
|
461
|
-
-
|
|
462
|
-
-
|
|
463
|
-
-
|
|
464
|
-
-
|
|
416
|
+
- No interactive access — bridge sessions only respond to cues
|
|
417
|
+
- 2-second polling latency (vs instant for Claude Code sessions)
|
|
418
|
+
- Must be spawned via the bridge to participate
|
|
419
|
+
- `@github/copilot-sdk` adds ~243MB to node_modules
|
|
420
|
+
- Node 20+ required (rest of claude-tempo works on Node 18+)
|
|
421
|
+
|
|
422
|
+
</details>
|
|
423
|
+
|
|
424
|
+
## Development
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
git clone https://github.com/vinceblank/claude-tempo.git
|
|
428
|
+
cd claude-tempo && npm install
|
|
429
|
+
|
|
430
|
+
npm run build # compile TypeScript + pre-bundle workflows
|
|
431
|
+
npm test # run tests
|
|
432
|
+
npm link # link CLI for local testing
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
> **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.
|
|
436
|
+
|
|
437
|
+
## Why Temporal?
|
|
438
|
+
|
|
439
|
+
- **Cross-machine** — Any session that can reach the Temporal server can join
|
|
440
|
+
- **Instant signaling** — Temporal signals deliver messages with no polling
|
|
441
|
+
- **Durable history** — Full audit trail in Temporal's event history
|
|
442
|
+
- **No custom infrastructure** — No broker, no database — just Temporal
|
|
443
|
+
- **Extensible** — The conductor's signal/query contract is a public API
|
|
444
|
+
|
|
445
|
+
## Known limitations
|
|
446
|
+
|
|
447
|
+
- **`recruit` requires manual acknowledgment** — Recruited sessions use `--dangerously-load-development-channels`. Claude Code shows a confirmation prompt that must be manually acknowledged in the spawned terminal. This will be resolved once claude-tempo is published as an approved channel plugin. Copilot bridge sessions do not have this limitation.
|
|
465
448
|
|
|
466
449
|
## License
|
|
467
450
|
|