sisyphi 0.1.17 → 0.1.21
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 +37 -180
- package/dist/cli.js +40 -28
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +166 -92
- package/dist/daemon.js.map +1 -1
- package/dist/templates/agent-plugin/agents/review-plan.md +94 -68
- package/dist/templates/agent-plugin/agents/spec-draft.md +27 -51
- package/dist/templates/agent-plugin/hooks/hooks.json +3 -0
- package/dist/templates/agent-plugin/hooks/intercept-send-message.sh +11 -0
- package/dist/templates/agent-suffix.md +7 -9
- package/dist/templates/orchestrator-plugin/hooks/hooks.json +0 -10
- package/dist/templates/orchestrator-plugin/scripts/block-task.sh +8 -1
- package/dist/templates/orchestrator.md +22 -18
- package/package.json +1 -1
- package/templates/agent-plugin/agents/review-plan.md +94 -68
- package/templates/agent-plugin/agents/spec-draft.md +27 -51
- package/templates/agent-plugin/hooks/hooks.json +3 -0
- package/templates/agent-plugin/hooks/intercept-send-message.sh +11 -0
- package/templates/agent-suffix.md +7 -9
- package/templates/orchestrator-plugin/hooks/hooks.json +0 -10
- package/templates/orchestrator-plugin/scripts/block-task.sh +8 -1
- package/templates/orchestrator.md +22 -18
- package/dist/templates/orchestrator-plugin/scripts/stop-suggest.sh +0 -12
- package/templates/orchestrator-plugin/scripts/stop-suggest.sh +0 -12
package/README.md
CHANGED
|
@@ -29,39 +29,21 @@
|
|
|
29
29
|
|
|
30
30
|
A tmux-integrated orchestration daemon for [Claude Code](https://docs.anthropic.com/en/docs/claude-code) multi-agent workflows.
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
## What this is
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
Sisyphus is a thin orchestration layer on top of Claude Code. It doesn't replace Claude Code or wrap it in some abstraction — it just runs multiple Claude Code instances in tmux panes and coordinates them. Every agent is a real `claude` process with full access to your codebase, your tools, your CLAUDE.md, your hooks. You keep all the steerability of Claude Code; sisyphus just handles the "run N of them in parallel and loop until done" part.
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
▼
|
|
40
|
-
┌─────────────┐
|
|
41
|
-
│ Orchestrator │ ◄── Reads state, plans work, spawns agents
|
|
42
|
-
└──────┬──────┘
|
|
43
|
-
│ sisyphus spawn (×N)
|
|
44
|
-
▼
|
|
45
|
-
┌─────┐ ┌─────┐ ┌─────┐
|
|
46
|
-
│ A-1 │ │ A-2 │ │ A-3 │ ◄── Parallel Claude agents in tmux panes
|
|
47
|
-
└──┬──┘ └──┬──┘ └──┬──┘
|
|
48
|
-
│ │ │
|
|
49
|
-
▼ ▼ ▼
|
|
50
|
-
sisyphus submit (each agent reports back)
|
|
51
|
-
│
|
|
52
|
-
▼
|
|
53
|
-
┌─────────────┐
|
|
54
|
-
│ Orchestrator │ ◄── Respawned with updated state (next cycle)
|
|
55
|
-
└─────────────┘
|
|
56
|
-
```
|
|
36
|
+
If you're familiar with the [Ralph Wiggum loop](https://ghuntley.com/ralph/) — `while true; do claude --prompt task.md; done` — sisyphus is that idea taken further. Instead of one agent in a loop, you get an orchestrator that decomposes work into parallel agents, each looping independently, with structured state that persists across cycles. The orchestrator itself is in a Ralph loop: it plans, spawns agents, gets killed, and respawns fresh with all the results. Same principle, more leverage.
|
|
37
|
+
|
|
38
|
+
## How it works
|
|
57
39
|
|
|
58
|
-
|
|
59
|
-
2. **Orchestrator** decomposes it, spawns agents, yields
|
|
60
|
-
3. **Agents** work in parallel tmux panes, send progress reports, submit when done
|
|
61
|
-
4. **Daemon** detects completion, respawns orchestrator with updated state
|
|
62
|
-
5. **Orchestrator** reviews reports, spawns more agents or completes the session
|
|
40
|
+
Most hard tasks aren't hard because any single piece is difficult — they're hard because there are many pieces and context gets lost between them. A developer working a 12-file refactor holds it all in their head until they don't, then makes a mistake three files from the end because they forgot a constraint from the beginning.
|
|
63
41
|
|
|
64
|
-
|
|
42
|
+
Sisyphus solves this structurally. An **orchestrator** Claude instance reads the full task, breaks it into subtasks, and spawns parallel **agent** Claude instances — each in its own tmux pane with a focused instruction. Agents work simultaneously, submit reports when they're done, and the orchestrator respawns to review progress and plan the next round.
|
|
43
|
+
|
|
44
|
+
The key mechanism: **the orchestrator is stateless**. After it spawns agents and yields, it gets killed. When all agents finish, the daemon respawns a fresh orchestrator with the complete session state — every agent report, every cycle's history, the running plan. This means the orchestrator never degrades. Cycle 1 and cycle 15 get the same quality of reasoning, because each cycle starts with a full context window and a clean slate. The boulder rolls back down; Sisyphus walks back down after it, picks it up, and pushes again — but this time he remembers everything from every previous push.
|
|
45
|
+
|
|
46
|
+
The daemon handles the lifecycle: spawning panes, detecting when agents finish, persisting state to disk, respawning the orchestrator. You just describe what you want built and watch it work.
|
|
65
47
|
|
|
66
48
|
## Requirements
|
|
67
49
|
|
|
@@ -75,190 +57,65 @@ The orchestrator is stateless — it's killed after yielding and respawned fresh
|
|
|
75
57
|
npm install -g sisyphi
|
|
76
58
|
```
|
|
77
59
|
|
|
78
|
-
|
|
79
|
-
- `sisyphus` — the CLI for interacting with sessions
|
|
80
|
-
- `sisyphusd` — the background daemon
|
|
81
|
-
|
|
82
|
-
### Claude Code Plugin (optional)
|
|
83
|
-
|
|
84
|
-
The companion plugin on the [crouton-kit](https://github.com/CaptainCrouton89/crouton-kit) marketplace adds specialized agent types and an orchestration skill with task breakdown patterns for common workflows (bug fixes, feature builds, refactors, reviews, etc.).
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
claude plugins install CaptainCrouton89/crouton-kit sisyphus
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
This makes `sisyphus:debug`, `sisyphus:implement`, `sisyphus:plan`, and other agent types available for `sisyphus spawn --agent-type`.
|
|
91
|
-
|
|
92
|
-
## Quick Start
|
|
60
|
+
The daemon starts automatically on first use via launchd. It auto-updates when new versions are published.
|
|
93
61
|
|
|
94
|
-
|
|
62
|
+
## Usage
|
|
95
63
|
|
|
96
|
-
|
|
97
|
-
sisyphusd
|
|
98
|
-
```
|
|
64
|
+
Sisyphus is a CLI that Claude Code calls for you. You tell Claude to use it, and Claude handles the rest — calling `sisyphus start`, writing the task description, and kicking off the orchestration loop.
|
|
99
65
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
To run it persistently on macOS, use launchd — create `~/Library/LaunchAgents/com.sisyphus.daemon.plist`:
|
|
103
|
-
|
|
104
|
-
```xml
|
|
105
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
106
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
107
|
-
<plist version="1.0">
|
|
108
|
-
<dict>
|
|
109
|
-
<key>Label</key>
|
|
110
|
-
<string>com.sisyphus.daemon</string>
|
|
111
|
-
<key>ProgramArguments</key>
|
|
112
|
-
<array>
|
|
113
|
-
<string>sisyphusd</string>
|
|
114
|
-
</array>
|
|
115
|
-
<key>KeepAlive</key>
|
|
116
|
-
<true/>
|
|
117
|
-
<key>RunAtLoad</key>
|
|
118
|
-
<true/>
|
|
119
|
-
<key>StandardOutPath</key>
|
|
120
|
-
<string>~/.sisyphus/daemon.log</string>
|
|
121
|
-
<key>StandardErrorPath</key>
|
|
122
|
-
<string>~/.sisyphus/daemon.log</string>
|
|
123
|
-
</dict>
|
|
124
|
-
</plist>
|
|
125
|
-
```
|
|
66
|
+
In Claude Code, just say something like:
|
|
126
67
|
|
|
127
|
-
|
|
68
|
+
> Use sisyphus to migrate our REST API from Express to Hono. The API lives in src/api/ with 14 route files...
|
|
128
69
|
|
|
129
|
-
|
|
130
|
-
launchctl load ~/Library/LaunchAgents/com.sisyphus.daemon.plist
|
|
131
|
-
```
|
|
70
|
+
Claude will call `sisyphus start` with a detailed task description, and tmux panes will start appearing with parallel agents working on your codebase.
|
|
132
71
|
|
|
133
|
-
|
|
72
|
+
### Setting up a slash command (recommended)
|
|
134
73
|
|
|
135
|
-
|
|
136
|
-
sisyphus uninstall # Unload from launchd
|
|
137
|
-
sisyphus uninstall --purge # Also remove ~/.sisyphus data
|
|
138
|
-
```
|
|
74
|
+
Create a file at `.claude/commands/sisyphus-begin.md` in your project:
|
|
139
75
|
|
|
140
|
-
|
|
76
|
+
~~~markdown
|
|
77
|
+
Run `sisyphus start` with a detailed task description:
|
|
141
78
|
|
|
142
79
|
```bash
|
|
143
|
-
sisyphus start "
|
|
80
|
+
sisyphus start "your task description"
|
|
144
81
|
```
|
|
145
82
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
### 3. Watch it work
|
|
83
|
+
**Write a thorough task description.** Include what needs to be built or fixed, where relevant code lives, what done looks like, constraints or preferences, and adjacent concerns (don't break X, keep Y working). More context produces better results — the orchestrator figures out how to break it down.
|
|
149
84
|
|
|
85
|
+
**Example:**
|
|
150
86
|
```bash
|
|
151
|
-
sisyphus
|
|
152
|
-
sisyphus list # List sessions in current project
|
|
153
|
-
sisyphus list --all # List sessions across all projects
|
|
87
|
+
sisyphus start "Rip out our hand-rolled RBAC system and replace it with a proper policy engine. Current implementation is scattered across 20+ middleware files in src/middleware/auth/ that each do their own role checks with hardcoded string comparisons. Replace with a centralized policy engine in src/auth/policies/ using a declarative permission model — define resources, actions, and role mappings in a single config, then write one middleware that evaluates policies. Migrate every route that currently calls requireRole() or checkPermission() to the new system. The admin panel (src/routes/admin/) has the most complex rules including org-scoped permissions and delegated access — those need to work exactly as before. Add integration tests that cover the full matrix: superadmin, org-admin, member, and guest across every protected endpoint. Don't break the public API routes in src/routes/v1/public/. The existing test suite (npm test) must pass when you're done."
|
|
154
88
|
```
|
|
89
|
+
~~~
|
|
155
90
|
|
|
156
|
-
|
|
91
|
+
Then in Claude Code, type `/sisyphus-begin` followed by your task and Claude will use sisyphus to orchestrate it.
|
|
157
92
|
|
|
158
|
-
|
|
93
|
+
Alternatively, add a note to your `CLAUDE.md`:
|
|
159
94
|
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
sisyphus
|
|
95
|
+
```markdown
|
|
96
|
+
## Sisyphus
|
|
97
|
+
For large tasks, use the `sisyphus` CLI to orchestrate parallel agents.
|
|
98
|
+
Run `sisyphus start "detailed task description"` inside tmux.
|
|
164
99
|
```
|
|
165
100
|
|
|
166
|
-
|
|
101
|
+
### Monitoring and stopping
|
|
167
102
|
|
|
168
103
|
```bash
|
|
169
|
-
#
|
|
170
|
-
sisyphus
|
|
171
|
-
sisyphus status [session-id] # Session state (defaults to active session)
|
|
172
|
-
sisyphus list [-a, --all] # List sessions (--all for cross-project)
|
|
173
|
-
sisyphus resume <id> [message] # Resume paused session
|
|
174
|
-
sisyphus kill <id> # Kill session and all agents
|
|
175
|
-
sisyphus uninstall [--purge] [-y] # Unload daemon from launchd
|
|
176
|
-
|
|
177
|
-
# Daemon management
|
|
178
|
-
sisyphusd # Start the daemon
|
|
179
|
-
sisyphusd stop # Stop the daemon
|
|
180
|
-
sisyphusd restart # Restart the daemon
|
|
181
|
-
|
|
182
|
-
# Used by the orchestrator/agents (not typically run manually):
|
|
183
|
-
sisyphus spawn --agent-type <t> --name <n> --instruction "..."
|
|
184
|
-
sisyphus spawn --agent-type <t> --name <n> --instruction "..." --worktree
|
|
185
|
-
sisyphus yield [--prompt "next cycle context"]
|
|
186
|
-
sisyphus complete --report "summary" # Mark session done
|
|
187
|
-
sisyphus submit --report "findings" # Agent submits final report
|
|
188
|
-
sisyphus report --message "progress" # Agent sends progress update
|
|
104
|
+
sisyphus status # Check session state
|
|
105
|
+
sisyphus kill <session-id> # Stop everything
|
|
189
106
|
```
|
|
190
107
|
|
|
191
|
-
Both `yield`, `submit`, and `report` support stdin piping for long content:
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
echo "detailed report" | sisyphus submit
|
|
195
|
-
echo "progress update" | sisyphus report
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
## Git Worktree Isolation
|
|
199
|
-
|
|
200
|
-
Agents can work in isolated git worktrees to avoid conflicts when multiple agents edit files in parallel:
|
|
201
|
-
|
|
202
|
-
```bash
|
|
203
|
-
sisyphus spawn --agent-type sisyphus:implement --name "auth" \
|
|
204
|
-
--instruction "implement auth module" --worktree
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
With `--worktree`, the daemon:
|
|
208
|
-
1. Creates a new branch (`sisyphus/{session}/{agent-id}`) and worktree
|
|
209
|
-
2. Symlinks `.sisyphus` and `.claude` directories into the worktree
|
|
210
|
-
3. Runs bootstrap commands from `.sisyphus/worktree.json` (copy files, install deps, etc.)
|
|
211
|
-
4. Automatically merges the agent's branch back when the agent submits
|
|
212
|
-
|
|
213
|
-
Configure worktree bootstrap in `.sisyphus/worktree.json`:
|
|
214
|
-
|
|
215
|
-
```json
|
|
216
|
-
{
|
|
217
|
-
"symlink": [".env", "node_modules"],
|
|
218
|
-
"copy": ["package.json"],
|
|
219
|
-
"init": "npm install"
|
|
220
|
-
}
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
## Architecture
|
|
224
|
-
|
|
225
|
-
Three layers communicating over a Unix socket (`~/.sisyphus/daemon.sock`):
|
|
226
|
-
|
|
227
|
-
- **CLI** (`sisyphus`) — Commander.js program that sends JSON requests to the daemon
|
|
228
|
-
- **Daemon** (`sisyphusd`) — Manages sessions, spawns/monitors tmux panes, tracks state
|
|
229
|
-
- **Shared** — Types, protocol definitions, config resolution
|
|
230
|
-
|
|
231
|
-
### State & Persistence
|
|
232
|
-
|
|
233
|
-
State is persisted as JSON at `.sisyphus/sessions/{id}/state.json` (project-relative), written atomically via temp file + rename.
|
|
234
|
-
|
|
235
|
-
Each session directory contains:
|
|
236
|
-
```
|
|
237
|
-
.sisyphus/sessions/{id}/
|
|
238
|
-
├── state.json # Session state (atomic writes)
|
|
239
|
-
├── plan.md # Orchestrator memory — outstanding work
|
|
240
|
-
├── logs.md # Orchestrator memory — session log
|
|
241
|
-
├── prompts/ # Rendered system + user prompt files
|
|
242
|
-
├── reports/ # Agent report files
|
|
243
|
-
└── context/ # Persistent artifacts (specs, plans, explorations)
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
The orchestrator maintains `plan.md` and `logs.md` across cycles as persistent memory — these survive orchestrator respawns and give each new cycle continuity with previous work.
|
|
247
|
-
|
|
248
108
|
## Configuration
|
|
249
109
|
|
|
250
|
-
|
|
110
|
+
Project (`.sisyphus/config.json`) overrides global (`~/.sisyphus/config.json`):
|
|
251
111
|
|
|
252
112
|
```json
|
|
253
113
|
{
|
|
254
114
|
"model": "sonnet",
|
|
255
|
-
"
|
|
256
|
-
"tmuxSession": "my-session"
|
|
115
|
+
"autoUpdate": true
|
|
257
116
|
}
|
|
258
117
|
```
|
|
259
118
|
|
|
260
|
-
You can also override the orchestrator prompt per-project by placing a file at `.sisyphus/orchestrator.md`.
|
|
261
|
-
|
|
262
119
|
## License
|
|
263
120
|
|
|
264
121
|
MIT
|
package/dist/cli.js
CHANGED
|
@@ -229,17 +229,23 @@ function getTmuxWindow() {
|
|
|
229
229
|
|
|
230
230
|
// src/cli/commands/start.ts
|
|
231
231
|
function registerStart(program2) {
|
|
232
|
-
program2.command("start").description("Start a new sisyphus session").argument("<task>", "Task description for the orchestrator").action(async (task) => {
|
|
232
|
+
program2.command("start").description("Start a new sisyphus session").argument("<task>", "Task description for the orchestrator").option("-c, --context <context>", "Background context for the orchestrator").action(async (task, opts) => {
|
|
233
233
|
const tmuxSession = getTmuxSession();
|
|
234
234
|
const tmuxWindow = getTmuxWindow();
|
|
235
|
-
const request = { type: "start", task, cwd: process.cwd(), tmuxSession, tmuxWindow };
|
|
235
|
+
const request = { type: "start", task, context: opts.context, cwd: process.cwd(), tmuxSession, tmuxWindow };
|
|
236
236
|
const response = await sendRequest(request);
|
|
237
237
|
if (response.ok) {
|
|
238
238
|
const sessionId = response.data?.sessionId;
|
|
239
|
-
console.log(`
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
239
|
+
console.log(`Task handed off to sisyphus orchestrator (session ${sessionId})`);
|
|
240
|
+
console.log(`The orchestrator and its agents will handle this task autonomously \u2014 no further action needed from you.`);
|
|
241
|
+
console.log(`
|
|
242
|
+
Monitor:`);
|
|
243
|
+
console.log(` sisyphus status ${sessionId} # agents, cycles, reports`);
|
|
244
|
+
console.log(` tail -f ~/.sisyphus/daemon.log # daemon activity`);
|
|
245
|
+
console.log(`
|
|
246
|
+
Control:`);
|
|
247
|
+
console.log(` sisyphus resume ${sessionId} "new instructions" # respawn with follow-up`);
|
|
248
|
+
console.log(` sisyphus kill ${sessionId} # stop all agents and orchestrator`);
|
|
243
249
|
} else {
|
|
244
250
|
console.error(`Error: ${response.error}`);
|
|
245
251
|
process.exit(1);
|
|
@@ -247,21 +253,40 @@ function registerStart(program2) {
|
|
|
247
253
|
});
|
|
248
254
|
}
|
|
249
255
|
|
|
256
|
+
// src/cli/stdin.ts
|
|
257
|
+
function readStdin() {
|
|
258
|
+
if (process.stdin.isTTY) return Promise.resolve(null);
|
|
259
|
+
return new Promise((resolve2, reject) => {
|
|
260
|
+
const chunks = [];
|
|
261
|
+
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
262
|
+
process.stdin.on("end", () => {
|
|
263
|
+
const text = Buffer.concat(chunks).toString("utf-8").trim();
|
|
264
|
+
resolve2(text || null);
|
|
265
|
+
});
|
|
266
|
+
process.stdin.on("error", reject);
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
250
270
|
// src/cli/commands/spawn.ts
|
|
251
271
|
function registerSpawn(program2) {
|
|
252
|
-
program2.command("spawn").description("Spawn a new agent (orchestrator only)").option("--agent-type <type>", "Agent role label (default: worker)", "worker").requiredOption("--name <name>", "Agent name").
|
|
272
|
+
program2.command("spawn").description("Spawn a new agent (orchestrator only)").argument("[instruction]", "Task instruction for the agent").option("--agent-type <type>", "Agent role label (default: worker)", "worker").requiredOption("--name <name>", "Agent name").option("--instruction <instruction>", "Task instruction for the agent (or pipe via stdin)").option("--worktree", "Spawn agent in an isolated git worktree").action(async (positionalInstruction, opts) => {
|
|
253
273
|
assertTmux();
|
|
254
274
|
const sessionId = process.env.SISYPHUS_SESSION_ID;
|
|
255
275
|
if (!sessionId) {
|
|
256
276
|
console.error("Error: SISYPHUS_SESSION_ID environment variable not set");
|
|
257
277
|
process.exit(1);
|
|
258
278
|
}
|
|
279
|
+
const instruction = opts.instruction ?? positionalInstruction ?? await readStdin();
|
|
280
|
+
if (!instruction) {
|
|
281
|
+
console.error("Error: --instruction is required (or pipe via stdin)");
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
259
284
|
const request = {
|
|
260
285
|
type: "spawn",
|
|
261
286
|
sessionId,
|
|
262
287
|
agentType: opts.agentType,
|
|
263
288
|
name: opts.name,
|
|
264
|
-
instruction
|
|
289
|
+
instruction,
|
|
265
290
|
...opts.worktree ? { worktree: true } : {}
|
|
266
291
|
};
|
|
267
292
|
const response = await sendRequest(request);
|
|
@@ -279,22 +304,6 @@ function registerSpawn(program2) {
|
|
|
279
304
|
|
|
280
305
|
// src/cli/commands/submit.ts
|
|
281
306
|
import { execSync as execSync3 } from "child_process";
|
|
282
|
-
|
|
283
|
-
// src/cli/stdin.ts
|
|
284
|
-
function readStdin() {
|
|
285
|
-
if (process.stdin.isTTY) return Promise.resolve(null);
|
|
286
|
-
return new Promise((resolve2, reject) => {
|
|
287
|
-
const chunks = [];
|
|
288
|
-
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
289
|
-
process.stdin.on("end", () => {
|
|
290
|
-
const text = Buffer.concat(chunks).toString("utf-8").trim();
|
|
291
|
-
resolve2(text || null);
|
|
292
|
-
});
|
|
293
|
-
process.stdin.on("error", reject);
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// src/cli/commands/submit.ts
|
|
298
307
|
function isInWorktree() {
|
|
299
308
|
try {
|
|
300
309
|
const gitDir = execSync3("git rev-parse --git-dir", { encoding: "utf-8" }).trim();
|
|
@@ -350,7 +359,6 @@ function registerSubmit(program2) {
|
|
|
350
359
|
}
|
|
351
360
|
|
|
352
361
|
// src/cli/commands/yield.ts
|
|
353
|
-
import { writeFileSync as writeFileSync2 } from "fs";
|
|
354
362
|
function registerYield(program2) {
|
|
355
363
|
program2.command("yield").description("Yield control back to daemon (orchestrator only)").option("--prompt <text>", "Instructions for the next orchestrator cycle (or pipe via stdin)").action(async (opts) => {
|
|
356
364
|
assertTmux();
|
|
@@ -363,7 +371,6 @@ function registerYield(program2) {
|
|
|
363
371
|
const request = { type: "yield", sessionId, agentId: "orchestrator", nextPrompt };
|
|
364
372
|
const response = await sendRequest(request);
|
|
365
373
|
if (response.ok) {
|
|
366
|
-
writeFileSync2(`/tmp/sisyphus-exit-${sessionId}`, "");
|
|
367
374
|
console.log("Yielded. Waiting for agents to complete.");
|
|
368
375
|
} else {
|
|
369
376
|
console.error(`Error: ${response.error}`);
|
|
@@ -373,7 +380,6 @@ function registerYield(program2) {
|
|
|
373
380
|
}
|
|
374
381
|
|
|
375
382
|
// src/cli/commands/complete.ts
|
|
376
|
-
import { writeFileSync as writeFileSync3 } from "fs";
|
|
377
383
|
function registerComplete(program2) {
|
|
378
384
|
program2.command("complete").description("Mark session as completed (orchestrator only)").requiredOption("--report <report>", "Final completion report").action(async (opts) => {
|
|
379
385
|
assertTmux();
|
|
@@ -385,8 +391,10 @@ function registerComplete(program2) {
|
|
|
385
391
|
const request = { type: "complete", sessionId, report: opts.report };
|
|
386
392
|
const response = await sendRequest(request);
|
|
387
393
|
if (response.ok) {
|
|
388
|
-
writeFileSync3(`/tmp/sisyphus-exit-${sessionId}`, "");
|
|
389
394
|
console.log("Session completed.");
|
|
395
|
+
console.log(`
|
|
396
|
+
Follow up:`);
|
|
397
|
+
console.log(` sisyphus resume ${sessionId} "new instructions" # respawn orchestrator with follow-up`);
|
|
390
398
|
} else {
|
|
391
399
|
console.error(`Error: ${response.error}`);
|
|
392
400
|
process.exit(1);
|
|
@@ -463,6 +471,10 @@ function printSession(session) {
|
|
|
463
471
|
${BOLD}Session: ${session.id}${RESET}`);
|
|
464
472
|
console.log(` Status: ${status}`);
|
|
465
473
|
console.log(` Task: ${session.task}`);
|
|
474
|
+
if (session.context) {
|
|
475
|
+
const truncated = session.context.length > 120 ? session.context.slice(0, 120) + "..." : session.context;
|
|
476
|
+
console.log(` Context: ${truncated}`);
|
|
477
|
+
}
|
|
466
478
|
console.log(` CWD: ${session.cwd}`);
|
|
467
479
|
console.log(` Created: ${session.createdAt}`);
|
|
468
480
|
console.log(` Duration: ${sessionDuration}${session.completedAt ? "" : " (ongoing)"}`);
|