claude-tempo 0.26.0 → 0.27.0
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 -1
- package/README.md +21 -21
- package/dist/activities/outbox.js +20 -12
- package/dist/cli/commands.d.ts +21 -73
- package/dist/cli/commands.js +200 -646
- package/dist/cli/daemon.d.ts +31 -3
- package/dist/cli/daemon.js +58 -16
- package/dist/cli/help-text.js +47 -47
- package/dist/cli/removed-verbs.d.ts +9 -0
- package/dist/cli/removed-verbs.js +75 -0
- package/dist/cli/startup.d.ts +103 -0
- package/dist/cli/startup.js +615 -0
- package/dist/cli.js +54 -170
- package/dist/client/ensure-conductor-spawned.d.ts +32 -0
- package/dist/client/ensure-conductor-spawned.js +45 -0
- package/dist/client/index.d.ts +1 -7
- package/dist/client/index.js +447 -0
- package/dist/client/interface.d.ts +177 -3
- package/dist/config.d.ts +6 -0
- package/dist/config.js +45 -7
- package/dist/daemon.js +20 -80
- package/dist/ensemble/loader.js +9 -0
- package/dist/ensemble/saver.js +3 -1
- package/dist/ensemble/schema.d.ts +7 -1
- package/dist/reconcile/orphans.d.ts +134 -2
- package/dist/reconcile/orphans.js +206 -15
- package/dist/server.js +14 -8
- package/dist/tools/destroy.d.ts +1 -1
- package/dist/tools/destroy.js +149 -24
- package/dist/tools/{pause-ensemble.d.ts → pause.d.ts} +1 -1
- package/dist/tools/pause.js +36 -0
- package/dist/tools/{resume-ensemble.d.ts → play.d.ts} +1 -1
- package/dist/tools/play.js +57 -0
- package/dist/tools/restore.d.ts +4 -0
- package/dist/tools/restore.js +91 -0
- package/dist/tools/shutdown.d.ts +4 -0
- package/dist/tools/shutdown.js +54 -0
- package/dist/tui/App.d.ts +63 -0
- package/dist/tui/App.js +548 -155
- package/dist/tui/bootstrap-types.d.ts +46 -0
- package/dist/tui/bootstrap-types.js +7 -0
- package/dist/tui/commands.d.ts +48 -1
- package/dist/tui/commands.js +383 -177
- package/dist/tui/components/DestroyConfirmModal.d.ts +17 -0
- package/dist/tui/components/DestroyConfirmModal.js +62 -0
- package/dist/tui/components/HomeView.d.ts +54 -0
- package/dist/tui/components/HomeView.js +306 -0
- package/dist/tui/components/LoadLineupModal.d.ts +18 -0
- package/dist/tui/components/LoadLineupModal.js +79 -0
- package/dist/tui/components/NewEnsembleModal.d.ts +9 -0
- package/dist/tui/components/NewEnsembleModal.js +73 -0
- package/dist/tui/components/PromptArea.js +9 -12
- package/dist/tui/components/RestoreConfirmModal.d.ts +18 -0
- package/dist/tui/components/RestoreConfirmModal.js +71 -0
- package/dist/tui/components/StatusBar.d.ts +34 -1
- package/dist/tui/components/StatusBar.js +59 -14
- package/dist/tui/index.d.ts +8 -0
- package/dist/tui/index.js +12 -0
- package/dist/tui/removed-commands.d.ts +9 -0
- package/dist/tui/removed-commands.js +22 -0
- package/dist/tui/store.d.ts +130 -0
- package/dist/tui/store.js +139 -1
- package/dist/tui/utils/format.d.ts +19 -0
- package/dist/tui/utils/format.js +17 -0
- package/dist/utils/ensemble-ops.d.ts +61 -0
- package/dist/utils/ensemble-ops.js +77 -0
- package/package.json +3 -1
- package/dist/tools/pause-ensemble.js +0 -58
- package/dist/tools/resume-ensemble.js +0 -79
package/CLAUDE.md
CHANGED
|
@@ -28,6 +28,8 @@ src/
|
|
|
28
28
|
│ ├── mcp.ts # MCP server registration helpers (init, global vs project)
|
|
29
29
|
│ ├── output.ts # Shared CLI output formatting helpers
|
|
30
30
|
│ ├── preflight.ts # Environment preflight checks
|
|
31
|
+
│ ├── removed-verbs.ts # lookup table for the 10 CLI verbs removed in #288 — dispatches migration hints before loading Temporal surface
|
|
32
|
+
│ ├── startup.ts # auto-provisioning bootstrap state machine (#289) — six-step idempotent sequence used by bare `claude-tempo` invocation
|
|
31
33
|
│ └── upgrade-command.ts # upgrade subcommand — crash-proof; dynamic-imports Temporal only for active-session warning
|
|
32
34
|
├── adapters/
|
|
33
35
|
│ ├── README.md # Adapter contract documentation
|
|
@@ -69,7 +71,7 @@ src/
|
|
|
69
71
|
│ ├── worktree.ts / stage.ts / stages.ts / cancel-stage.ts
|
|
70
72
|
│ ├── load-lineup.ts / save-lineup.ts / agent-types.ts / resolve.ts
|
|
71
73
|
│ ├── set-name.ts / set-part.ts / who-am-i.ts / release.ts
|
|
72
|
-
│ ├── pause
|
|
74
|
+
│ ├── pause.ts / play.ts / shutdown.ts / restore.ts
|
|
73
75
|
│ ├── hosts.ts
|
|
74
76
|
│ └── helpers.ts # Zod/MCP tool registration wrapper
|
|
75
77
|
├── tui/
|
package/README.md
CHANGED
|
@@ -59,11 +59,10 @@ claude-tempo up
|
|
|
59
59
|
This starts Temporal, registers the MCP server, launches the daemon, and opens a conductor session. Then add players:
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
claude-tempo start # open a player session
|
|
63
62
|
claude-tempo status # see who's active
|
|
64
63
|
```
|
|
65
64
|
|
|
66
|
-
Or ask the conductor to `recruit`
|
|
65
|
+
Or use the TUI to recruit players, or ask the conductor to `recruit` from inside Claude Code.
|
|
67
66
|
|
|
68
67
|
### Manual setup
|
|
69
68
|
|
|
@@ -71,8 +70,7 @@ Or ask the conductor to `recruit` players from inside Claude Code.
|
|
|
71
70
|
claude-tempo server # start Temporal dev server
|
|
72
71
|
claude-tempo init # register MCP server globally
|
|
73
72
|
claude-tempo preflight # verify environment
|
|
74
|
-
claude-tempo
|
|
75
|
-
claude-tempo start # start a player
|
|
73
|
+
claude-tempo up # launch conductor via auto-provisioning
|
|
76
74
|
```
|
|
77
75
|
|
|
78
76
|
## Upgrading
|
|
@@ -90,12 +88,15 @@ claude-tempo upgrade 0.22.0
|
|
|
90
88
|
## Stopping & Tear Down
|
|
91
89
|
|
|
92
90
|
```bash
|
|
93
|
-
#
|
|
94
|
-
claude-tempo
|
|
91
|
+
# Terminate all sessions in an ensemble
|
|
92
|
+
claude-tempo destroy my-ensemble
|
|
95
93
|
|
|
96
94
|
# Tear down everything (all sessions, schedulers, and Maestro workflows)
|
|
97
95
|
claude-tempo down --all
|
|
98
96
|
|
|
97
|
+
# Tear down and terminate all workflows in one step
|
|
98
|
+
claude-tempo down --destroy -y
|
|
99
|
+
|
|
99
100
|
# Stop the background daemon
|
|
100
101
|
claude-tempo daemon stop
|
|
101
102
|
```
|
|
@@ -107,17 +108,17 @@ claude-tempo daemon stop
|
|
|
107
108
|
## Core Concepts
|
|
108
109
|
|
|
109
110
|
- **Player** — A Claude Code session registered as a Temporal workflow
|
|
110
|
-
- **Conductor** —
|
|
111
|
+
- **Conductor** — Required orchestration hub (one per ensemble); receives `report` calls and connects to external interfaces. Lineup schema enforces its presence.
|
|
111
112
|
- **Ensemble** — A named group of players isolated from other ensembles; defaults to `default`
|
|
112
113
|
- **Cue** — A message sent to a player by name via Temporal signal
|
|
113
114
|
- **Lineup** — A YAML file that defines a full team and recruits them in one step
|
|
114
115
|
- **Player Type** — A reusable agent definition (`.md` with YAML frontmatter) that gives a player a named role
|
|
115
116
|
|
|
116
|
-
Players in one ensemble cannot see or message players in another:
|
|
117
|
+
Players in one ensemble cannot see or message players in another. Launch `claude-tempo` to open the TUI and switch between ensembles, or target a specific ensemble directly:
|
|
117
118
|
|
|
118
119
|
```bash
|
|
119
|
-
claude-tempo
|
|
120
|
-
claude-tempo
|
|
120
|
+
claude-tempo up frontend # provision and launch conductor in "frontend"
|
|
121
|
+
claude-tempo up backend # provision and launch conductor in "backend"
|
|
121
122
|
```
|
|
122
123
|
|
|
123
124
|
## MCP Tools
|
|
@@ -139,17 +140,16 @@ Tools available inside Claude Code sessions connected to claude-tempo:
|
|
|
139
140
|
## CLI
|
|
140
141
|
|
|
141
142
|
```bash
|
|
142
|
-
claude-tempo
|
|
143
|
-
claude-tempo
|
|
144
|
-
claude-tempo
|
|
143
|
+
claude-tempo # launch TUI (auto-provisions on first run)
|
|
144
|
+
claude-tempo up [ensemble] # provision infrastructure and launch conductor
|
|
145
|
+
claude-tempo down [--destroy] # tear down infrastructure (--destroy also terminates workflows)
|
|
145
146
|
claude-tempo status [ensemble] # list active sessions
|
|
147
|
+
claude-tempo destroy <ensemble> # terminate all sessions in an ensemble
|
|
148
|
+
claude-tempo restore <ensemble> # restore orphaned sessions on this host
|
|
146
149
|
claude-tempo hosts # list daemons polling this Temporal namespace (--all/--json)
|
|
147
|
-
claude-tempo recall <name> # read a player's message history (--limit/--offset/--preview/--
|
|
150
|
+
claude-tempo recall <name> # read a player's message history (--limit/--offset/--preview/--json)
|
|
148
151
|
claude-tempo attachment-info <name> # inspect a session's phase, holder, lease, and heartbeat age
|
|
149
152
|
claude-tempo release [ensemble] # release held players (unlock + deliver tasks)
|
|
150
|
-
claude-tempo pause [ensemble] # pause all sessions and the scheduler
|
|
151
|
-
claude-tempo resume [ensemble] # resume a paused ensemble (--release also releases held players)
|
|
152
|
-
claude-tempo tui # open the terminal UI
|
|
153
153
|
claude-tempo daemon <sub> # manage the worker daemon
|
|
154
154
|
claude-tempo upgrade # update to latest
|
|
155
155
|
```
|
|
@@ -240,7 +240,7 @@ claude-tempo tui --ensemble my-ensemble # direct ensemble mode
|
|
|
240
240
|
The TUI provides a chat-focused shell for managing your ensemble:
|
|
241
241
|
|
|
242
242
|
- **Ensemble chat feed** — live aggregated view of conductor + player traffic; type bare text to message the conductor, `@player message` to message directly
|
|
243
|
-
- **Slash commands** — `/recruit`, `/status`, `/schedule`, `/gates`, `/stages`, `/worktree`, `/go` (release held), `/pause`, `/
|
|
243
|
+
- **Slash commands** — `/recruit`, `/status`, `/schedule`, `/gates`, `/stages`, `/worktree`, `/go` (release held), `/pause`, `/play`, `/shutdown`, `/restore`, `/home`, and more; type `/help` for the full list
|
|
244
244
|
- **Interactive overlays and wizards** — step-by-step flows for recruiting players, creating schedules, and managing ensembles
|
|
245
245
|
|
|
246
246
|
📖 [TUI reference → docs/tui.md](docs/tui.md)
|
|
@@ -249,10 +249,10 @@ The TUI provides a chat-focused shell for managing your ensemble:
|
|
|
249
249
|
|
|
250
250
|
> **Experimental** — subject to breaking changes.
|
|
251
251
|
|
|
252
|
-
GitHub Copilot CLI sessions can join an ensemble using `--agent copilot
|
|
252
|
+
GitHub Copilot CLI sessions can join an ensemble using `--agent copilot`. Recruit one from the TUI:
|
|
253
253
|
|
|
254
|
-
```
|
|
255
|
-
|
|
254
|
+
```
|
|
255
|
+
/recruit copilot-1 --agent copilot
|
|
256
256
|
```
|
|
257
257
|
|
|
258
258
|
📖 [Copilot bridge setup and limitations → docs/copilot.md](docs/copilot.md)
|
|
@@ -575,15 +575,22 @@ function createOutboxActivities(client, config) {
|
|
|
575
575
|
// already exists at `~/.claude/projects/<encoded-path>/<uuid>.jsonl`
|
|
576
576
|
// ("Session ID already in use"). A prior failed spawn can leave that
|
|
577
577
|
// file behind, wedging every subsequent `fresh` restart that reuses the
|
|
578
|
-
// stored sessionId.
|
|
579
|
-
//
|
|
580
|
-
//
|
|
581
|
-
//
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
578
|
+
// stored sessionId.
|
|
579
|
+
//
|
|
580
|
+
// #306: `/restart` ALWAYS spawns a fresh Claude Code process — never
|
|
581
|
+
// `--resume <id>`. The transcript `.jsonl` for the prior `spawnSessionId`
|
|
582
|
+
// is NOT guaranteed to have been flushed to disk before the prior
|
|
583
|
+
// adapter was hard-terminated (Windows `taskkill /T /F` is synchronous
|
|
584
|
+
// and unconditional). Claude Code then errors out with "No conversation
|
|
585
|
+
// found with session ID" and the new terminal drops to shell.
|
|
586
|
+
//
|
|
587
|
+
// Context preservation is already handled by the Step 5 replay above —
|
|
588
|
+
// we re-send recent messages to the fresh session. That's authoritative;
|
|
589
|
+
// the session-id `--resume` path was only ever a bonus on top. So we
|
|
590
|
+
// mint a new UUID on every restart, persist it to metadata, and never
|
|
591
|
+
// pass `resume: true` to the spawn.
|
|
592
|
+
const spawnSessionId = crypto.randomUUID();
|
|
593
|
+
await handle.signal(signals_1.updateMetadataSignal, { sessionId: spawnSessionId });
|
|
587
594
|
// Issue #184: re-resolve on the invoker host against the session's
|
|
588
595
|
// workDir (NOT the daemon's process.cwd — daemon runs elsewhere than
|
|
589
596
|
// the session's project, so the project-tier lookup needs the session's
|
|
@@ -598,8 +605,9 @@ function createOutboxActivities(client, config) {
|
|
|
598
605
|
host: targetHost,
|
|
599
606
|
attachmentId: token.attachmentId,
|
|
600
607
|
runId: token.runId,
|
|
601
|
-
|
|
602
|
-
|
|
608
|
+
// #306: `/restart` is always a fresh spawn (see comment above).
|
|
609
|
+
resume: false,
|
|
610
|
+
sessionId: spawnSessionId,
|
|
603
611
|
adapterId,
|
|
604
612
|
...(resolved ? {
|
|
605
613
|
agentDefinition: resolved.name,
|
|
@@ -608,7 +616,7 @@ function createOutboxActivities(client, config) {
|
|
|
608
616
|
} : {}),
|
|
609
617
|
}],
|
|
610
618
|
});
|
|
611
|
-
log(`Restart prepared for "${targetPlayerId}" — attachmentId=${token.attachmentId}, spawnEntryId=${spawnEntryId}, host=${targetHost}${fresh ?
|
|
619
|
+
log(`Restart prepared for "${targetPlayerId}" — attachmentId=${token.attachmentId}, spawnEntryId=${spawnEntryId}, host=${targetHost}, fresh sessionId=${spawnSessionId}${fresh ? ' (context replay skipped)' : ''}`);
|
|
612
620
|
return { success: true };
|
|
613
621
|
}
|
|
614
622
|
catch (err) {
|
package/dist/cli/commands.d.ts
CHANGED
|
@@ -1,28 +1,5 @@
|
|
|
1
1
|
import { CliOverrides } from '../config';
|
|
2
2
|
import { AgentType } from '../types';
|
|
3
|
-
interface StartOpts extends CliOverrides {
|
|
4
|
-
ensemble: string;
|
|
5
|
-
conductor: boolean;
|
|
6
|
-
replace?: boolean;
|
|
7
|
-
resume?: boolean;
|
|
8
|
-
name?: string;
|
|
9
|
-
skipPreflight?: boolean;
|
|
10
|
-
agent: AgentType;
|
|
11
|
-
dir?: string;
|
|
12
|
-
/**
|
|
13
|
-
* Issue #172: `conduct --lineup <name>` — load a lineup during conductor
|
|
14
|
-
* startup and apply the same initial-startup semantics as `up --lineup`:
|
|
15
|
-
* conductor instructions deferred, players held, banner shown. Only
|
|
16
|
-
* meaningful when `conductor: true`.
|
|
17
|
-
*/
|
|
18
|
-
lineup?: string;
|
|
19
|
-
/**
|
|
20
|
-
* Issue #172: opt out of the defer-conductor-instructions behavior.
|
|
21
|
-
* Forces the legacy immediate-start path even on `conduct --lineup`.
|
|
22
|
-
*/
|
|
23
|
-
noHold?: boolean;
|
|
24
|
-
}
|
|
25
|
-
export declare function start(opts: StartOpts): Promise<void>;
|
|
26
3
|
interface StatusOpts extends CliOverrides {
|
|
27
4
|
ensemble?: string;
|
|
28
5
|
}
|
|
@@ -50,24 +27,16 @@ interface UpOpts extends CliOverrides {
|
|
|
50
27
|
}
|
|
51
28
|
export declare function up(opts: UpOpts): Promise<void>;
|
|
52
29
|
interface DownOpts extends CliOverrides {
|
|
53
|
-
/** Explicitly specified ensemble name. If undefined, auto-detect from running workflows. */
|
|
54
|
-
ensemble?: string;
|
|
55
|
-
all: boolean;
|
|
56
30
|
removeMcp: boolean;
|
|
57
31
|
keepDaemon: boolean;
|
|
58
32
|
yes: boolean;
|
|
33
|
+
/** When true, terminate every workflow across every ensemble before
|
|
34
|
+
* stopping infra. Without it, workflows stay on the Temporal server and
|
|
35
|
+
* resume on the next `up`. */
|
|
36
|
+
destroy: boolean;
|
|
59
37
|
dir: string;
|
|
60
38
|
}
|
|
61
39
|
export declare function down(opts: DownOpts): Promise<void>;
|
|
62
|
-
interface StopOpts extends CliOverrides {
|
|
63
|
-
/** Stop a specific player by name. */
|
|
64
|
-
name?: string;
|
|
65
|
-
/** Stop all sessions in this ensemble. */
|
|
66
|
-
ensemble?: string;
|
|
67
|
-
/** Stop every session across all ensembles. */
|
|
68
|
-
all?: boolean;
|
|
69
|
-
}
|
|
70
|
-
export declare function stop(opts: StopOpts): Promise<void>;
|
|
71
40
|
interface AgentTypesCommandOpts {
|
|
72
41
|
subcommand?: string;
|
|
73
42
|
name?: string;
|
|
@@ -84,27 +53,17 @@ interface VerbOpts extends CliOverrides {
|
|
|
84
53
|
name: string;
|
|
85
54
|
ensemble?: string;
|
|
86
55
|
}
|
|
87
|
-
interface
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
force?: boolean;
|
|
91
|
-
contextMessages?: number;
|
|
92
|
-
/** PR-F: required when force-restarting a session attached to a different host. */
|
|
93
|
-
yesSteal?: string;
|
|
94
|
-
}
|
|
95
|
-
interface DetachCliOpts extends VerbOpts {
|
|
96
|
-
deadlineMs?: number;
|
|
97
|
-
}
|
|
98
|
-
interface DestroyCliOpts extends VerbOpts {
|
|
99
|
-
reason?: string;
|
|
100
|
-
}
|
|
101
|
-
interface MigrateCliOpts extends RestartCliOpts {
|
|
102
|
-
host: string;
|
|
56
|
+
interface DestroyCliOpts extends CliOverrides {
|
|
57
|
+
ensemble: string;
|
|
58
|
+
yes: boolean;
|
|
103
59
|
}
|
|
104
|
-
|
|
105
|
-
|
|
60
|
+
/**
|
|
61
|
+
* `claude-tempo destroy <ensemble> [-y]` — terminate every workflow in an
|
|
62
|
+
* ensemble (#288). Prompts with the ensemble name and workflow count unless
|
|
63
|
+
* `-y` is passed. The per-player destroy path lives in the TUI (`/destroy
|
|
64
|
+
* --player`).
|
|
65
|
+
*/
|
|
106
66
|
export declare function destroy(opts: DestroyCliOpts): Promise<void>;
|
|
107
|
-
export declare function migrate(opts: MigrateCliOpts): Promise<void>;
|
|
108
67
|
export declare function attachmentInfo(opts: VerbOpts): Promise<void>;
|
|
109
68
|
export interface HostsCliOpts extends CliOverrides {
|
|
110
69
|
ensemble?: string;
|
|
@@ -142,16 +101,15 @@ export interface RecallCliOpts extends VerbOpts {
|
|
|
142
101
|
}
|
|
143
102
|
export declare function recall(opts: RecallCliOpts): Promise<void>;
|
|
144
103
|
interface RestoreCliOpts extends CliOverrides {
|
|
145
|
-
|
|
146
|
-
name?: string;
|
|
147
|
-
ensemble?: string;
|
|
148
|
-
/** Restore every orphan in the namespace, respecting allowlist. */
|
|
149
|
-
all?: boolean;
|
|
150
|
-
/** Filter to orphans whose `preferredHost` matches this value. */
|
|
151
|
-
fromHost?: string;
|
|
152
|
-
/** List candidates without restoring. */
|
|
153
|
-
dryRun?: boolean;
|
|
104
|
+
ensemble: string;
|
|
154
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* `claude-tempo restore <ensemble>` — delegate to {@link TempoClient.restore},
|
|
108
|
+
* which reattaches orphans AND unpauses maestro + scheduler (#298 — the
|
|
109
|
+
* direct-to-`restoreOrphansOnce` path left the ensemble paused after a
|
|
110
|
+
* `shutdown → restore` roundtrip). The TUI home view (#290) is the picker
|
|
111
|
+
* surface; the CLI is the scriptable bulk operation, one ensemble at a time.
|
|
112
|
+
*/
|
|
155
113
|
export declare function restore(opts: RestoreCliOpts): Promise<void>;
|
|
156
114
|
interface EnsembleCommandOpts extends CliOverrides {
|
|
157
115
|
subcommand?: string;
|
|
@@ -163,14 +121,4 @@ interface ReleaseOpts extends CliOverrides {
|
|
|
163
121
|
}
|
|
164
122
|
/** Release all held sessions in an ensemble (unlock outbox, deliver initial messages). */
|
|
165
123
|
export declare function release(opts: ReleaseOpts): Promise<void>;
|
|
166
|
-
interface PauseResumeOpts extends CliOverrides {
|
|
167
|
-
ensemble: string;
|
|
168
|
-
/** Issue #172: when true on `resume`, also fan out `releaseHeldSignal` to every
|
|
169
|
-
* session so deferred task messages are delivered and outboxes unlocked in one shot. */
|
|
170
|
-
release?: boolean;
|
|
171
|
-
}
|
|
172
|
-
/** Pause an entire ensemble — sessions, scheduler, and maestro. */
|
|
173
|
-
export declare function pause(opts: PauseResumeOpts): Promise<void>;
|
|
174
|
-
/** Resume an entire ensemble — sessions, scheduler, and maestro. */
|
|
175
|
-
export declare function resume(opts: PauseResumeOpts): Promise<void>;
|
|
176
124
|
export {};
|