sisyphi 0.1.2 → 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.
Files changed (73) hide show
  1. package/dist/{chunk-FWHTKXN5.js → chunk-N2BPQOO2.js} +23 -3
  2. package/dist/chunk-N2BPQOO2.js.map +1 -0
  3. package/dist/cli.js +85 -162
  4. package/dist/cli.js.map +1 -1
  5. package/dist/daemon.js +603 -186
  6. package/dist/daemon.js.map +1 -1
  7. package/dist/templates/CLAUDE.md +50 -0
  8. package/dist/templates/agent-plugin/.claude/agents/debug.md +39 -0
  9. package/dist/templates/agent-plugin/.claude/agents/plan.md +101 -0
  10. package/dist/templates/agent-plugin/.claude/agents/review-plan.md +81 -0
  11. package/dist/templates/agent-plugin/.claude/agents/review.md +56 -0
  12. package/dist/templates/agent-plugin/.claude/agents/spec-draft.md +73 -0
  13. package/dist/templates/agent-plugin/.claude/agents/test-spec.md +56 -0
  14. package/dist/templates/agent-plugin/.claude-plugin/plugin.json +5 -0
  15. package/dist/templates/agent-plugin/agents/CLAUDE.md +52 -0
  16. package/dist/templates/agent-plugin/agents/debug.md +39 -0
  17. package/dist/templates/agent-plugin/agents/operator.md +56 -0
  18. package/dist/templates/agent-plugin/agents/plan.md +101 -0
  19. package/dist/templates/agent-plugin/agents/review-plan.md +81 -0
  20. package/dist/templates/agent-plugin/agents/review.md +56 -0
  21. package/dist/templates/agent-plugin/agents/spec-draft.md +73 -0
  22. package/dist/templates/agent-plugin/agents/test-spec.md +56 -0
  23. package/dist/templates/agent-suffix.md +3 -1
  24. package/dist/templates/banner.txt +24 -6
  25. package/dist/templates/orchestrator-plugin/.claude/commands/begin.md +62 -0
  26. package/dist/templates/orchestrator-plugin/.claude/skills/orchestration/SKILL.md +40 -0
  27. package/dist/templates/orchestrator-plugin/.claude/skills/orchestration/task-patterns.md +222 -0
  28. package/dist/templates/orchestrator-plugin/.claude/skills/orchestration/workflow-examples.md +208 -0
  29. package/dist/templates/orchestrator-plugin/.claude-plugin/plugin.json +5 -0
  30. package/dist/templates/orchestrator-plugin/hooks/hooks.json +25 -0
  31. package/dist/templates/orchestrator-plugin/scripts/block-task.sh +4 -0
  32. package/dist/templates/orchestrator-plugin/scripts/stop-suggest.sh +4 -0
  33. package/dist/templates/orchestrator-plugin/skills/git-management/SKILL.md +111 -0
  34. package/dist/templates/orchestrator-plugin/skills/orchestration/SKILL.md +40 -0
  35. package/dist/templates/orchestrator-plugin/skills/orchestration/task-patterns.md +248 -0
  36. package/dist/templates/orchestrator-plugin/skills/orchestration/workflow-examples.md +237 -0
  37. package/dist/templates/orchestrator-settings.json +2 -0
  38. package/dist/templates/orchestrator.md +56 -49
  39. package/dist/templates/resources/.claude/agents/debug.md +39 -0
  40. package/dist/templates/resources/.claude/agents/plan.md +101 -0
  41. package/dist/templates/resources/.claude/agents/review-plan.md +81 -0
  42. package/dist/templates/resources/.claude/agents/review.md +56 -0
  43. package/dist/templates/resources/.claude/agents/spec-draft.md +73 -0
  44. package/dist/templates/resources/.claude/agents/test-spec.md +56 -0
  45. package/dist/templates/resources/.claude/commands/begin.md +62 -0
  46. package/dist/templates/resources/.claude/skills/orchestration/SKILL.md +40 -0
  47. package/dist/templates/resources/.claude/skills/orchestration/task-patterns.md +222 -0
  48. package/dist/templates/resources/.claude/skills/orchestration/workflow-examples.md +208 -0
  49. package/dist/templates/resources/.claude-plugin/plugin.json +8 -0
  50. package/package.json +2 -2
  51. package/templates/CLAUDE.md +50 -0
  52. package/templates/agent-plugin/.claude-plugin/plugin.json +5 -0
  53. package/templates/agent-plugin/agents/CLAUDE.md +52 -0
  54. package/templates/agent-plugin/agents/debug.md +39 -0
  55. package/templates/agent-plugin/agents/operator.md +56 -0
  56. package/templates/agent-plugin/agents/plan.md +101 -0
  57. package/templates/agent-plugin/agents/review-plan.md +81 -0
  58. package/templates/agent-plugin/agents/review.md +56 -0
  59. package/templates/agent-plugin/agents/spec-draft.md +73 -0
  60. package/templates/agent-plugin/agents/test-spec.md +56 -0
  61. package/templates/agent-suffix.md +3 -1
  62. package/templates/banner.txt +24 -6
  63. package/templates/orchestrator-plugin/.claude-plugin/plugin.json +5 -0
  64. package/templates/orchestrator-plugin/hooks/hooks.json +25 -0
  65. package/templates/orchestrator-plugin/scripts/block-task.sh +4 -0
  66. package/templates/orchestrator-plugin/scripts/stop-suggest.sh +4 -0
  67. package/templates/orchestrator-plugin/skills/git-management/SKILL.md +111 -0
  68. package/templates/orchestrator-plugin/skills/orchestration/SKILL.md +40 -0
  69. package/templates/orchestrator-plugin/skills/orchestration/task-patterns.md +248 -0
  70. package/templates/orchestrator-plugin/skills/orchestration/workflow-examples.md +237 -0
  71. package/templates/orchestrator-settings.json +2 -0
  72. package/templates/orchestrator.md +56 -49
  73. package/dist/chunk-FWHTKXN5.js.map +0 -1
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/shared/paths.ts
4
4
  import { homedir } from "os";
