sisyphi 0.1.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/LICENSE +21 -0
- package/README.md +175 -0
- package/dist/chunk-5WP7O7D3.js +56 -0
- package/dist/chunk-5WP7O7D3.js.map +1 -0
- package/dist/cli.js +532 -0
- package/dist/cli.js.map +1 -0
- package/dist/daemon.js +983 -0
- package/dist/daemon.js.map +1 -0
- package/dist/templates/agent-suffix.md +61 -0
- package/dist/templates/orchestrator.md +152 -0
- package/package.json +49 -0
- package/templates/agent-suffix.md +61 -0
- package/templates/orchestrator.md +152 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-present Silas Rhyneer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# sisyphi
|
|
2
|
+
|
|
3
|
+
A tmux-integrated orchestration daemon for [Claude Code](https://docs.anthropic.com/en/docs/claude-code) multi-agent workflows.
|
|
4
|
+
|
|
5
|
+
A background daemon manages sessions where an **orchestrator** Claude instance breaks tasks into subtasks, spawns **agent** Claude instances in tmux panes, and coordinates their lifecycle through cycles. Agents work in parallel, submit reports, and the orchestrator respawns each cycle with fresh context to review progress and plan next steps.
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
You ──► sisyphus start "build auth system"
|
|
11
|
+
│
|
|
12
|
+
▼
|
|
13
|
+
┌─────────────┐
|
|
14
|
+
│ Orchestrator │ ◄── Reads state, plans work, spawns agents
|
|
15
|
+
└──────┬──────┘
|
|
16
|
+
│ sisyphus spawn (×N)
|
|
17
|
+
▼
|
|
18
|
+
┌─────┐ ┌─────┐ ┌─────┐
|
|
19
|
+
│ A-1 │ │ A-2 │ │ A-3 │ ◄── Parallel Claude agents in tmux panes
|
|
20
|
+
└──┬──┘ └──┬──┘ └──┬──┘
|
|
21
|
+
│ │ │
|
|
22
|
+
▼ ▼ ▼
|
|
23
|
+
sisyphus submit (each agent reports back)
|
|
24
|
+
│
|
|
25
|
+
▼
|
|
26
|
+
┌─────────────┐
|
|
27
|
+
│ Orchestrator │ ◄── Respawned with updated state (next cycle)
|
|
28
|
+
└─────────────┘
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
1. **You** run `sisyphus start` with a high-level task
|
|
32
|
+
2. **Orchestrator** decomposes it, adds tasks, spawns agents, yields
|
|
33
|
+
3. **Agents** work in parallel tmux panes, send progress reports, submit when done
|
|
34
|
+
4. **Daemon** detects completion, respawns orchestrator with updated state
|
|
35
|
+
5. **Orchestrator** reviews reports, spawns more agents or completes the session
|
|
36
|
+
|
|
37
|
+
The orchestrator is stateless — it's killed after yielding and respawned fresh each cycle with the full session state. This means it never runs out of context, no matter how many cycles a session takes.
|
|
38
|
+
|
|
39
|
+
## Requirements
|
|
40
|
+
|
|
41
|
+
- **Node.js** >= 22
|
|
42
|
+
- **tmux** (you must be inside a tmux session)
|
|
43
|
+
- **Claude Code** CLI (`claude`) installed and authenticated
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install -g sisyphi
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This gives you two commands:
|
|
52
|
+
- `sisyphus` — the CLI for interacting with sessions
|
|
53
|
+
- `sisyphusd` — the background daemon
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
### 1. Start the daemon
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
sisyphusd
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Or run it in the background. On macOS you can use launchd — create `~/Library/LaunchAgents/com.sisyphus.daemon.plist`:
|
|
64
|
+
|
|
65
|
+
```xml
|
|
66
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
67
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
68
|
+
<plist version="1.0">
|
|
69
|
+
<dict>
|
|
70
|
+
<key>Label</key>
|
|
71
|
+
<string>com.sisyphus.daemon</string>
|
|
72
|
+
<key>ProgramArguments</key>
|
|
73
|
+
<array>
|
|
74
|
+
<string>sisyphusd</string>
|
|
75
|
+
</array>
|
|
76
|
+
<key>KeepAlive</key>
|
|
77
|
+
<true/>
|
|
78
|
+
<key>RunAtLoad</key>
|
|
79
|
+
<true/>
|
|
80
|
+
<key>StandardOutPath</key>
|
|
81
|
+
<string>~/.sisyphus/daemon.log</string>
|
|
82
|
+
<key>StandardErrorPath</key>
|
|
83
|
+
<string>~/.sisyphus/daemon.log</string>
|
|
84
|
+
</dict>
|
|
85
|
+
</plist>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Then load it:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
launchctl load ~/Library/LaunchAgents/com.sisyphus.daemon.plist
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 2. Start a session (inside tmux)
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
sisyphus start "Refactor the authentication module to use JWT tokens"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The orchestrator spawns in a yellow tmux pane and begins planning.
|
|
101
|
+
|
|
102
|
+
### 3. Watch it work
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
sisyphus status # Check session state, tasks, agents
|
|
106
|
+
sisyphus tasks list # View task breakdown
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Agent panes appear as the orchestrator spawns them, color-coded by agent:
|
|
110
|
+
|
|
111
|
+
| Role | Color |
|
|
112
|
+
|------|-------|
|
|
113
|
+
| Orchestrator | Yellow |
|
|
114
|
+
| Agents | Blue, Green, Magenta, Cyan, Red, White (rotating) |
|
|
115
|
+
|
|
116
|
+
### 4. Resume or complete
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
sisyphus resume <session-id> # Resume a paused session
|
|
120
|
+
sisyphus resume <session-id> "focus on tests" # Resume with new instructions
|
|
121
|
+
sisyphus list # List all sessions
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## CLI Reference
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Session lifecycle
|
|
128
|
+
sisyphus start "task description" # Create session, launch orchestrator
|
|
129
|
+
sisyphus status # Current session state
|
|
130
|
+
sisyphus list # List all sessions
|
|
131
|
+
sisyphus resume <id> [message] # Resume paused session
|
|
132
|
+
sisyphus kill <id> # Kill a session
|
|
133
|
+
|
|
134
|
+
# These are used by the orchestrator/agents (not typically run manually):
|
|
135
|
+
sisyphus spawn --agent-type <t> --name <n> --instruction "..."
|
|
136
|
+
sisyphus yield # Orchestrator yields control
|
|
137
|
+
sisyphus complete --report "summary" # Mark session done
|
|
138
|
+
sisyphus submit --report "findings" # Agent submits final report
|
|
139
|
+
sisyphus report --message "progress" # Agent sends progress update
|
|
140
|
+
|
|
141
|
+
# Task management
|
|
142
|
+
sisyphus tasks list
|
|
143
|
+
sisyphus tasks add "description"
|
|
144
|
+
sisyphus tasks add "idea" --status draft
|
|
145
|
+
echo "long description" | sisyphus tasks add # stdin piping
|
|
146
|
+
sisyphus tasks update <taskId> --status done
|
|
147
|
+
sisyphus tasks update <taskId> --description "refined"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Architecture
|
|
151
|
+
|
|
152
|
+
Three layers communicating over a Unix socket (`~/.sisyphus/daemon.sock`):
|
|
153
|
+
|
|
154
|
+
- **CLI** (`sisyphus`) — Commander.js program that sends JSON requests to the daemon
|
|
155
|
+
- **Daemon** (`sisyphusd`) — Manages sessions, spawns/monitors tmux panes, tracks state
|
|
156
|
+
- **Shared** — Types, protocol definitions, config resolution
|
|
157
|
+
|
|
158
|
+
State is persisted as JSON at `.sisyphus/sessions/{id}/state.json` (relative to your project directory), written atomically via temp file + rename.
|
|
159
|
+
|
|
160
|
+
## Configuration
|
|
161
|
+
|
|
162
|
+
Config is layered: project (`.sisyphus/config.json`) overrides global (`~/.sisyphus/config.json`).
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"model": "sonnet",
|
|
167
|
+
"pollIntervalMs": 3000
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
You can also override the orchestrator prompt per-project by placing a file at `.sisyphus/orchestrator.md`.
|
|
172
|
+
|
|
173
|
+
## License
|
|
174
|
+
|
|
175
|
+
MIT
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/shared/paths.ts
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
function globalDir() {
|
|
7
|
+
return join(homedir(), ".sisyphus");
|
|
8
|
+
}
|
|
9
|
+
function socketPath() {
|
|
10
|
+
return join(globalDir(), "daemon.sock");
|
|
11
|
+
}
|
|
12
|
+
function globalConfigPath() {
|
|
13
|
+
return join(globalDir(), "config.json");
|
|
14
|
+
}
|
|
15
|
+
function daemonPidPath() {
|
|
16
|
+
return join(globalDir(), "daemon.pid");
|
|
17
|
+
}
|
|
18
|
+
function projectDir(cwd) {
|
|
19
|
+
return join(cwd, ".sisyphus");
|
|
20
|
+
}
|
|
21
|
+
function projectConfigPath(cwd) {
|
|
22
|
+
return join(projectDir(cwd), "config.json");
|
|
23
|
+
}
|
|
24
|
+
function projectOrchestratorPromptPath(cwd) {
|
|
25
|
+
return join(projectDir(cwd), "orchestrator.md");
|
|
26
|
+
}
|
|
27
|
+
function sessionsDir(cwd) {
|
|
28
|
+
return join(projectDir(cwd), "sessions");
|
|
29
|
+
}
|
|
30
|
+
function sessionDir(cwd, sessionId) {
|
|
31
|
+
return join(sessionsDir(cwd), sessionId);
|
|
32
|
+
}
|
|
33
|
+
function statePath(cwd, sessionId) {
|
|
34
|
+
return join(sessionDir(cwd, sessionId), "state.json");
|
|
35
|
+
}
|
|
36
|
+
function reportsDir(cwd, sessionId) {
|
|
37
|
+
return join(sessionDir(cwd, sessionId), "reports");
|
|
38
|
+
}
|
|
39
|
+
function reportFilePath(cwd, sessionId, agentId, suffix) {
|
|
40
|
+
return join(reportsDir(cwd, sessionId), `${agentId}-${suffix}.md`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
globalDir,
|
|
45
|
+
socketPath,
|
|
46
|
+
globalConfigPath,
|
|
47
|
+
daemonPidPath,
|
|
48
|
+
projectConfigPath,
|
|
49
|
+
projectOrchestratorPromptPath,
|
|
50
|
+
sessionsDir,
|
|
51
|
+
sessionDir,
|
|
52
|
+
statePath,
|
|
53
|
+
reportsDir,
|
|
54
|
+
reportFilePath
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=chunk-5WP7O7D3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/paths.ts"],"sourcesContent":["import { homedir } from 'node:os';\nimport { 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"],"mappings":";;;AAAA,SAAS,eAAe;AACxB,SAAS,YAAY;AAEd,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;AAMO,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;","names":[]}
|