spawn-chat.ts
1 /** 2 * Spawn Chat MCP Tool - Open Claude Code in another DreamNode 3 * Enables holarchy traversal by spawning new sessions in subcontexts 4 */ 5 6 import { exec } from 'child_process'; 7 import { promisify } from 'util'; 8 import { DreamNodeService } from '../services/standalone-adapter.js'; 9 10 const execAsync = promisify(exec); 11 12 /** 13 * Tool: spawn_chat 14 * Open Claude Code in a new terminal tab for a specific DreamNode 15 */ 16 export async function spawnChat(args: { 17 identifier: string; 18 prompt?: string; 19 }): Promise<{ 20 success: boolean; 21 dreamnode_path?: string; 22 dreamnode_title?: string; 23 error?: string; 24 }> { 25 try { 26 // Resolve DreamNode 27 const node = await DreamNodeService.getDreamNode(args.identifier); 28 29 if (!node) { 30 return { 31 success: false, 32 error: `DreamNode not found: ${args.identifier}` 33 }; 34 } 35 36 // Build the claude command 37 let claudeCmd = 'claude'; 38 if (args.prompt) { 39 // Escape the prompt for shell 40 const escapedPrompt = args.prompt.replace(/'/g, "'\\''"); 41 claudeCmd = `claude '${escapedPrompt}'`; 42 } 43 44 // macOS: Use osascript to open new Terminal tab and run command 45 const script = ` 46 tell application "Terminal" 47 activate 48 tell application "System Events" to keystroke "t" using command down 49 delay 0.3 50 do script "cd '${node.path}' && ${claudeCmd}" in front window 51 end tell 52 `; 53 54 await execAsync(`osascript -e '${script.replace(/'/g, "'\"'\"'")}'`); 55 56 return { 57 success: true, 58 dreamnode_path: node.path, 59 dreamnode_title: node.title 60 }; 61 } catch (error) { 62 return { 63 success: false, 64 error: error instanceof Error ? error.message : 'Unknown error' 65 }; 66 } 67 } 68 69 /** 70 * Export tool definitions for MCP registration 71 */ 72 export const spawnChatTools = { 73 spawn_chat: { 74 name: 'spawn_chat', 75 description: 'Open Claude Code in a new terminal tab for a specific DreamNode. Enables holarchy traversal - spawn sessions in subcontexts to delegate work.', 76 inputSchema: { 77 type: 'object' as const, 78 properties: { 79 identifier: { 80 type: 'string', 81 description: 'UUID or title of the DreamNode to open Claude Code in' 82 }, 83 prompt: { 84 type: 'string', 85 description: 'Optional initial prompt to send to Claude Code' 86 } 87 }, 88 required: ['identifier'] 89 }, 90 handler: spawnChat 91 } 92 };