5
- import { join } from "path";
5
+ import { basename, join } from "path";
6
6
  function globalDir() {
7
7
  return join(homedir(), ".sisyphus");
8
8
  }
@@ -42,9 +42,24 @@ function reportsDir(cwd, sessionId) {
42
42
  function reportFilePath(cwd, sessionId, agentId, suffix) {
43
43
  return join(reportsDir(cwd, sessionId), `${agentId}-${suffix}.md`);
44
44
  }
45
+ function promptsDir(cwd, sessionId) {
46
+ return join(sessionDir(cwd, sessionId), "prompts");
47
+ }
45
48
  function contextDir(cwd, sessionId) {
46
49
  return join(sessionDir(cwd, sessionId), "context");
47
50
  }
51
+ function planPath(cwd, sessionId) {
52
+ return join(sessionDir(cwd, sessionId), "plan.md");
53
+ }
54
+ function logsPath(cwd, sessionId) {
55
+ return join(sessionDir(cwd, sessionId), "logs.md");
56
+ }
57
+ function worktreeConfigPath(cwd) {
58
+ return join(projectDir(cwd), "worktree.json");
59
+ }
60
+ function worktreeBaseDir(cwd) {
61
+ return join(cwd, "..", `${basename(cwd)}-sisyphus-wt`);
62
+ }
48
63
 
49
64
  export {
50
65
  globalDir,
@@ -59,6 +74,11 @@ export {
59
74
  statePath,
60
75
  reportsDir,
61
76
  reportFilePath,
62
- contextDir
77
+ promptsDir,
78
+ contextDir,
79
+ planPath,
80
+ logsPath,
81
+ worktreeConfigPath,
82
+ worktreeBaseDir
63
83
  };
64
- //# sourceMappingURL=chunk-FWHTKXN5.js.map
84
+ //# sourceMappingURL=chunk-N2BPQOO2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/paths.ts"],"sourcesContent":["import { homedir } from 'node:os';\nimport { basename, join } from 'node:path';\n\nexport function globalDir(): string {\n return join(homedir(), '.sisyphus');\n}\n\nexport function socketPath(): string {\n return join(globalDir(), 'daemon.sock');\n}\n\nexport function globalConfigPath(): string {\n return join(globalDir(), 'config.json');\n}\n\nexport function daemonLogPath(): string {\n return join(globalDir(), 'daemon.log');\n}\n\nexport function daemonPidPath(): string {\n return join(globalDir(), 'daemon.pid');\n}\n\nexport function projectDir(cwd: string): string {\n return join(cwd, '.sisyphus');\n}\n\nexport function projectConfigPath(cwd: string): string {\n return join(projectDir(cwd), 'config.json');\n}\n\nexport function projectOrchestratorPromptPath(cwd: string): string {\n return join(projectDir(cwd), 'orchestrator.md');\n}\n\nexport function sessionsDir(cwd: string): string {\n return join(projectDir(cwd), 'sessions');\n}\n\nexport function sessionDir(cwd: string, sessionId: string): string {\n return join(sessionsDir(cwd), sessionId);\n}\n\nexport function statePath(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'state.json');\n}\n\nexport function reportsDir(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'reports');\n}\n\nexport function reportFilePath(cwd: string, sessionId: string, agentId: string, suffix: string): string {\n return join(reportsDir(cwd, sessionId), `${agentId}-${suffix}.md`);\n}\n\nexport function promptsDir(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'prompts');\n}\n\nexport function contextDir(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'context');\n}\n\nexport function planPath(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'plan.md');\n}\n\nexport function logsPath(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'logs.md');\n}\n\nexport function worktreeConfigPath(cwd: string): string {\n return join(projectDir(cwd), 'worktree.json');\n}\n\nexport function worktreeBaseDir(cwd: string): string {\n return join(cwd, '..', `${basename(cwd)}-sisyphus-wt`);\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;AACxB,SAAS,UAAU,YAAY;AAExB,SAAS,YAAoB;AAClC,SAAO,KAAK,QAAQ,GAAG,WAAW;AACpC;AAEO,SAAS,aAAqB;AACnC,SAAO,KAAK,UAAU,GAAG,aAAa;AACxC;AAEO,SAAS,mBAA2B;AACzC,SAAO,KAAK,UAAU,GAAG,aAAa;AACxC;AAEO,SAAS,gBAAwB;AACtC,SAAO,KAAK,UAAU,GAAG,YAAY;AACvC;AAEO,SAAS,gBAAwB;AACtC,SAAO,KAAK,UAAU,GAAG,YAAY;AACvC;AAEO,SAAS,WAAW,KAAqB;AAC9C,SAAO,KAAK,KAAK,WAAW;AAC9B;AAEO,SAAS,kBAAkB,KAAqB;AACrD,SAAO,KAAK,WAAW,GAAG,GAAG,aAAa;AAC5C;AAEO,SAAS,8BAA8B,KAAqB;AACjE,SAAO,KAAK,WAAW,GAAG,GAAG,iBAAiB;AAChD;AAEO,SAAS,YAAY,KAAqB;AAC/C,SAAO,KAAK,WAAW,GAAG,GAAG,UAAU;AACzC;AAEO,SAAS,WAAW,KAAa,WAA2B;AACjE,SAAO,KAAK,YAAY,GAAG,GAAG,SAAS;AACzC;AAEO,SAAS,UAAU,KAAa,WAA2B;AAChE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,YAAY;AACtD;AAEO,SAAS,WAAW,KAAa,WAA2B;AACjE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,eAAe,KAAa,WAAmB,SAAiB,QAAwB;AACtG,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,GAAG,OAAO,IAAI,MAAM,KAAK;AACnE;AAEO,SAAS,WAAW,KAAa,WAA2B;AACjE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,WAAW,KAAa,WAA2B;AACjE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,SAAS,KAAa,WAA2B;AAC/D,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,SAAS,KAAa,WAA2B;AAC/D,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,mBAAmB,KAAqB;AACtD,SAAO,KAAK,WAAW,GAAG,GAAG,eAAe;AAC9C;AAEO,SAAS,gBAAgB,KAAqB;AACnD,SAAO,KAAK,KAAK,MAAM,GAAG,SAAS,GAAG,CAAC,cAAc;AACvD;","names":[]}
package/dist/cli.js CHANGED
@@ -3,14 +3,11 @@ import {
3
3
  daemonLogPath,
4
4
  globalDir,
5
5
  socketPath
6
- } from "./chunk-FWHTKXN5.js";
6
+ } from "./chunk-N2BPQOO2.js";
7
7
 
8
8
  // src/cli/index.ts
9
9
  import { Command } from "commander";
10
10
 
11
- // src/cli/commands/start.ts
12
- import { execSync as execSync2 } from "child_process";
13
-
14
11
  // src/cli/client.ts
15
12
  import { connect as connect2 } from "net";
16
13
 
@@ -163,41 +160,59 @@ function rawSend(request) {
163
160
  });
