sisyphi 1.0.12 → 1.0.14

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.
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  globalConfigPath,
4
4
  projectConfigPath
5
- } from "./chunk-JXKUI4P6.js";
5
+ } from "./chunk-YGBGKMTF.js";
6
6
 
7
7
  // src/shared/config.ts
8
8
  import { readFileSync } from "fs";
@@ -84,4 +84,4 @@ export {
84
84
  exec,
85
85
  execSafe
86
86
  };
87
- //# sourceMappingURL=chunk-LWWRGQWM.js.map
87
+ //# sourceMappingURL=chunk-MMA43N67.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/config.ts","../src/shared/env.ts","../src/shared/exec.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { globalConfigPath, projectConfigPath } from './paths.js';\n\nexport interface WorktreeConfig {\n copy?: string[];\n clone?: string[];\n symlink?: string[];\n init?: string;\n}\n\nexport type EffortLevel = 'low' | 'medium' | 'high' | 'max';\n\nexport type KeyedWorktreeConfig = Record<string, WorktreeConfig>;\n\nexport interface Config {\n model?: string;\n tmuxSession?: string;\n orchestratorPrompt?: string;\n pollIntervalMs?: number;\n autoUpdate?: boolean;\n orchestratorEffort?: EffortLevel;\n agentEffort?: EffortLevel;\n editor?: string;\n repos?: string[];\n}\n\nconst DEFAULT_CONFIG: Config = {\n pollIntervalMs: 5000,\n orchestratorEffort: 'high',\n agentEffort: 'medium',\n};\n\nfunction readJsonFile(filePath: string): Partial<Config> {\n try {\n const content = readFileSync(filePath, 'utf-8');\n return JSON.parse(content) as Partial<Config>;\n } catch {\n return {};\n }\n}\n\nexport function loadConfig(cwd: string): Config {\n const global = readJsonFile(globalConfigPath());\n const project = readJsonFile(projectConfigPath(cwd));\n return { ...DEFAULT_CONFIG, ...global, ...project };\n}\n","/**\n * Build a PATH string that includes common binary directories\n * across package managers and platforms.\n *\n * Prepends known directories that exist on the system to the current PATH.\n * This ensures tmux commands can find binaries installed by Homebrew,\n * MacPorts, nix, and other package managers.\n */\nexport function augmentedPath(): string {\n const rawPath = process.env['PATH'];\n const basePath = rawPath !== undefined && rawPath.length > 0 ? rawPath : '/usr/bin:/bin';\n\n // Common binary directories across platforms/package managers.\n // Only prepend ones that aren't already in PATH.\n const candidates = [\n '/opt/homebrew/bin', // Homebrew (Apple Silicon macOS)\n '/opt/homebrew/sbin', // Homebrew sbin\n '/usr/local/bin', // Homebrew (Intel macOS), manual installs\n '/usr/local/sbin', // Manual installs\n '/opt/local/bin', // MacPorts\n '/opt/local/sbin', // MacPorts\n '/home/linuxbrew/.linuxbrew/bin', // Linuxbrew\n ];\n\n // Check for nix profile paths\n const nixProfile = process.env['NIX_PROFILES'];\n if (nixProfile) {\n for (const p of nixProfile.split(' ').reverse()) {\n candidates.push(`${p}/bin`);\n }\n }\n\n const existing = new Set(basePath.split(':'));\n const prepend = candidates.filter(dir => !existing.has(dir));\n\n return prepend.length > 0 ? `${prepend.join(':')}:${basePath}` : basePath;\n}\n\n/**\n * Environment variables for child processes that need access to\n * user-installed binaries (tmux, git, claude, etc.).\n */\nexport function execEnv(): Record<string, string | undefined> {\n return {\n ...process.env,\n PATH: augmentedPath(),\n };\n}\n","import { execSync } from 'node:child_process';\nimport { execEnv } from './env.js';\n\nexport const EXEC_ENV = execEnv();\n\nexport function exec(cmd: string, cwd?: string): string {\n return execSync(cmd, { encoding: 'utf-8', env: EXEC_ENV, cwd }).trim();\n}\n\nexport function execSafe(cmd: string, cwd?: string): string | null {\n try {\n return execSync(cmd, { encoding: 'utf-8', env: EXEC_ENV, cwd, stdio: ['pipe', 'pipe', 'pipe'] }).trim();\n } catch { return null; }\n}\n"],"mappings":";;;;;;;AAAA,SAAS,oBAAoB;AA0B7B,IAAM,iBAAyB;AAAA,EAC7B,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EACpB,aAAa;AACf;AAEA,SAAS,aAAa,UAAmC;AACvD,MAAI;AACF,UAAM,UAAU,aAAa,UAAU,OAAO;AAC9C,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEO,SAAS,WAAW,KAAqB;AAC9C,QAAM,SAAS,aAAa,iBAAiB,CAAC;AAC9C,QAAM,UAAU,aAAa,kBAAkB,GAAG,CAAC;AACnD,SAAO,EAAE,GAAG,gBAAgB,GAAG,QAAQ,GAAG,QAAQ;AACpD;;;ACrCO,SAAS,gBAAwB;AACtC,QAAM,UAAU,QAAQ,IAAI,MAAM;AAClC,QAAM,WAAW,YAAY,UAAa,QAAQ,SAAS,IAAI,UAAU;AAIzE,QAAM,aAAa;AAAA,IACjB;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,EACF;AAGA,QAAM,aAAa,QAAQ,IAAI,cAAc;AAC7C,MAAI,YAAY;AACd,eAAW,KAAK,WAAW,MAAM,GAAG,EAAE,QAAQ,GAAG;AAC/C,iBAAW,KAAK,GAAG,CAAC,MAAM;AAAA,IAC5B;AAAA,EACF;AAEA,QAAM,WAAW,IAAI,IAAI,SAAS,MAAM,GAAG,CAAC;AAC5C,QAAM,UAAU,WAAW,OAAO,SAAO,CAAC,SAAS,IAAI,GAAG,CAAC;AAE3D,SAAO,QAAQ,SAAS,IAAI,GAAG,QAAQ,KAAK,GAAG,CAAC,IAAI,QAAQ,KAAK;AACnE;AAMO,SAAS,UAA8C;AAC5D,SAAO;AAAA,IACL,GAAG,QAAQ;AAAA,IACX,MAAM,cAAc;AAAA,EACtB;AACF;;;AC/CA,SAAS,gBAAgB;AAGlB,IAAM,WAAW,QAAQ;AAEzB,SAAS,KAAK,KAAa,KAAsB;AACtD,SAAO,SAAS,KAAK,EAAE,UAAU,SAAS,KAAK,UAAU,IAAI,CAAC,EAAE,KAAK;AACvE;AAEO,SAAS,SAAS,KAAa,KAA6B;AACjE,MAAI;AACF,WAAO,SAAS,KAAK,EAAE,UAAU,SAAS,KAAK,UAAU,KAAK,OAAO,CAAC,QAAQ,QAAQ,MAAM,EAAE,CAAC,EAAE,KAAK;AAAA,EACxG,QAAQ;AAAE,WAAO;AAAA,EAAM;AACzB;","names":[]}
@@ -5,7 +5,7 @@ import {
5
5
  sessionsDir,
6
6
  socketPath,
7
7
  statePath
8
- } from "./chunk-JXKUI4P6.js";
8
+ } from "./chunk-YGBGKMTF.js";
9
9
 
