claude-tmux 1.0.7 → 1.0.9
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 +8 -15
- package/dist/index.js +14 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,13 +31,12 @@ Add to your Claude Code MCP settings:
|
|
|
31
31
|
Launch a new Claude Code instance in a tmux session.
|
|
32
32
|
|
|
33
33
|
```
|
|
34
|
-
spawn(
|
|
34
|
+
spawn(name, prompt, workdir)
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
- `name`: Unique session name (e.g., 'refactor-auth', 'debug-api')
|
|
38
|
+
- `prompt`: Initial prompt to send to Claude
|
|
38
39
|
- `workdir`: Working directory for Claude to operate in
|
|
39
|
-
- `prompt`: Initial prompt to send to Claude on startup
|
|
40
|
-
- `dangerouslySkipPermissions`: Skip permission prompts for fully autonomous operation
|
|
41
40
|
|
|
42
41
|
### read
|
|
43
42
|
|
|
@@ -66,20 +65,14 @@ kill("task-name")
|
|
|
66
65
|
## Usage Pattern
|
|
67
66
|
|
|
68
67
|
```
|
|
69
|
-
spawn(
|
|
70
|
-
read(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
For steering mid-task:
|
|
75
|
-
|
|
76
|
-
```
|
|
77
|
-
send("task-name", "do something else")
|
|
78
|
-
read("task-name") → waits for completion, returns output
|
|
68
|
+
spawn(name, prompt, workdir) → start session
|
|
69
|
+
read(name) → wait for completion, get output
|
|
70
|
+
send(name, text) → steer with follow-up
|
|
71
|
+
read(name) → wait for completion, get output
|
|
72
|
+
kill(name) → cleanup
|
|
79
73
|
```
|
|
80
74
|
|
|
81
75
|
## Tips
|
|
82
76
|
|
|
83
|
-
-
|
|
84
|
-
- User can attach manually: `tmux attach -t claude-<name>`
|
|
77
|
+
- Attach manually: `tmux attach -t claude-<name>`
|
|
85
78
|
- Always kill sessions when done to avoid orphaned processes
|
package/dist/index.js
CHANGED
|
@@ -53,17 +53,16 @@ async function waitForIdle(session) {
|
|
|
53
53
|
const timeout = 600000; // 10 minutes
|
|
54
54
|
const lines = 100; // Capture more lines to catch done signal
|
|
55
55
|
const startTime = Date.now();
|
|
56
|
-
let lastOutput = "";
|
|
57
56
|
let idleCount = 0;
|
|
57
|
+
let output = "";
|
|
58
58
|
// Initial delay to let Claude start working
|
|
59
59
|
await sleep(5000);
|
|
60
60
|
while (Date.now() - startTime < timeout) {
|
|
61
61
|
await sleep(2000);
|
|
62
62
|
try {
|
|
63
|
-
|
|
63
|
+
output = runTmux(`capture-pane -t "${session}" -p -S -${lines}`);
|
|
64
64
|
// If busy, reset idle count and continue polling
|
|
65
65
|
if (isBusy(output)) {
|
|
66
|
-
lastOutput = output;
|
|
67
66
|
idleCount = 0;
|
|
68
67
|
continue;
|
|
69
68
|
}
|
|
@@ -77,17 +76,16 @@ async function waitForIdle(session) {
|
|
|
77
76
|
if (idleCount >= 2) {
|
|
78
77
|
return filterUIChrome(output);
|
|
79
78
|
}
|
|
80
|
-
lastOutput = output;
|
|
81
79
|
}
|
|
82
80
|
catch (e) {
|
|
83
81
|
return `Error: ${e.message}`;
|
|
84
82
|
}
|
|
85
83
|
}
|
|
86
|
-
return `Timeout after 10 minutes. Session still running.\n\n${filterUIChrome(
|
|
84
|
+
return `Timeout after 10 minutes. Session still running.\n\n${filterUIChrome(output)}`;
|
|
87
85
|
}
|
|
88
86
|
const server = new McpServer({
|
|
89
87
|
name: "claude-tmux",
|
|
90
|
-
version: "1.0.
|
|
88
|
+
version: "1.0.9",
|
|
91
89
|
}, {
|
|
92
90
|
instructions: `# claude-tmux: Autonomous Claude Agents
|
|
93
91
|
|
|
@@ -102,28 +100,22 @@ Spawn Claude Code instances in tmux sessions for long-running, independent tasks
|
|
|
102
100
|
## Pattern
|
|
103
101
|
|
|
104
102
|
\`\`\`
|
|
105
|
-
spawn(
|
|
106
|
-
read(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
For steering mid-task:
|
|
111
|
-
\`\`\`
|
|
112
|
-
send("task-name", "do something else")
|
|
113
|
-
read("task-name") → waits for completion, returns output
|
|
103
|
+
spawn(name, prompt, workdir) → start session
|
|
104
|
+
read(name) → wait for completion, get output
|
|
105
|
+
send(name, text) → steer with follow-up
|
|
106
|
+
read(name) → wait for completion, get output
|
|
107
|
+
kill(name) → cleanup
|
|
114
108
|
\`\`\`
|
|
115
109
|
|
|
116
110
|
## Tips
|
|
117
|
-
- Use \`dangerouslySkipPermissions: true\` for fully autonomous operation
|
|
118
111
|
- User can attach manually: \`tmux attach -t claude-<name>\`
|
|
119
112
|
- Always kill sessions when done`,
|
|
120
113
|
});
|
|
121
114
|
server.tool("spawn", "Launch a new Claude Code instance in a tmux session. Creates an interactive session you can communicate with via send/read. The session runs until killed. Use for multi-turn conversations or tasks requiring steering.", {
|
|
122
115
|
name: z.string().min(1).max(50).describe("Unique session name (e.g., 'refactor-auth', 'debug-api')"),
|
|
116
|
+
prompt: z.string().describe("Initial prompt to send to Claude on startup"),
|
|
123
117
|
workdir: z.string().describe("Working directory for Claude to operate in"),
|
|
124
|
-
|
|
125
|
-
dangerouslySkipPermissions: z.boolean().optional().default(false).describe("Skip permission prompts for fully autonomous operation"),
|
|
126
|
-
}, async ({ name, workdir, prompt, dangerouslySkipPermissions }) => {
|
|
118
|
+
}, async ({ name, prompt, workdir }) => {
|
|
127
119
|
const session = sessionName(name);
|
|
128
120
|
runTmuxSafe(`kill-session -t "${session}"`);
|
|
129
121
|
try {
|
|
@@ -132,15 +124,9 @@ server.tool("spawn", "Launch a new Claude Code instance in a tmux session. Creat
|
|
|
132
124
|
catch (e) {
|
|
133
125
|
return { content: [{ type: "text", text: `Error: ${e.message}` }] };
|
|
134
126
|
}
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
writeFileSync(tempFile, prompt);
|
|
139
|
-
runTmux(`send-keys -t "${session}" 'claude ${flags}"$(cat ${tempFile})" && rm ${tempFile}' Enter`);
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
runTmux(`send-keys -t "${session}" 'claude ${flags}' Enter`);
|
|
143
|
-
}
|
|
127
|
+
const tempFile = `/tmp/claude-prompt-${session}.txt`;
|
|
128
|
+
writeFileSync(tempFile, prompt);
|
|
129
|
+
runTmux(`send-keys -t "${session}" 'claude --dangerously-skip-permissions "$(cat ${tempFile})" && rm ${tempFile}' Enter`);
|
|
144
130
|
return { content: [{ type: "text", text: `Started ${session}` }] };
|
|
145
131
|
});
|
|
146
132
|
server.tool("read", "Wait for a Claude session to finish working and return the terminal output. You can continue other work while waiting.", {
|