164
161
  }
165
162
  async function sendRequest(request) {
166
- try {
167
- return await rawSend(request);
168
- } catch (err) {
169
- const code = err.code;
170
- if (code === "ENOENT" || code === "ECONNREFUSED") {
171
- if (process.platform !== "darwin") {
172
- throw new Error(
173
- `Sisyphus daemon is not running.
174
- Start it manually: sisyphusd &
175
- Or check logs at: ~/.sisyphus/daemon.log`
176
- );
163
+ const sleep2 = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
164
+ const MAX_ATTEMPTS = 5;
165
+ const RETRY_DELAY_MS = 2e3;
166
+ let installedDaemon = false;
167
+ let lastErr;
168
+ for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
169
+ try {
170
+ return await rawSend(request);
171
+ } catch (err) {
172
+ lastErr = err;
173
+ const code = err.code;
174
+ if (code !== "ENOENT" && code !== "ECONNREFUSED") {
175
+ throw err;
176
+ }
177
+ if (attempt === MAX_ATTEMPTS) break;
178
+ if (process.platform === "darwin" && !installedDaemon) {
179
+ installedDaemon = true;
180
+ await ensureDaemonInstalled();
181
+ await waitForDaemon(5e3);
182
+ } else {
183
+ process.stderr.write(`Daemon not ready, retrying (${attempt}/${MAX_ATTEMPTS - 1})...
184
+ `);
185
+ await sleep2(RETRY_DELAY_MS);
177
186
  }
178
- await ensureDaemonInstalled();
179
- await waitForDaemon(5e3);
180
- return rawSend(request);
181
187
  }
182
- throw err;
183
188
  }
189
+ if (process.platform !== "darwin") {
190
+ throw new Error(
191
+ `Sisyphus daemon is not running.
192
+ Start it manually: sisyphusd &
193
+ Or check logs at: ~/.sisyphus/daemon.log`
194
+ );
195
+ }
196
+ throw lastErr;
184
197
  }
185
198
 
186
- // src/cli/commands/start.ts
187
- function getTmuxSession() {
188
- try {
189
- return execSync2('tmux display-message -p "#{session_name}"', { encoding: "utf8" }).trim();
190
- } catch {
191
- throw new Error("Not running inside tmux");
199
+ // src/cli/tmux.ts
200
+ import { execSync as execSync2 } from "child_process";
201
+ function assertTmux() {
202
+ if (!process.env.TMUX) {
203
+ throw new Error("Not running inside a tmux pane. Sisyphus requires tmux.");
192
204
  }
193
205
  }
206
+ function getTmuxSession() {
207
+ assertTmux();
208
+ return execSync2('tmux display-message -p "#{session_name}"', { encoding: "utf8" }).trim();
209
+ }
194
210
  function getTmuxWindow() {
195
- try {
196
- return execSync2('tmux display-message -p "#{window_id}"', { encoding: "utf8" }).trim();
197
- } catch {
198
- throw new Error("Not running inside tmux");
199
- }
211
+ assertTmux();
212
+ return execSync2('tmux display-message -p "#{window_id}"', { encoding: "utf8" }).trim();
200
213
  }
214
+
215
+ // src/cli/commands/start.ts
201
216
  function registerStart(program2) {
202
217
  program2.command("start").description("Start a new sisyphus session").argument("<task>", "Task description for the orchestrator").action(async (task) => {
203
218
  const tmuxSession = getTmuxSession();
@@ -219,7 +234,8 @@ function registerStart(program2) {
219
234
 
220
235
  // src/cli/commands/spawn.ts
221
236
  function registerSpawn(program2) {
222
- 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").requiredOption("--instruction <instruction>", "Task instruction for the agent").action(async (opts) => {
237
+ 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").requiredOption("--instruction <instruction>", "Task instruction for the agent").option("--worktree", "Spawn agent in an isolated git worktree").action(async (opts) => {
238
+ assertTmux();
223
239
  const sessionId = process.env.SISYPHUS_SESSION_ID;
224
240
  if (!sessionId) {
225
241
  console.error("Error: SISYPHUS_SESSION_ID environment variable not set");
@@ -230,7 +246,8 @@ function registerSpawn(program2) {
230
246
  sessionId,
231
247
  agentType: opts.agentType,
232
248
  name: opts.name,
233
- instruction: opts.instruction
249
+ instruction: opts.instruction,
250
+ ...opts.worktree ? { worktree: true } : {}
234
251
  };
235
252
  const response = await sendRequest(request);
236
253
  if (response.ok) {
@@ -262,6 +279,7 @@ function readStdin() {
262
279
  // src/cli/commands/submit.ts
263
280
  function registerSubmit(program2) {
264
281
  program2.command("submit").description("Submit work report and exit (agent only)").option("--report <report>", "Work report (or pipe via stdin)").action(async (opts) => {
282
+ assertTmux();
265
283
  const sessionId = process.env.SISYPHUS_SESSION_ID;
266
284
  const agentId = process.env.SISYPHUS_AGENT_ID;
267
285
  if (!sessionId || !agentId) {
@@ -288,6 +306,7 @@ function registerSubmit(program2) {
288
306
  // src/cli/commands/yield.ts
289
307
  function registerYield(program2) {
290
308
  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) => {
309
+ assertTmux();
291
310
  const sessionId = process.env.SISYPHUS_SESSION_ID;
292
311
  if (!sessionId) {
293
312
  console.error("Error: SISYPHUS_SESSION_ID environment variable not set");
@@ -308,6 +327,7 @@ function registerYield(program2) {
308
327
  // src/cli/commands/complete.ts
309
328
  function registerComplete(program2) {
310
329
  program2.command("complete").description("Mark session as completed (orchestrator only)").requiredOption("--report <report>", "Final completion report").action(async (opts) => {
330
+ assertTmux();
311
331
  const sessionId = process.env.SISYPHUS_SESSION_ID;
312
332
  if (!sessionId) {
313
333
  console.error("Error: SISYPHUS_SESSION_ID environment variable not set");
@@ -317,7 +337,6 @@ function registerComplete(program2) {
317
337
  const response = await sendRequest(request);
318
338
  if (response.ok) {
319
339
  console.log("Session completed.");
320
- console.log("All panes will close.");
321
340
  } else {
322
341
  console.error(`Error: ${response.error}`);
323
342
  process.exit(1);
@@ -339,16 +358,8 @@ var STATUS_COLORS = {
339
358
  // red
340
359
  crashed: "\x1B[31m",
341
360
  // red
342
- lost: "\x1B[90m",
361
+ lost: "\x1B[90m"
343
362
  // gray
344
- draft: "\x1B[2m",
345
- // dim
346
- pending: "\x1B[90m",
347
- // gray
348
- in_progress: "\x1B[33m",
349
- // yellow
350
- done: "\x1B[32m"
351
- // green
352
363
  };
353
364
  var RESET = "\x1B[0m";
354
365
  var BOLD = "\x1B[1m";
@@ -390,10 +401,6 @@ function formatAgent(agent) {
390
401
  }
391
402
  return line;
392
403
  }
393
- function formatTask(task) {
394
- const status = colorize(task.status, task.status);
395
- return ` ${task.id}: ${task.description} [${status}]`;
396
- }
397
404
  function formatCycle(cycle) {
398
405
  const duration = cycle.completedAt ? ` ${DIM}(${formatDuration(cycle.timestamp, cycle.completedAt)})${RESET}` : ` ${DIM}(running)${RESET}`;
399
406
  const agents = cycle.agentsSpawned.length > 0 ? ` \u2014 agents: ${cycle.agentsSpawned.join(", ")}` : "";
@@ -417,13 +424,6 @@ ${BOLD}Session: ${session.id}${RESET}`);
417
424
  console.log(formatCycle(cycle));
418
425
  }
419
426
  }
420
- if (session.tasks.length > 0) {
421
- console.log(`
422
- ${BOLD}Tasks:${RESET}`);
423
- for (const task of session.tasks) {
424
- console.log(formatTask(task));
425
- }
426
- }
427
427
  if (session.agents.length > 0) {
428
428
  console.log(`
429
429
  ${BOLD}Agents:${RESET}`);
@@ -451,112 +451,50 @@ function registerStatus(program2) {
451
451
  });
452
452
  }
453
453
 
454
- // src/cli/commands/tasks.ts
455
- function getSessionId() {
456
- const sessionId = process.env.SISYPHUS_SESSION_ID;
457
- if (!sessionId) {
458
- console.error("Error: SISYPHUS_SESSION_ID environment variable not set");
459
- process.exit(1);
460
- }
461
- return sessionId;
462
- }
463
- var STATUS_COLORS2 = {
464
- draft: "\x1B[2m",
465
- // dim
466
- pending: "\x1B[90m",
467
- // gray
468
- in_progress: "\x1B[33m",
469
- // yellow
470
- done: "\x1B[32m"
471
- // green
472
- };
473
- var RESET2 = "\x1B[0m";
474
- function registerTasks(program2) {
475
- const tasks = program2.command("tasks").description("Manage session tasks");
476
- tasks.command("add").description("Add a new task").argument("[description]", "Task description (or pipe via stdin)").option("--status <status>", "Initial status (draft|pending)", "pending").action(async (descriptionArg, opts) => {
477
- const description = descriptionArg ?? await readStdin();
478
- if (!description) {
479
- console.error("Error: provide a description argument or pipe via stdin");
480
- process.exit(1);
481
- }
482
- const sessionId = getSessionId();
483
- const request = { type: "tasks_add", sessionId, description, status: opts.status !== "pending" ? opts.status : void 0 };
484
- const response = await sendRequest(request);
485
- if (response.ok) {
486
- const taskId = response.data?.taskId;
487
- console.log(`Task added: ${taskId} [${opts.status}]`);
488
- } else {
489
- console.error(`Error: ${response.error}`);
490
- if (response.error?.includes("Unknown session")) console.error("Hint: run `sisyphus list` to see active sessions.");
491
- process.exit(1);
492
- }
493
- });
494
- tasks.command("update").description("Update a task").argument("<task-id>", "Task ID (e.g. t1)").option("--status <status>", "New status (draft|pending|in_progress|done)").option("--description <description>", "New description").action(async (taskId, opts) => {
495
- if (!opts.status && !opts.description) {
496
- console.error("Error: provide --status and/or --description");
497
- process.exit(1);
498
- }
499
- const sessionId = getSessionId();
500
- const request = { type: "tasks_update", sessionId, taskId, status: opts.status, description: opts.description };
501
- const response = await sendRequest(request);
502
- if (response.ok) {
503
- const parts = [];
504
- if (opts.status) parts.push(`status \u2192 ${opts.status}`);
505
- if (opts.description) parts.push(`description updated`);
506
- console.log(`Task ${taskId}: ${parts.join(", ")}`);
507
- } else {
508
- console.error(`Error: ${response.error}`);
509
- if (response.error?.includes("not found")) console.error("Hint: run `sisyphus tasks list` to see current tasks.");
510
- if (response.error?.includes("Unknown session")) console.error("Hint: run `sisyphus list` to see active sessions.");
511
- process.exit(1);
512
- }
513
- });
514
- tasks.command("list").description("List all tasks").action(async () => {
515
- const sessionId = getSessionId();
516
- const request = { type: "tasks_list", sessionId };
517
- const response = await sendRequest(request);
518
- if (response.ok) {
519
- const taskList = response.data?.tasks ?? [];
520
- if (taskList.length === 0) {
521
- console.log("No tasks");
522
- return;
523
- }
524
- for (const task of taskList) {
525
- const color = STATUS_COLORS2[task.status] ?? "";
526
- console.log(` ${task.id}: ${task.description} [${color}${task.status}${RESET2}]`);
527
- }
528
- } else {
529
- console.error(`Error: ${response.error}`);
530
- if (response.error?.includes("Unknown session")) console.error("Hint: run `sisyphus list` to see active sessions.");
531
- process.exit(1);
532
- }
533
- });
534
- }
535
-
536
454
  // src/cli/commands/list.ts
537
- var STATUS_COLORS3 = {
455
+ import { basename } from "path";
456
+ var STATUS_COLORS2 = {
538
457
  active: "\x1B[32m",
539
458
  paused: "\x1B[33m",
540
459
  completed: "\x1B[36m"
541
460
  };
542
- var RESET3 = "\x1B[0m";
461
+ var RESET2 = "\x1B[0m";
543
462
  var BOLD2 = "\x1B[1m";
544
463
  var DIM2 = "\x1B[2m";
464
+ function truncateTask(task, max) {
465
+ if (task.length <= max) return task;
466
+ return task.slice(0, max - 1) + "\u2026";
467
+ }
545
468
  function registerList(program2) {
546
- program2.command("list").description("List all sessions").action(async () => {
547
- const request = { type: "list" };
469
+ program2.command("list").description("List sessions (defaults to current project)").option("-a, --all", "Show sessions from all projects").action(async (opts) => {
470
+ const cwd = process.cwd();
471
+ const request = { type: "list", cwd, all: opts.all };
548
472
  const response = await sendRequest(request);
549
473
  if (response.ok) {
550
474
  const sessions = response.data?.sessions ?? [];
475
+ const totalCount = response.data?.totalCount;
476
+ const filtered = response.data?.filtered;
551
477
  if (sessions.length === 0) {
552
- console.log("No sessions");
478
+ if (filtered && totalCount && totalCount > 0) {
479
+ console.log(`No sessions in this project. ${totalCount} session(s) in other projects.`);
480
+ console.log(`${DIM2}Run ${RESET2}sisyphus list --all${DIM2} to show all.${RESET2}`);
481
+ } else {
482
+ console.log("No sessions");
483
+ }
553
484
  return;
554
485
  }
555
486
  for (const s of sessions) {
556
- const color = STATUS_COLORS3[s.status] ?? "";
557
- const status = `${color}${s.status}${RESET3}`;
558
- const agents = `${DIM2}${s.agentCount} agent(s)${RESET3}`;
559
- console.log(` ${BOLD2}${s.id}${RESET3} ${status} ${agents} ${s.task}`);
487
+ const color = STATUS_COLORS2[s.status] ?? "";
488
+ const status = `${color}${s.status}${RESET2}`;
489
+ const agents = `${DIM2}${s.agentCount} agent(s)${RESET2}`;
490
+ const task = truncateTask(s.task, 60);
491
+ const cwdLabel = opts.all && s.cwd ? ` ${DIM2}${basename(s.cwd)}${RESET2}` : "";
492
+ console.log(` ${BOLD2}${s.id}${RESET2} ${status} ${agents} ${task}${cwdLabel}`);
493
+ }
494
+ if (filtered && totalCount && totalCount > sessions.length) {
495
+ const otherCount = totalCount - sessions.length;
496
+ console.log(`
497
+ ${DIM2}${otherCount} more session(s) in other projects. Run ${RESET2}sisyphus list --all${DIM2} to show all.${RESET2}`);
560
498
  }
561
499
  } else {
562
500
  console.error(`Error: ${response.error}`);
@@ -568,6 +506,7 @@ function registerList(program2) {
568
506
  // src/cli/commands/report.ts
569
507
  function registerReport(program2) {
570
508
  program2.command("report").description("Send a progress report without exiting (agent only)").option("--message <message>", "Progress report content").action(async (opts) => {
509
+ assertTmux();
571
510
  const sessionId = process.env.SISYPHUS_SESSION_ID;
572
511
  const agentId = process.env.SISYPHUS_AGENT_ID;
573
512
  if (!sessionId || !agentId) {
@@ -591,25 +530,10 @@ function registerReport(program2) {
591
530
  }
592
531
 
593
532
  // src/cli/commands/resume.ts
594
- import { execSync as execSync3 } from "child_process";
595
- function getTmuxSession2() {
596
- try {
597
- return execSync3('tmux display-message -p "#{session_name}"', { encoding: "utf8" }).trim();
598
- } catch {
599
- throw new Error("Not running inside tmux");
600
- }
601
- }
602
- function getTmuxWindow2() {
603
- try {
604
- return execSync3('tmux display-message -p "#{window_id}"', { encoding: "utf8" }).trim();
605
- } catch {
606
- throw new Error("Not running inside tmux");
607
- }
608
- }
609
533
  function registerResume(program2) {
610
534
  program2.command("resume").description("Resume a paused session").argument("<session-id>", "Session ID to resume").argument("[message]", "Additional instructions for the orchestrator").action(async (sessionId, message) => {
611
- const tmuxSession = getTmuxSession2();
612
- const tmuxWindow = getTmuxWindow2();
535
+ const tmuxSession = getTmuxSession();
536
+ const tmuxWindow = getTmuxWindow();
613
537
  const cwd = process.cwd();
614
538
  const request = { type: "resume", sessionId, cwd, tmuxSession, tmuxWindow, message };
615
539
  const response = await sendRequest(request);
@@ -678,7 +602,6 @@ registerReport(program);
678
602
  registerYield(program);
679
603
  registerComplete(program);
680
604
  registerStatus(program);
681
- registerTasks(program);
682
605
  registerList(program);
683
606
  registerResume(program);
684
607
  registerKill(program);