10
10
  // src/shared/utils.ts
11
11
  function computeActiveTimeMs(session) {
@@ -261,4 +261,4 @@ export {
261
261
  buildCompanionContext,
262
262
  buildSessionContext
263
263
  };
264
- //# sourceMappingURL=chunk-T7ETTIQK.js.map
264
+ //# sourceMappingURL=chunk-Q6VQOUN3.js.map
@@ -1,29 +1,4 @@
1
1
  #!/usr/bin/env node
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __commonJS = (cb, mod) => function __require() {
9
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
2
 
28
3
  // src/shared/paths.ts
29
4
  import { homedir } from "os";
@@ -108,8 +83,6 @@ function worktreeBaseDir(cwd) {
108
83
  }
109
84
 
110
85
  export {
111
- __commonJS,
112
- __toESM,
113
86
  globalDir,
114
87
  socketPath,
115
88
  globalConfigPath,
@@ -137,4 +110,4 @@ export {
137
110
  worktreeConfigPath,
138
111
  worktreeBaseDir
139
112
  };
140
- //# sourceMappingURL=chunk-JXKUI4P6.js.map
113
+ //# sourceMappingURL=chunk-YGBGKMTF.js.map
@@ -1 +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 daemonUpdatingPath(): string {\n return join(globalDir(), 'updating');\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 messagesDir(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'messages');\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 roadmapPath(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'roadmap.md');\n}\n\nexport function goalPath(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'goal.md');\n}\n\nexport function logsDir(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'logs');\n}\n\nexport function cycleLogPath(cwd: string, sessionId: string, cycle: number): string {\n return join(logsDir(cwd, sessionId), `cycle-${String(cycle).padStart(3, '0')}.md`);\n}\n\n// Backwards compat for old sessions\nexport function legacyLogsPath(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'logs.md');\n}\n\nexport function snapshotsDir(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'snapshots');\n}\n\nexport function snapshotDir(cwd: string, sessionId: string, cycle: number): string {\n return join(snapshotsDir(cwd, sessionId), `cycle-${cycle}`);\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,qBAA6B;AAC3C,SAAO,KAAK,UAAU,GAAG,UAAU;AACrC;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,YAAY,KAAa,WAA2B;AAClE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,UAAU;AACpD;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,YAAY,KAAa,WAA2B;AAClE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,YAAY;AACtD;AAEO,SAAS,SAAS,KAAa,WAA2B;AAC/D,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,QAAQ,KAAa,WAA2B;AAC9D,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,MAAM;AAChD;AAEO,SAAS,aAAa,KAAa,WAAmB,OAAuB;AAClF,SAAO,KAAK,QAAQ,KAAK,SAAS,GAAG,SAAS,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC,KAAK;AACnF;AAGO,SAAS,eAAe,KAAa,WAA2B;AACrE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,aAAa,KAAa,WAA2B;AACnE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,WAAW;AACrD;AAEO,SAAS,YAAY,KAAa,WAAmB,OAAuB;AACjF,SAAO,KAAK,aAAa,KAAK,SAAS,GAAG,SAAS,KAAK,EAAE;AAC5D;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":[]}
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 daemonUpdatingPath(): string {\n return join(globalDir(), 'updating');\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 messagesDir(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'messages');\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 roadmapPath(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'roadmap.md');\n}\n\nexport function goalPath(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'goal.md');\n}\n\nexport function logsDir(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'logs');\n}\n\nexport function cycleLogPath(cwd: string, sessionId: string, cycle: number): string {\n return join(logsDir(cwd, sessionId), `cycle-${String(cycle).padStart(3, '0')}.md`);\n}\n\n// Backwards compat for old sessions\nexport function legacyLogsPath(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'logs.md');\n}\n\nexport function snapshotsDir(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'snapshots');\n}\n\nexport function snapshotDir(cwd: string, sessionId: string, cycle: number): string {\n return join(snapshotsDir(cwd, sessionId), `cycle-${cycle}`);\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,qBAA6B;AAC3C,SAAO,KAAK,UAAU,GAAG,UAAU;AACrC;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,YAAY,KAAa,WAA2B;AAClE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,UAAU;AACpD;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,YAAY,KAAa,WAA2B;AAClE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,YAAY;AACtD;AAEO,SAAS,SAAS,KAAa,WAA2B;AAC/D,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,QAAQ,KAAa,WAA2B;AAC9D,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,MAAM;AAChD;AAEO,SAAS,aAAa,KAAa,WAAmB,OAAuB;AAClF,SAAO,KAAK,QAAQ,KAAK,SAAS,GAAG,SAAS,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC,KAAK;AACnF;AAGO,SAAS,eAAe,KAAa,WAA2B;AACrE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,aAAa,KAAa,WAA2B;AACnE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,WAAW;AACrD;AAEO,SAAS,YAAY,KAAa,WAAmB,OAAuB;AACjF,SAAO,KAAK,aAAa,KAAK,SAAS,GAAG,SAAS,KAAK,EAAE;AAC5D;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
@@ -5,7 +5,7 @@ import {
5
5
  formatDuration,
6
6
  rawSend,
7
7
  statusColor
8
- } from "./chunk-T7ETTIQK.js";
8
+ } from "./chunk-Q6VQOUN3.js";
9
9
  import {
10
10
  shellQuote
11
11
  } from "./chunk-6G226ZK7.js";
