claude-tempo 0.1.1 → 0.1.3
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 +8 -6
- package/dist/cli/commands.js +23 -2
- package/dist/server.js +1 -1
- package/dist/spawn.js +3 -2
- package/package.json +29 -1
- package/workflow-bundle.js +7680 -0
package/README.md
CHANGED
|
@@ -142,6 +142,7 @@ The `claude-tempo` CLI handles setup, session management, and diagnostics.
|
|
|
142
142
|
| Command | Description |
|
|
143
143
|
|---------|-------------|
|
|
144
144
|
| `up [ensemble]` | First-time setup: start Temporal, configure MCP, launch conductor |
|
|
145
|
+
| `down` | Stop Temporal, terminate sessions, remove MCP config |
|
|
145
146
|
| `server` | Start the Temporal dev server and register search attributes |
|
|
146
147
|
| `conduct [ensemble]` | Start a conductor session (one per ensemble) |
|
|
147
148
|
| `start [ensemble]` | Start a player session |
|
|
@@ -154,7 +155,7 @@ The `claude-tempo` CLI handles setup, session management, and diagnostics.
|
|
|
154
155
|
|
|
155
156
|
```
|
|
156
157
|
--temporal-address <addr> Temporal server address (default: localhost:7233)
|
|
157
|
-
-n, --name <name> Set the
|
|
158
|
+
-n, --name <name> Set the player name for the session (start/conduct/up)
|
|
158
159
|
--skip-preflight Skip preflight checks (start/conduct)
|
|
159
160
|
--background, -d Run Temporal in background (server only)
|
|
160
161
|
--dir <path> Target directory for init (default: cwd)
|
|
@@ -211,14 +212,14 @@ claude-tempo server -d # shorthand
|
|
|
211
212
|
{
|
|
212
213
|
"mcpServers": {
|
|
213
214
|
"claude-tempo": {
|
|
214
|
-
"command": "
|
|
215
|
-
"args": []
|
|
215
|
+
"command": "npx",
|
|
216
|
+
"args": ["claude-tempo-server"]
|
|
216
217
|
}
|
|
217
218
|
}
|
|
218
219
|
}
|
|
219
220
|
```
|
|
220
221
|
|
|
221
|
-
|
|
222
|
+
Uses `npx` to resolve the server binary, so it works regardless of PATH configuration.
|
|
222
223
|
|
|
223
224
|
### `status` — ensemble overview
|
|
224
225
|
|
|
@@ -330,13 +331,13 @@ The `recruit` tool and CLI automatically detect and open sessions in your termin
|
|
|
330
331
|
| Terminal.app | `.command` file | — | — |
|
|
331
332
|
| gnome-terminal | — | `--` flag | — |
|
|
332
333
|
| konsole / xterm | — | `-e` flag | — |
|
|
333
|
-
| cmd.exe / PowerShell | — | — | `
|
|
334
|
+
| cmd.exe / PowerShell | — | — | `start` command |
|
|
334
335
|
|
|
335
336
|
All macOS terminals use approaches that preserve the user's full shell environment (fish, zsh, bash) including node version managers (fnm, nvm).
|
|
336
337
|
|
|
337
338
|
### Session naming
|
|
338
339
|
|
|
339
|
-
Sessions start with a random 8-character hex ID.
|
|
340
|
+
Sessions start with a random 8-character hex ID. You can set a name at launch with `-n` or use `set_name` inside a session:
|
|
340
341
|
|
|
341
342
|
- Names are stored as Temporal search attributes (`ClaudeTempoPlayerId`) and updated in-place — no workflow restart needed
|
|
342
343
|
- Other players use the name to send messages via `cue` and discover sessions via `ensemble`
|
|
@@ -353,6 +354,7 @@ Sessions start with a random 8-character hex ID. Use `set_name` to give a sessio
|
|
|
353
354
|
| `CLAUDE_TEMPO_TASK_QUEUE` | `claude-tempo` | Task queue name |
|
|
354
355
|
| `CLAUDE_TEMPO_ENSEMBLE` | `default` | Ensemble name (isolates groups of players) |
|
|
355
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) |
|
|
356
358
|
|
|
357
359
|
## Development
|
|
358
360
|
|
package/dist/cli/commands.js
CHANGED
|
@@ -47,6 +47,7 @@ const child_process_1 = require("child_process");
|
|
|
47
47
|
const os_1 = require("os");
|
|
48
48
|
const client_1 = require("@temporalio/client");
|
|
49
49
|
const spawn_1 = require("../spawn");
|
|
50
|
+
const config_1 = require("../config");
|
|
50
51
|
const preflight_1 = require("./preflight");
|
|
51
52
|
const out = __importStar(require("./output"));
|
|
52
53
|
/** Package root is two levels up from dist/cli/ */
|
|
@@ -67,6 +68,23 @@ async function start(opts) {
|
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
const role = opts.conductor ? 'conductor' : 'player';
|
|
71
|
+
// Check if a conductor workflow already exists for this ensemble
|
|
72
|
+
if (opts.conductor) {
|
|
73
|
+
try {
|
|
74
|
+
const connection = await client_1.Connection.connect({ address: opts.temporalAddress });
|
|
75
|
+
const client = new client_1.Client({ connection });
|
|
76
|
+
const conductorWfId = (0, config_1.conductorWorkflowId)(opts.ensemble);
|
|
77
|
+
const handle = client.workflow.getHandle(conductorWfId);
|
|
78
|
+
const desc = await handle.describe();
|
|
79
|
+
if (desc.status.name === 'RUNNING') {
|
|
80
|
+
out.warn(`A conductor workflow already exists for ensemble "${opts.ensemble}". Reconnecting...`);
|
|
81
|
+
}
|
|
82
|
+
await connection.close();
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// No existing conductor — proceed normally
|
|
86
|
+
}
|
|
87
|
+
}
|
|
70
88
|
out.log(`Starting ${out.bold(role)} in ensemble ${out.cyan(opts.ensemble)}`);
|
|
71
89
|
const claudeArgs = [
|
|
72
90
|
'--dangerously-skip-permissions',
|
|
@@ -81,6 +99,9 @@ async function start(opts) {
|
|
|
81
99
|
if (opts.conductor) {
|
|
82
100
|
envVars.CLAUDE_TEMPO_CONDUCTOR = 'true';
|
|
83
101
|
}
|
|
102
|
+
if (opts.name) {
|
|
103
|
+
envVars.CLAUDE_TEMPO_PLAYER_NAME = opts.name;
|
|
104
|
+
}
|
|
84
105
|
const { pid } = (0, spawn_1.spawnInTerminal)(claudeArgs, workDir, envVars);
|
|
85
106
|
out.success(`Launched ${role} session${opts.name ? ` "${opts.name}"` : ''} (pid ${pid ?? 'unknown'})`);
|
|
86
107
|
out.log(` Ensemble: ${opts.ensemble}`);
|
|
@@ -171,8 +192,8 @@ async function status(opts) {
|
|
|
171
192
|
async function init(opts) {
|
|
172
193
|
const mcpPath = (0, path_1.join)(opts.dir, '.mcp.json');
|
|
173
194
|
const entry = {
|
|
174
|
-
command: '
|
|
175
|
-
args: [],
|
|
195
|
+
command: 'npx',
|
|
196
|
+
args: ['claude-tempo-server'],
|
|
176
197
|
};
|
|
177
198
|
if ((0, fs_1.existsSync)(mcpPath)) {
|
|
178
199
|
try {
|
package/dist/server.js
CHANGED
|
@@ -89,7 +89,7 @@ async function main() {
|
|
|
89
89
|
}
|
|
90
90
|
const config = (0, config_1.getConfig)();
|
|
91
91
|
const isConductor = process.env.CLAUDE_TEMPO_CONDUCTOR === 'true';
|
|
92
|
-
let playerId = isConductor ? 'conductor' : crypto.randomBytes(4).toString('hex');
|
|
92
|
+
let playerId = isConductor ? 'conductor' : (process.env.CLAUDE_TEMPO_PLAYER_NAME || crypto.randomBytes(4).toString('hex'));
|
|
93
93
|
const getPlayerId = () => playerId;
|
|
94
94
|
const setPlayerId = (id) => { playerId = id; };
|
|
95
95
|
const workDir = process.cwd();
|
package/dist/spawn.js
CHANGED
|
@@ -174,11 +174,12 @@ function spawnInTerminal(claudeArgs, workDir, envVars) {
|
|
|
174
174
|
return { pid: child.pid };
|
|
175
175
|
}
|
|
176
176
|
if (process.platform === 'win32') {
|
|
177
|
-
|
|
177
|
+
// Use 'start' to open a visible terminal window, and pass the full
|
|
178
|
+
// command as a single string to avoid DEP0190 deprecation warning
|
|
179
|
+
const child = (0, child_process_1.spawn)('cmd.exe', ['/c', 'start', '""', claudeBin, ...claudeArgs], {
|
|
178
180
|
cwd: workDir,
|
|
179
181
|
detached: true,
|
|
180
182
|
stdio: 'ignore',
|
|
181
|
-
shell: true,
|
|
182
183
|
env: { ...process.env, ...envVars },
|
|
183
184
|
});
|
|
184
185
|
child.unref();
|
package/package.json
CHANGED
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-tempo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "MCP server for multi-session Claude Code coordination via Temporal",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/server.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./dist/server.js",
|
|
9
|
+
"./types": {
|
|
10
|
+
"types": "./dist/types.d.ts",
|
|
11
|
+
"default": "./dist/types.js"
|
|
12
|
+
},
|
|
13
|
+
"./config": {
|
|
14
|
+
"types": "./dist/config.d.ts",
|
|
15
|
+
"default": "./dist/config.js"
|
|
16
|
+
},
|
|
17
|
+
"./spawn": {
|
|
18
|
+
"types": "./dist/spawn.d.ts",
|
|
19
|
+
"default": "./dist/spawn.js"
|
|
20
|
+
},
|
|
21
|
+
"./signals": {
|
|
22
|
+
"types": "./dist/workflows/signals.d.ts",
|
|
23
|
+
"default": "./dist/workflows/signals.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
7
26
|
"bin": {
|
|
8
27
|
"claude-tempo": "dist/cli.js",
|
|
9
28
|
"claude-tempo-server": "dist/server.js"
|
|
@@ -26,8 +45,17 @@
|
|
|
26
45
|
"ts-node": "^10.9.0",
|
|
27
46
|
"typescript": "^5.5.0"
|
|
28
47
|
},
|
|
48
|
+
"typesVersions": {
|
|
49
|
+
"*": {
|
|
50
|
+
"types": ["dist/types.d.ts"],
|
|
51
|
+
"config": ["dist/config.d.ts"],
|
|
52
|
+
"spawn": ["dist/spawn.d.ts"],
|
|
53
|
+
"signals": ["dist/workflows/signals.d.ts"]
|
|
54
|
+
}
|
|
55
|
+
},
|
|
29
56
|
"files": [
|
|
30
57
|
"dist",
|
|
58
|
+
"workflow-bundle.js",
|
|
31
59
|
"CLAUDE.md",
|
|
32
60
|
"README.md"
|
|
33
61
|
],
|