claude-multi-session 1.0.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 +545 -0
- package/STRATEGY.md +179 -0
- package/bin/cli.js +693 -0
- package/bin/mcp.js +27 -0
- package/bin/setup.js +469 -0
- package/package.json +42 -0
- package/src/delegate.js +343 -0
- package/src/index.js +35 -0
- package/src/manager.js +510 -0
- package/src/mcp-server.js +808 -0
- package/src/safety-net.js +170 -0
- package/src/store.js +130 -0
- package/src/stream-session.js +463 -0
package/bin/mcp.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* claude-multi-session MCP Server entry point.
|
|
5
|
+
*
|
|
6
|
+
* This starts the MCP (Model Context Protocol) server that exposes
|
|
7
|
+
* multi-session tools to Claude Code as native tools.
|
|
8
|
+
*
|
|
9
|
+
* Claude Code connects to this server via stdio. Once connected,
|
|
10
|
+
* tools like spawn_session, send_message, delegate_task appear
|
|
11
|
+
* in Claude's tool list — just like Read, Edit, Grep, etc.
|
|
12
|
+
*
|
|
13
|
+
* Usage (in Claude Code MCP config):
|
|
14
|
+
* {
|
|
15
|
+
* "mcpServers": {
|
|
16
|
+
* "multi-session": {
|
|
17
|
+
* "command": "cms-mcp"
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* Or run directly:
|
|
23
|
+
* node bin/mcp.js
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const { startServer } = require('../src/mcp-server');
|
|
27
|
+
startServer();
|
package/bin/setup.js
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ╔══════════════════════════════════════════════════════════════╗
|
|
5
|
+
* ║ claude-multi-session — Setup Wizard ║
|
|
6
|
+
* ╚══════════════════════════════════════════════════════════════╝
|
|
7
|
+
*
|
|
8
|
+
* Automatically registers the multi-session MCP server with Claude Code.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* cms setup Interactive setup wizard
|
|
12
|
+
* cms setup --global Skip prompt, install globally
|
|
13
|
+
* cms setup --local Skip prompt, install locally
|
|
14
|
+
* cms setup --uninstall Remove MCP entry + CLAUDE.md section
|
|
15
|
+
* cms setup --postinstall (Internal) Print hint after npm install
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
const os = require('os');
|
|
21
|
+
const readline = require('readline');
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Constants
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
// The name of the MCP server entry in settings.json
|
|
28
|
+
const MCP_SERVER_NAME = 'multi-session';
|
|
29
|
+
|
|
30
|
+
// Marker used to identify the strategy section in CLAUDE.md
|
|
31
|
+
// (so we can detect duplicates and remove on uninstall)
|
|
32
|
+
const CLAUDE_MD_START_MARKER = '<!-- claude-multi-session:start -->';
|
|
33
|
+
const CLAUDE_MD_END_MARKER = '<!-- claude-multi-session:end -->';
|
|
34
|
+
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// Strategy Guide Content (concise version of STRATEGY.md)
|
|
37
|
+
// ============================================================================
|
|
38
|
+
|
|
39
|
+
// This gets appended to CLAUDE.md when the user opts in.
|
|
40
|
+
// It's a condensed version — just the decision framework and key rules.
|
|
41
|
+
const STRATEGY_CONTENT = `
|
|
42
|
+
${CLAUDE_MD_START_MARKER}
|
|
43
|
+
|
|
44
|
+
## Multi-Session Strategy (claude-multi-session)
|
|
45
|
+
|
|
46
|
+
### When to Delegate
|
|
47
|
+
- **3+ independent parts** — run in parallel (e.g., login + signup + reset)
|
|
48
|
+
- **Task too large for one context** — full features with tests
|
|
49
|
+
- **Different models needed** — haiku for lookups, opus for architecture
|
|
50
|
+
- **Risky operations** — delegate with safety limits
|
|
51
|
+
|
|
52
|
+
### When NOT to Delegate
|
|
53
|
+
- Simple tasks (< 5 min, < 3 files) — do it yourself
|
|
54
|
+
- Tightly coupled changes — must happen atomically
|
|
55
|
+
- Just reading/exploring — use Read, Grep, Glob directly
|
|
56
|
+
|
|
57
|
+
### Decision Flow
|
|
58
|
+
1. Simple task? → Do it yourself
|
|
59
|
+
2. Can split into independent parts? → Delegate each in parallel
|
|
60
|
+
3. Needs safety limits? → Use \`delegate_task\` with \`max_cost\` / \`max_turns\`
|
|
61
|
+
4. Otherwise → \`spawn_session\` + \`send_message\` for direct control
|
|
62
|
+
|
|
63
|
+
### Model Selection
|
|
64
|
+
| Task | Model |
|
|
65
|
+
|------|-------|
|
|
66
|
+
| Simple lookups, counting | haiku |
|
|
67
|
+
| Standard edits, bug fixes, tests | sonnet |
|
|
68
|
+
| Architecture, complex refactoring | opus |
|
|
69
|
+
|
|
70
|
+
### The Correction Loop
|
|
71
|
+
1. \`delegate_task\` → read result
|
|
72
|
+
2. Status = completed? → evaluate quality
|
|
73
|
+
3. Good? → \`finish_task\` | Bad? → \`continue_task\` with specific fixes
|
|
74
|
+
4. Hopeless? → \`abort_task\`, try differently
|
|
75
|
+
|
|
76
|
+
### Anti-Patterns
|
|
77
|
+
- Don't delegate trivial tasks (spawning overhead isn't worth it)
|
|
78
|
+
- Don't use \`full\` preset by default (use \`edit\`, escalate if needed)
|
|
79
|
+
- Don't send vague corrections ("fix it") — be specific
|
|
80
|
+
- Don't coordinate parallel sessions editing the SAME file (conflicts)
|
|
81
|
+
- Don't forget to \`finish_task\` — stopped sessions consume stored data
|
|
82
|
+
|
|
83
|
+
${CLAUDE_MD_END_MARKER}
|
|
84
|
+
`;
|
|
85
|
+
|
|
86
|
+
// ============================================================================
|
|
87
|
+
// Helpers
|
|
88
|
+
// ============================================================================
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Ask the user a question and return their answer.
|
|
92
|
+
* Uses Node's readline module — zero dependencies.
|
|
93
|
+
*/
|
|
94
|
+
function ask(question) {
|
|
95
|
+
return new Promise((resolve) => {
|
|
96
|
+
const rl = readline.createInterface({
|
|
97
|
+
input: process.stdin,
|
|
98
|
+
output: process.stdout,
|
|
99
|
+
});
|
|
100
|
+
rl.question(question, (answer) => {
|
|
101
|
+
rl.close();
|
|
102
|
+
resolve(answer.trim());
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Print a styled log line.
|
|
109
|
+
* @param {string} msg - The message to print
|
|
110
|
+
* @param {'info'|'success'|'warn'|'error'} [level] - Optional level
|
|
111
|
+
*/
|
|
112
|
+
function log(msg, level) {
|
|
113
|
+
const prefix = {
|
|
114
|
+
info: ' ',
|
|
115
|
+
success: ' ✓ ',
|
|
116
|
+
warn: ' ⚠ ',
|
|
117
|
+
error: ' ✗ ',
|
|
118
|
+
}[level || 'info'];
|
|
119
|
+
console.log(prefix + msg);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Figure out whether this package was installed globally or locally,
|
|
124
|
+
* and return the right MCP server command config.
|
|
125
|
+
*
|
|
126
|
+
* Global install: the `cms-mcp` binary is on PATH, so we can just call it.
|
|
127
|
+
* Local install: we need an absolute path to bin/mcp.js.
|
|
128
|
+
*/
|
|
129
|
+
function detectMcpCommand() {
|
|
130
|
+
// __dirname is the "bin/" folder where this script lives
|
|
131
|
+
// One level up is the package root
|
|
132
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
133
|
+
const mcpBin = path.join(packageRoot, 'bin', 'mcp.js');
|
|
134
|
+
|
|
135
|
+
// Check if cms-mcp is likely on PATH (global install)
|
|
136
|
+
// We do this by checking if the package is inside a global node_modules
|
|
137
|
+
const isGlobal = packageRoot.includes(path.join('node_modules', 'claude-multi-session'))
|
|
138
|
+
&& (
|
|
139
|
+
packageRoot.includes(path.join('lib', 'node_modules')) // npm global on Linux/Mac
|
|
140
|
+
|| packageRoot.includes(path.join('AppData', 'Roaming', 'npm')) // npm global on Windows
|
|
141
|
+
|| packageRoot.includes('nvm') // nvm managed
|
|
142
|
+
|| packageRoot.includes('.volta') // volta managed
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
if (isGlobal) {
|
|
146
|
+
// Global install — cms-mcp should be on PATH
|
|
147
|
+
return { command: 'cms-mcp' };
|
|
148
|
+
} else {
|
|
149
|
+
// Local or dev install — use absolute path to bin/mcp.js
|
|
150
|
+
return { command: 'node', args: [mcpBin] };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Read a JSON file safely. Returns empty object if file doesn't exist
|
|
156
|
+
* or has invalid JSON.
|
|
157
|
+
*/
|
|
158
|
+
function readJsonSafe(filePath) {
|
|
159
|
+
try {
|
|
160
|
+
if (!fs.existsSync(filePath)) return {};
|
|
161
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
162
|
+
return JSON.parse(raw);
|
|
163
|
+
} catch {
|
|
164
|
+
return {};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Write JSON to a file with nice formatting.
|
|
170
|
+
*/
|
|
171
|
+
function writeJson(filePath, data) {
|
|
172
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ============================================================================
|
|
176
|
+
// Core Setup Logic
|
|
177
|
+
// ============================================================================
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Add the multi-session MCP server to a Claude Code settings.json file.
|
|
181
|
+
*
|
|
182
|
+
* @param {string} settingsPath - Absolute path to settings.json
|
|
183
|
+
* @returns {{ created: boolean, existed: boolean, overwritten: boolean }}
|
|
184
|
+
*/
|
|
185
|
+
async function addMcpServer(settingsPath) {
|
|
186
|
+
const result = { created: false, existed: false, overwritten: false };
|
|
187
|
+
|
|
188
|
+
// 1. Make sure the directory exists
|
|
189
|
+
const dir = path.dirname(settingsPath);
|
|
190
|
+
if (!fs.existsSync(dir)) {
|
|
191
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
192
|
+
log(`Created ${dir}`, 'info');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// 2. Read existing settings (or start with empty object)
|
|
196
|
+
const settings = readJsonSafe(settingsPath);
|
|
197
|
+
const fileExists = fs.existsSync(settingsPath);
|
|
198
|
+
|
|
199
|
+
if (!fileExists) {
|
|
200
|
+
log(`Creating ${settingsPath} ...`, 'info');
|
|
201
|
+
result.created = true;
|
|
202
|
+
} else {
|
|
203
|
+
log(`Reading ${settingsPath} ...`, 'info');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// 3. Ensure mcpServers key exists
|
|
207
|
+
if (!settings.mcpServers) {
|
|
208
|
+
settings.mcpServers = {};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// 4. Check if multi-session already exists
|
|
212
|
+
if (settings.mcpServers[MCP_SERVER_NAME]) {
|
|
213
|
+
result.existed = true;
|
|
214
|
+
const answer = await ask(
|
|
215
|
+
` MCP server "${MCP_SERVER_NAME}" already exists. Overwrite? (y/n) > `
|
|
216
|
+
);
|
|
217
|
+
if (answer.toLowerCase() !== 'y') {
|
|
218
|
+
log('Skipped — keeping existing MCP config.', 'warn');
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
result.overwritten = true;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// 5. Build the MCP config entry
|
|
225
|
+
const mcpConfig = detectMcpCommand();
|
|
226
|
+
settings.mcpServers[MCP_SERVER_NAME] = mcpConfig;
|
|
227
|
+
|
|
228
|
+
log('Adding multi-session MCP server ...', 'info');
|
|
229
|
+
|
|
230
|
+
// 6. Write back
|
|
231
|
+
writeJson(settingsPath, settings);
|
|
232
|
+
log(`Wrote ${settingsPath}`, 'success');
|
|
233
|
+
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Append the strategy guide to a CLAUDE.md file.
|
|
239
|
+
*
|
|
240
|
+
* @param {string} claudeMdPath - Absolute path to CLAUDE.md
|
|
241
|
+
* @returns {{ created: boolean, skipped: boolean }}
|
|
242
|
+
*/
|
|
243
|
+
function addStrategyGuide(claudeMdPath, skipPrompt) {
|
|
244
|
+
const result = { created: false, skipped: false };
|
|
245
|
+
|
|
246
|
+
// Check if file exists
|
|
247
|
+
let existing = '';
|
|
248
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
249
|
+
existing = fs.readFileSync(claudeMdPath, 'utf-8');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Check if strategy section already exists (avoid duplicates)
|
|
253
|
+
if (existing.includes(CLAUDE_MD_START_MARKER)) {
|
|
254
|
+
log('Strategy guide already in CLAUDE.md — skipping.', 'warn');
|
|
255
|
+
result.skipped = true;
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Create directory if needed
|
|
260
|
+
const dir = path.dirname(claudeMdPath);
|
|
261
|
+
if (!fs.existsSync(dir)) {
|
|
262
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Append the strategy content
|
|
266
|
+
if (existing) {
|
|
267
|
+
// Append to existing file
|
|
268
|
+
fs.appendFileSync(claudeMdPath, '\n' + STRATEGY_CONTENT, 'utf-8');
|
|
269
|
+
log(`Appended strategy guide to ${claudeMdPath}`, 'success');
|
|
270
|
+
} else {
|
|
271
|
+
// Create new file with strategy content
|
|
272
|
+
fs.writeFileSync(claudeMdPath, STRATEGY_CONTENT.trim() + '\n', 'utf-8');
|
|
273
|
+
log(`Created ${claudeMdPath} with strategy guide`, 'success');
|
|
274
|
+
result.created = true;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Remove multi-session from settings.json and CLAUDE.md.
|
|
282
|
+
*
|
|
283
|
+
* @param {string} settingsPath - Path to settings.json
|
|
284
|
+
* @param {string} claudeMdPath - Path to CLAUDE.md
|
|
285
|
+
*/
|
|
286
|
+
function uninstall(settingsPath, claudeMdPath) {
|
|
287
|
+
console.log('\n Uninstalling multi-session...\n');
|
|
288
|
+
|
|
289
|
+
// 1. Remove from settings.json
|
|
290
|
+
if (fs.existsSync(settingsPath)) {
|
|
291
|
+
const settings = readJsonSafe(settingsPath);
|
|
292
|
+
if (settings.mcpServers && settings.mcpServers[MCP_SERVER_NAME]) {
|
|
293
|
+
delete settings.mcpServers[MCP_SERVER_NAME];
|
|
294
|
+
|
|
295
|
+
// Clean up empty mcpServers object
|
|
296
|
+
if (Object.keys(settings.mcpServers).length === 0) {
|
|
297
|
+
delete settings.mcpServers;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
writeJson(settingsPath, settings);
|
|
301
|
+
log(`Removed "${MCP_SERVER_NAME}" from ${settingsPath}`, 'success');
|
|
302
|
+
} else {
|
|
303
|
+
log(`"${MCP_SERVER_NAME}" not found in ${settingsPath}`, 'warn');
|
|
304
|
+
}
|
|
305
|
+
} else {
|
|
306
|
+
log(`${settingsPath} not found — nothing to remove`, 'warn');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// 2. Remove strategy section from CLAUDE.md
|
|
310
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
311
|
+
let content = fs.readFileSync(claudeMdPath, 'utf-8');
|
|
312
|
+
if (content.includes(CLAUDE_MD_START_MARKER)) {
|
|
313
|
+
// Remove everything between (and including) the markers
|
|
314
|
+
const startIdx = content.indexOf(CLAUDE_MD_START_MARKER);
|
|
315
|
+
const endIdx = content.indexOf(CLAUDE_MD_END_MARKER);
|
|
316
|
+
if (startIdx !== -1 && endIdx !== -1) {
|
|
317
|
+
const before = content.slice(0, startIdx).trimEnd();
|
|
318
|
+
const after = content.slice(endIdx + CLAUDE_MD_END_MARKER.length).trimStart();
|
|
319
|
+
content = before + (after ? '\n\n' + after : '') + '\n';
|
|
320
|
+
fs.writeFileSync(claudeMdPath, content, 'utf-8');
|
|
321
|
+
log(`Removed strategy guide from ${claudeMdPath}`, 'success');
|
|
322
|
+
}
|
|
323
|
+
} else {
|
|
324
|
+
log('No strategy guide found in CLAUDE.md — nothing to remove', 'warn');
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
console.log('\n ✓ Uninstall complete. Restart Claude Code to apply.\n');
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// ============================================================================
|
|
332
|
+
// Main Entry Point
|
|
333
|
+
// ============================================================================
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Run the setup wizard.
|
|
337
|
+
*
|
|
338
|
+
* @param {object} flags - CLI flags passed from cli.js or direct invocation
|
|
339
|
+
*/
|
|
340
|
+
async function run(flags = {}) {
|
|
341
|
+
// --postinstall mode: just print a hint and exit
|
|
342
|
+
if (flags.postinstall) {
|
|
343
|
+
console.log('');
|
|
344
|
+
console.log(' ╔═══════════════════════════════════════════════════════╗');
|
|
345
|
+
console.log(' ║ claude-multi-session installed successfully! ║');
|
|
346
|
+
console.log(' ║ ║');
|
|
347
|
+
console.log(' ║ Run setup to integrate with Claude Code: ║');
|
|
348
|
+
console.log(' ║ ║');
|
|
349
|
+
console.log(' ║ cms setup ║');
|
|
350
|
+
console.log(' ║ ║');
|
|
351
|
+
console.log(' ║ This registers the MCP server so Claude Code ║');
|
|
352
|
+
console.log(' ║ can use multi-session tools natively. ║');
|
|
353
|
+
console.log(' ╚═══════════════════════════════════════════════════════╝');
|
|
354
|
+
console.log('');
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Determine paths based on scope (global vs local)
|
|
359
|
+
const homeDir = os.homedir();
|
|
360
|
+
const globalSettingsPath = path.join(homeDir, '.claude', 'settings.json');
|
|
361
|
+
const globalClaudeMdPath = path.join(homeDir, '.claude', 'CLAUDE.md');
|
|
362
|
+
const localSettingsPath = path.join(process.cwd(), '.claude', 'settings.json');
|
|
363
|
+
const localClaudeMdPath = path.join(process.cwd(), 'CLAUDE.md');
|
|
364
|
+
|
|
365
|
+
// --uninstall mode
|
|
366
|
+
if (flags.uninstall) {
|
|
367
|
+
// Ask which scope to uninstall from (or use --global/--local flags)
|
|
368
|
+
let scope = flags.global ? 'global' : flags.local ? 'local' : null;
|
|
369
|
+
if (!scope) {
|
|
370
|
+
const answer = await ask(
|
|
371
|
+
' Uninstall from? (1 = Global, 2 = Local project) > '
|
|
372
|
+
);
|
|
373
|
+
scope = answer === '2' ? 'local' : 'global';
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const settingsPath = scope === 'global' ? globalSettingsPath : localSettingsPath;
|
|
377
|
+
const claudeMdPath = scope === 'global' ? globalClaudeMdPath : localClaudeMdPath;
|
|
378
|
+
uninstall(settingsPath, claudeMdPath);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Print header
|
|
383
|
+
console.log('');
|
|
384
|
+
console.log(' ╔═══════════════════════════════════════════════════════╗');
|
|
385
|
+
console.log(' ║ claude-multi-session — Setup Wizard ║');
|
|
386
|
+
console.log(' ╚═══════════════════════════════════════════════════════╝');
|
|
387
|
+
console.log('');
|
|
388
|
+
|
|
389
|
+
// Step 1: Determine scope
|
|
390
|
+
let scope;
|
|
391
|
+
if (flags.global) {
|
|
392
|
+
scope = 'global';
|
|
393
|
+
log('Scope: Global (all projects)', 'info');
|
|
394
|
+
} else if (flags.local) {
|
|
395
|
+
scope = 'local';
|
|
396
|
+
log('Scope: Local (this project only)', 'info');
|
|
397
|
+
} else {
|
|
398
|
+
console.log(' Where should the MCP server be registered?\n');
|
|
399
|
+
console.log(' 1) Global — available in ALL projects');
|
|
400
|
+
console.log(' Writes to: ~/.claude/settings.json\n');
|
|
401
|
+
console.log(' 2) Local — only THIS project');
|
|
402
|
+
console.log(' Writes to: .claude/settings.json\n');
|
|
403
|
+
const answer = await ask(' Choose (1 or 2) > ');
|
|
404
|
+
scope = answer === '2' ? 'local' : 'global';
|
|
405
|
+
console.log('');
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Step 2: Set paths based on scope
|
|
409
|
+
const settingsPath = scope === 'global' ? globalSettingsPath : localSettingsPath;
|
|
410
|
+
const claudeMdPath = scope === 'global' ? globalClaudeMdPath : localClaudeMdPath;
|
|
411
|
+
|
|
412
|
+
// Step 3: Add MCP server to settings.json
|
|
413
|
+
const mcpResult = await addMcpServer(settingsPath);
|
|
414
|
+
|
|
415
|
+
// Step 4: Ask about strategy guide
|
|
416
|
+
console.log('');
|
|
417
|
+
let addGuide;
|
|
418
|
+
if (flags['no-guide']) {
|
|
419
|
+
addGuide = false;
|
|
420
|
+
} else if (flags.guide) {
|
|
421
|
+
addGuide = true;
|
|
422
|
+
} else {
|
|
423
|
+
const answer = await ask(
|
|
424
|
+
' Add multi-session strategy guide to CLAUDE.md? (y/n) > '
|
|
425
|
+
);
|
|
426
|
+
addGuide = answer.toLowerCase() === 'y';
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (addGuide) {
|
|
430
|
+
addStrategyGuide(claudeMdPath);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Step 5: Print summary
|
|
434
|
+
console.log('');
|
|
435
|
+
console.log(' ╔═══════════════════════════════════════════════════════╗');
|
|
436
|
+
console.log(' ║ ✓ Setup complete! ║');
|
|
437
|
+
console.log(' ╚═══════════════════════════════════════════════════════╝');
|
|
438
|
+
console.log('');
|
|
439
|
+
log('Restart Claude Code to load the multi-session tools.', 'info');
|
|
440
|
+
log('You\'ll see 17 new tools: spawn_session, delegate_task, etc.', 'info');
|
|
441
|
+
console.log('');
|
|
442
|
+
log('Test it: Ask Claude to "list all multi-session sessions"', 'info');
|
|
443
|
+
log('Learn more: cms help', 'info');
|
|
444
|
+
console.log('');
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// ============================================================================
|
|
448
|
+
// Direct invocation support (node bin/setup.js)
|
|
449
|
+
// ============================================================================
|
|
450
|
+
|
|
451
|
+
// If this script is run directly (not required by cli.js),
|
|
452
|
+
// parse flags and run the wizard
|
|
453
|
+
if (require.main === module) {
|
|
454
|
+
// Parse simple flags from process.argv
|
|
455
|
+
const args = process.argv.slice(2);
|
|
456
|
+
const flags = {};
|
|
457
|
+
for (const arg of args) {
|
|
458
|
+
if (arg.startsWith('--')) {
|
|
459
|
+
const key = arg.slice(2);
|
|
460
|
+
flags[key] = true;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
run(flags).catch((err) => {
|
|
464
|
+
console.error(`\n ✗ Setup failed: ${err.message}\n`);
|
|
465
|
+
process.exit(1);
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
module.exports = { run };
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "claude-multi-session",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Multi-session orchestrator for Claude Code CLI — spawn, control, pause, resume, and send multiple inputs to Claude Code sessions programmatically",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"cms": "bin/cli.js",
|
|
8
|
+
"claude-multi-session": "bin/cli.js",
|
|
9
|
+
"cms-mcp": "bin/mcp.js",
|
|
10
|
+
"cms-setup": "bin/setup.js"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "node test-stream.js",
|
|
14
|
+
"postinstall": "node bin/setup.js --postinstall"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"claude",
|
|
18
|
+
"claude-code",
|
|
19
|
+
"session-manager",
|
|
20
|
+
"multi-session",
|
|
21
|
+
"orchestrator",
|
|
22
|
+
"ai",
|
|
23
|
+
"automation",
|
|
24
|
+
"cli"
|
|
25
|
+
],
|
|
26
|
+
"author": "",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"src/",
|
|
33
|
+
"bin/",
|
|
34
|
+
"README.md",
|
|
35
|
+
"STRATEGY.md",
|
|
36
|
+
"LICENSE"
|
|
37
|
+
],
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": ""
|
|
41
|
+
}
|
|
42
|
+
}
|