@@ -16,11 +16,11 @@ import {
16
16
  globalDir,
17
17
  roadmapPath,
18
18
  socketPath
19
- } from "./chunk-JXKUI4P6.js";
19
+ } from "./chunk-YGBGKMTF.js";
20
20
 
21
21
  // src/cli/index.ts
22
22
  import { Command } from "commander";
23
- import { existsSync as existsSync5, mkdirSync as mkdirSync4 } from "fs";
23
+ import { existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
24
24
 
25
25
  // src/cli/commands/start.ts
26
26
  import { execSync as execSync5 } from "child_process";
@@ -39,10 +39,17 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync, unlinkSy
39
39
  import { homedir } from "os";
40
40
  import { join } from "path";
41
41
  var DEFAULT_KEY = "M-s";
42
+ var DEFAULT_HOME_KEY = "M-S";
42
43
  var SISYPHUS_CONF_MARKER = "# sisyphus-managed \u2014 do not edit";
43
44
  function cycleScriptPath() {
44
45
  return join(globalDir(), "bin", "sisyphus-cycle");
45
46
  }
47
+ function homeScriptPath() {
48
+ return join(globalDir(), "bin", "sisyphus-home");
49
+ }
50
+ function killPaneScriptPath() {
51
+ return join(globalDir(), "bin", "sisyphus-kill-pane");
52
+ }
46
53
  function sisyphusTmuxConfPath() {
47
54
  return join(globalDir(), "tmux.conf");
48
55
  }
@@ -72,12 +79,69 @@ for (( i=0; i<\${#sessions[@]}; i++ )); do
72
79
  done
73
80
  tmux switch-client -t "\${sessions[0]}"
74
81
  `;
82
+ var HOME_SCRIPT = `#!/bin/bash
83
+ # Jump to the home (non-sisyphus) session that has the dashboard window
84
+ cwd=$(tmux show-option -v @sisyphus_cwd 2>/dev/null)
85
+ [ -z "$cwd" ] && exit 0
86
+ while IFS= read -r name; do
87
+ # Skip sisyphus agent/orchestrator sessions
88
+ case "$name" in sisyphus-*) continue ;; esac
89
+ scwd=$(tmux show-option -t "$name" -v @sisyphus_cwd 2>/dev/null)
90
+ if [ "$scwd" = "$cwd" ]; then
91
+ tmux switch-client -t "$name"
92
+ # Focus the dashboard window if it exists
93
+ tmux select-window -t "$name:sisyphus-dashboard" 2>/dev/null
94
+ exit 0
95
+ fi
96
+ done < <(tmux list-sessions -F '#{session_name}')
97
+ `;
98
+ var KILL_PANE_SCRIPT = `#!/bin/bash
99
+ # prefix-x override for sisyphus sessions.
100
+ # If this is the last pane, switch to the home session before killing.
101
+ session=$(tmux display-message -p '#{session_name}')
102
+ pane_count=$(tmux list-panes -t "$session" -F '#{pane_id}' | wc -l | tr -d ' ')
103
+
104
+ if [ "$pane_count" -le 1 ]; then
105
+ # Last pane \u2014 find home session, switch there, then kill sisyphus session
106
+ cwd=$(tmux show-option -t "$session" -v @sisyphus_cwd 2>/dev/null)
107
+ if [ -n "$cwd" ]; then
108
+ while IFS= read -r name; do
109
+ case "$name" in sisyphus-*) continue ;; esac
110
+ scwd=$(tmux show-option -t "$name" -v @sisyphus_cwd 2>/dev/null)
111
+ if [ "$scwd" = "$cwd" ]; then
112
+ tmux switch-client -t "$name"
113
+ tmux select-window -t "$name:sisyphus-dashboard" 2>/dev/null
114
+ tmux kill-session -t "$session"
115
+ exit 0
116
+ fi
117
+ done < <(tmux list-sessions -F '#{session_name}')
118
+ fi
119
+ # No home session found \u2014 just kill the pane
120
+ tmux kill-pane
121
+ else
122
+ # Multiple panes \u2014 kill this one and rebalance
123
+ tmux kill-pane
124
+ tmux select-layout even-horizontal
125
+ fi
126
+ `;
75
127
  function installCycleScript() {
76
- const scriptPath = cycleScriptPath();
77
128
  mkdirSync(join(globalDir(), "bin"), { recursive: true });
129
+ const scriptPath = cycleScriptPath();
78
130
  writeFileSync(scriptPath, CYCLE_SCRIPT, "utf8");
79
131
  chmodSync(scriptPath, 493);
80
132
  }
133
+ function installHomeScript() {
134
+ mkdirSync(join(globalDir(), "bin"), { recursive: true });
135
+ const scriptPath = homeScriptPath();
136
+ writeFileSync(scriptPath, HOME_SCRIPT, "utf8");
137
+ chmodSync(scriptPath, 493);
138
+ }
139
+ function installKillPaneScript() {
140
+ mkdirSync(join(globalDir(), "bin"), { recursive: true });
141
+ const scriptPath = killPaneScriptPath();
142
+ writeFileSync(scriptPath, KILL_PANE_SCRIPT, "utf8");
143
+ chmodSync(scriptPath, 493);
144
+ }
81
145
  function getExistingBinding(key) {
82
146
  try {
83
147
  const output = execSync("tmux list-keys", { stdio: ["pipe", "pipe", "pipe"] }).toString();
@@ -98,8 +162,10 @@ function getExistingBinding(key) {
98
162
  function isSisyphusBinding(binding) {
99
163
  return binding.includes("sisyphus");
100
164
  }
101
- function setupTmuxKeybind(key = DEFAULT_KEY) {
165
+ function setupTmuxKeybind(key = DEFAULT_KEY, homeKey = DEFAULT_HOME_KEY) {
102
166
  installCycleScript();
167
+ installHomeScript();
168
+ installKillPaneScript();
103
169
  const existing = getExistingBinding(key);
104
170
  if (existing !== null && !isSisyphusBinding(existing)) {
105
171
  return {
@@ -108,10 +174,24 @@ function setupTmuxKeybind(key = DEFAULT_KEY) {
108
174
  existingBinding: existing
109
175
  };
110
176
  }
177
+ if (homeKey !== key) {
178
+ const existingHome = getExistingBinding(homeKey);
179
+ if (existingHome !== null && !isSisyphusBinding(existingHome)) {
180
+ return {
181
+ status: "conflict",
182
+ message: `Tmux key ${homeKey} is already bound to something else.`,
183
+ existingBinding: existingHome
184
+ };
185
+ }
186
+ }
111
187
  const confPath = sisyphusTmuxConfPath();
112
- const bindingLine = `bind-key -T root ${key} run-shell ${cycleScriptPath()}`;
188
+ const cycleBinding = `bind-key -T root ${key} run-shell ${cycleScriptPath()}`;
189
+ const homeBinding = `bind-key -T root ${homeKey} run-shell ${homeScriptPath()}`;
190
+ const killPaneOverride = `bind-key -T prefix x if-shell "tmux display-message -p '#{session_name}' | grep -q '^sisyphus-'" "run-shell ${killPaneScriptPath()}" "kill-pane \\; select-layout even-horizontal"`;
113
191
  writeFileSync(confPath, `${SISYPHUS_CONF_MARKER}
114
- ${bindingLine}
192
+ ${cycleBinding}
193
+ ${homeBinding}
194
+ ${killPaneOverride}
115
195
  `, "utf8");
116
196
  const userConf = userTmuxConfPath();
117
197
  const sourceLine = `source-file ${confPath}`;
@@ -128,12 +208,14 @@ ${bindingLine}
128
208
  }
129
209
  try {
130
210
  execSync(`tmux bind-key -T root ${key} run-shell ${cycleScriptPath()}`, { stdio: "pipe" });
211
+ execSync(`tmux bind-key -T root ${homeKey} run-shell ${homeScriptPath()}`, { stdio: "pipe" });
212
+ execSync(`tmux ${killPaneOverride}`, { stdio: "pipe" });
131
213
  } catch {
132
214
  }
133
215
  if (existing !== null && isSisyphusBinding(existing)) {
134
216
  return {
135
217
  status: "already-installed",
136
- message: `Tmux keybinding ${key} already configured for sisyphus.`
218
+ message: `Tmux keybindings ${key} (cycle) and ${homeKey} (dashboard) already configured for sisyphus.`
137
219
  };
138
220
  }
139
221
  const persistNote = persistedToConf ? "" : `
@@ -141,7 +223,7 @@ Note: No tmux.conf found. Add this to your tmux config for persistence:
141
223
  source-file ${confPath}`;
142
224
  return {
143
225
  status: "installed",
144
- message: `Tmux keybinding set: ${key} cycles sisyphus sessions${persistNote}`
226
+ message: `Tmux keybindings set: ${key} cycles sessions, ${homeKey} jumps to dashboard${persistNote}`
145
227
  };
146
228
  }
147
229
  function removeTmuxKeybind() {
@@ -158,9 +240,14 @@ function removeTmuxKeybind() {
158
240
  if (existsSync(confPath)) {
159
241
  unlinkSync(confPath);
160
242
  }
161
- const scriptPath = cycleScriptPath();
162
- if (existsSync(scriptPath)) {
163
- unlinkSync(scriptPath);
243
+ try {
244
+ execSync("tmux bind-key -T prefix x kill-pane \\; select-layout even-horizontal", { stdio: "pipe" });
245
+ } catch {
246
+ }
247
+ for (const scriptPath of [cycleScriptPath(), homeScriptPath(), killPaneScriptPath()]) {
248
+ if (existsSync(scriptPath)) {
249
+ unlinkSync(scriptPath);
250
+ }
164
251
  }
165
252
  }
166
253
 
@@ -489,6 +576,10 @@ Control:`);
489
576
  });
490
577
  }
491
578
 
579
+ // src/cli/commands/spawn.ts
580
+ import { existsSync as existsSync3 } from "fs";
581
+ import { join as join4 } from "path";
582
+
492
583
  // src/cli/stdin.ts
493
584
  function readStdin() {
494
585
  if (process.stdin.isTTY) return Promise.resolve(null);
@@ -505,7 +596,7 @@ function readStdin() {
505
596
 
506
597
  // src/cli/commands/spawn.ts
507
598
  function registerSpawn(program2) {
508
- 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) => {
599
+ 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").option("--repo <name>", "Repo subdirectory to use for this agent").action(async (positionalInstruction, opts) => {
509
600
  assertTmux();
510
601
  const sessionId = process.env.SISYPHUS_SESSION_ID;
511
602
  if (!sessionId) {
@@ -517,13 +608,35 @@ function registerSpawn(program2) {
517
608
  console.error("Error: --instruction is required (or pipe via stdin)");
518
609
  process.exit(1);
519
610
  }
611
+ const sisyphusCwd = process.env["SISYPHUS_CWD"] ?? process.cwd();
612
+ if (opts.repo && (opts.repo.includes("/") || opts.repo.includes("..") || opts.repo.includes("\\"))) {
613
+ console.error("Error: --repo must be a directory name, not a path");
614
+ process.exit(1);
615
+ }
616
+ if (opts.repo && opts.repo !== ".") {
617
+ const repoPath = join4(sisyphusCwd, opts.repo);
618
+ if (!existsSync3(repoPath)) {
619
+ console.error(`Error: repo directory does not exist: ${repoPath}`);
620
+ process.exit(1);
621
+ }
622
+ if (opts.worktree && !existsSync3(join4(repoPath, ".git"))) {
623
+ console.error(`Error: --worktree requires a git repo; no .git found at ${repoPath}`);
624
+ process.exit(1);
625
+ }
626
+ } else if (!opts.repo) {
627
+ if (!existsSync3(join4(sisyphusCwd, ".git"))) {
628
+ console.error("Error: --repo is required when session root is not a git repo.");
629
+ process.exit(1);
630
+ }
631
+ }
520
632
  const request = {
521
633
  type: "spawn",
522
634
  sessionId,
523
635
  agentType: opts.agentType,
524
636
  name: opts.name,
525
637
  instruction,
526
- ...opts.worktree ? { worktree: true } : {}
638
+ ...opts.worktree ? { worktree: true } : {},
639
+ ...opts.repo ? { repo: opts.repo } : {}
527
640
  };
528
641
  const response = await sendRequest(request);
529
642
  if (response.ok) {
@@ -843,7 +956,7 @@ function truncateTask(task, max) {
843
956
  }
844
957
  function registerList(program2) {
845
958
  program2.command("list").description("List sessions (defaults to current project)").option("-a, --all", "Show sessions from all projects").action(async (opts) => {
846
- const cwd = process.cwd();
959
+ const cwd = process.env["SISYPHUS_CWD"] ?? process.cwd();
847
960
  const request = { type: "list", cwd, all: opts.all };
848
961
  const response = await sendRequest(request);
849
962
  if (response.ok) {
@@ -864,8 +977,9 @@ function registerList(program2) {
864
977
  const status = `${color}${s.status}${RESET2}`;
865
978
  const agents = `${DIM2}${s.agentCount} agent(s)${RESET2}`;
866
979
  const task = truncateTask(s.task, 60);
980
+ const label = s.name ? `${s.name} ${DIM2}(${s.id.slice(0, 8)})${RESET2}` : s.id;
867
981
  const cwdLabel = opts.all && s.cwd ? ` ${DIM2}${basename(s.cwd)}${RESET2}` : "";
868
- console.log(` ${BOLD2}${s.id}${RESET2} ${status} ${agents} ${task}${cwdLabel}`);
982
+ console.log(` ${BOLD2}${label}${RESET2} ${status} ${agents} ${task}${cwdLabel}`);
869
983
  }
870
984
  if (filtered && totalCount && totalCount > sessions.length) {
871
985
  const otherCount = totalCount - sessions.length;
@@ -908,7 +1022,7 @@ function registerReport(program2) {
908
1022
  // src/cli/commands/resume.ts
909
1023
  function registerResume(program2) {
910
1024
  program2.command("resume").description("Respawn orchestrator with new instructions (for paused/completed sessions)").addHelpText("after", "\n Use `resume` to restart a paused or completed session with new instructions.\n Use `continue` to keep working on a completed session without new instructions.\n").argument("<session-id>", "Session ID to resume").argument("[message]", "Additional instructions for the orchestrator").action(async (sessionId, message) => {
911
- const cwd = process.cwd();
1025
+ const cwd = process.env["SISYPHUS_CWD"] ?? process.cwd();
912
1026
  const request = { type: "resume", sessionId, cwd, message };
913
1027
  const response = await sendRequest(request);
914
1028
  if (response.ok) {
@@ -1027,7 +1141,8 @@ function registerRollback(program2) {
1027
1141
  console.error("Error: cycle must be a positive integer");
1028
1142
  process.exit(1);
1029
1143
  }
1030
- const request = { type: "rollback", sessionId, cwd: process.cwd(), toCycle };
1144
+ const cwd = process.env["SISYPHUS_CWD"] ?? process.cwd();
1145
+ const request = { type: "rollback", sessionId, cwd, toCycle };
1031
1146
  const response = await sendRequest(request);
1032
1147
  if (response.ok) {
1033
1148
  const data = response.data;
@@ -1086,7 +1201,7 @@ function registerSetupKeybind(program2) {
1086
1201
 
1087
1202
  // src/cli/commands/doctor.ts
1088
1203
  import { execSync as execSync7 } from "child_process";
1089
- import { existsSync as existsSync3, statSync } from "fs";
1204
+ import { existsSync as existsSync4, statSync } from "fs";
1090
1205
  function checkNodeVersion() {
1091
1206
  const major = parseInt(process.versions.node.split(".")[0], 10);
1092
1207
  if (major < 22) {
@@ -1143,7 +1258,7 @@ function checkDaemonInstalled() {
1143
1258
  };
1144
1259
  }
1145
1260
  const pid = daemonPidPath();
1146
- if (existsSync3(pid)) {
1261
+ if (existsSync4(pid)) {
1147
1262
  return { name: "Daemon setup", status: "ok", detail: `PID file found at ${pid}` };
1148
1263
  }
1149
1264
  return {
@@ -1155,7 +1270,7 @@ function checkDaemonInstalled() {
1155
1270
  }
1156
1271
  function checkDaemonRunning() {
1157
1272
  const pid = daemonPidPath();
1158
- if (!existsSync3(pid)) {
1273
+ if (!existsSync4(pid)) {
1159
1274
  const fix = process.platform === "darwin" ? "launchctl load -w ~/Library/LaunchAgents/com.sisyphus.daemon.plist" : "sisyphusd & \u2014 or check if the process is running";
1160
1275
  return {
1161
1276
  name: "Daemon process",
@@ -1193,7 +1308,7 @@ function checkTmux() {
1193
1308
  }
1194
1309
  function checkCycleScript() {
1195
1310
  const path = cycleScriptPath();
1196
- if (!existsSync3(path)) {
1311
+ if (!existsSync4(path)) {
1197
1312
  return {
1198
1313
  name: "Cycle script",
1199
1314
  status: "fail",
@@ -1218,7 +1333,7 @@ function checkCycleScript() {
1218
1333
  function checkTmuxKeybind() {
1219
1334
  const existing = getExistingBinding(DEFAULT_KEY);
1220
1335
  if (existing === null) {
1221
- if (existsSync3(sisyphusTmuxConfPath())) {
1336
+ if (existsSync4(sisyphusTmuxConfPath())) {
1222
1337
  return {
1223
1338
  name: `Tmux keybind (${DEFAULT_KEY})`,
1224
1339
  status: "warn",
@@ -1244,7 +1359,7 @@ function checkTmuxKeybind() {
1244
1359
  }
1245
1360
  function checkGlobalDir() {
1246
1361
  const dir = globalDir();
1247
- if (existsSync3(dir)) {
1362
+ if (existsSync4(dir)) {
1248
1363
  return { name: "Data directory", status: "ok", detail: dir };
1249
1364
  }
1250
1365
  return { name: "Data directory", status: "warn", detail: `${dir} does not exist (created on first use)` };
@@ -1419,8 +1534,8 @@ function registerGettingStarted(program2) {
1419
1534
  }
1420
1535
 
1421
1536
  // src/cli/commands/init.ts
1422
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
1423
- import { join as join4 } from "path";
1537
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
1538
+ import { join as join5 } from "path";
1424
1539
  var DEFAULT_CONFIG = {};
1425
1540
  var ORCHESTRATOR_TEMPLATE = `# Custom Orchestrator Prompt
1426
1541
 
@@ -1431,9 +1546,9 @@ var ORCHESTRATOR_TEMPLATE = `# Custom Orchestrator Prompt
1431
1546
  function registerInit(program2) {
1432
1547
  program2.command("init").description("Initialize sisyphus configuration for this project").option("--orchestrator", "Also create a custom orchestrator prompt template").action((opts) => {
1433
1548
  const cwd = process.cwd();
1434
- const sisDir = join4(cwd, ".sisyphus");
1435
- const configPath = join4(sisDir, "config.json");
1436
- if (existsSync4(configPath)) {
1549
+ const sisDir = join5(cwd, ".sisyphus");
1550
+ const configPath = join5(sisDir, "config.json");
1551
+ if (existsSync5(configPath)) {
1437
1552
  console.log(`Already initialized: ${configPath}`);
1438
1553
  return;
1439
1554
  }
@@ -1441,8 +1556,8 @@ function registerInit(program2) {
1441
1556
  writeFileSync3(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2) + "\n", "utf-8");
1442
1557
  console.log(`Created ${configPath}`);
1443
1558
  if (opts.orchestrator) {
1444
- const orchPath = join4(sisDir, "orchestrator.md");
1445
- if (!existsSync4(orchPath)) {
1559
+ const orchPath = join5(sisDir, "orchestrator.md");
1560
+ if (!existsSync5(orchPath)) {
1446
1561
  writeFileSync3(orchPath, ORCHESTRATOR_TEMPLATE, "utf-8");
1447
1562
  console.log(`Created ${orchPath}`);
1448
1563
  }
@@ -1503,7 +1618,7 @@ Run 'sisyphus getting-started' for a complete usage guide.
1503
1618
  var args = process.argv.slice(2);
1504
1619
  var firstArg = args[0];
1505
1620
  var skipWelcome = ["doctor", "getting-started", "help", "--help", "-h", "init", "uninstall", "--version", "-V"];
1506
- if (!existsSync5(globalDir()) && firstArg && !skipWelcome.includes(firstArg)) {
1621
+ if (!existsSync6(globalDir()) && firstArg && !skipWelcome.includes(firstArg)) {
1507
1622
  mkdirSync4(globalDir(), { recursive: true });
1508
1623
  console.log("");
1509
1624
  console.log(" Welcome to Sisyphus \u2014 multi-agent orchestration for Claude Code.");