spawn-skill 1.1.0 → 1.2.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/bin/CLAUDE.md +1 -3
- package/bin/cli.js +138 -267
- package/package.json +10 -3
package/bin/CLAUDE.md
CHANGED
|
@@ -7,7 +7,5 @@
|
|
|
7
7
|
|
|
8
8
|
| ID | Time | T | Title | Read |
|
|
9
9
|
|----|------|---|-------|------|
|
|
10
|
-
| #
|
|
11
|
-
| #894 | 8:55 PM | 🔵 | spawn-skill CLI contains embedded skill documentation | ~435 |
|
|
12
|
-
| #794 | 11:11 AM | ✅ | Simplified spawn-skill CLI package.json generation to use direct ws dependency | ~353 |
|
|
10
|
+
| #913 | 10:14 PM | 🔵 | Spawn-skill CLI tool provides Python SDK implementation | ~343 |
|
|
13
11
|
</claude-mem-context>
|
package/bin/cli.js
CHANGED
|
@@ -338,172 +338,6 @@ if __name__ == '__main__':
|
|
|
338
338
|
`;
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
-
function getMCPServer(token) {
|
|
342
|
-
return `#!/usr/bin/env node
|
|
343
|
-
/**
|
|
344
|
-
* Spawn.wtf MCP Server
|
|
345
|
-
* Bridges Spawn.wtf with Claude Code
|
|
346
|
-
*/
|
|
347
|
-
|
|
348
|
-
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
349
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
350
|
-
import {
|
|
351
|
-
CallToolRequestSchema,
|
|
352
|
-
ListToolsRequestSchema,
|
|
353
|
-
} from '@modelcontextprotocol/sdk/types.js';
|
|
354
|
-
import WebSocket from 'ws';
|
|
355
|
-
|
|
356
|
-
const RELAY_URL = 'wss://spawn-relay.ngvsqdjj5r.workers.dev/v1/agent';
|
|
357
|
-
const TOKEN = process.env.SPAWN_TOKEN || '${token}';
|
|
358
|
-
|
|
359
|
-
const messageQueue = [];
|
|
360
|
-
let ws = null;
|
|
361
|
-
let connected = false;
|
|
362
|
-
let connectionError = null;
|
|
363
|
-
|
|
364
|
-
function connectToRelay() {
|
|
365
|
-
if (!TOKEN) {
|
|
366
|
-
connectionError = 'SPAWN_TOKEN not set';
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
ws = new WebSocket(RELAY_URL, {
|
|
371
|
-
headers: { 'Authorization': \\\`Bearer \\\${TOKEN}\\\` }
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
ws.on('open', () => {
|
|
375
|
-
connected = true;
|
|
376
|
-
connectionError = null;
|
|
377
|
-
sendMessage('status_update', { status: 'idle', label: 'Ready' });
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
ws.on('message', (data) => {
|
|
381
|
-
try {
|
|
382
|
-
const msg = JSON.parse(data.toString());
|
|
383
|
-
if (msg.type === 'message') {
|
|
384
|
-
messageQueue.push({
|
|
385
|
-
id: msg.id,
|
|
386
|
-
timestamp: msg.ts || Date.now(),
|
|
387
|
-
text: msg.payload?.text || '',
|
|
388
|
-
from: msg.payload?.from || 'user'
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
} catch (e) {}
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
ws.on('close', () => {
|
|
395
|
-
connected = false;
|
|
396
|
-
setTimeout(connectToRelay, 5000);
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
ws.on('error', (err) => {
|
|
400
|
-
connectionError = err.message;
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
function sendMessage(type, payload) {
|
|
405
|
-
if (ws?.readyState === WebSocket.OPEN) {
|
|
406
|
-
ws.send(JSON.stringify({
|
|
407
|
-
type,
|
|
408
|
-
id: \\\`msg_\\\${Date.now()}\\\`,
|
|
409
|
-
ts: Date.now(),
|
|
410
|
-
payload
|
|
411
|
-
}));
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
setInterval(() => {
|
|
416
|
-
if (ws?.readyState === WebSocket.OPEN) {
|
|
417
|
-
sendMessage('ping', {});
|
|
418
|
-
}
|
|
419
|
-
}, 30000);
|
|
420
|
-
|
|
421
|
-
connectToRelay();
|
|
422
|
-
|
|
423
|
-
const server = new Server(
|
|
424
|
-
{ name: 'spawn', version: '1.0.0' },
|
|
425
|
-
{ capabilities: { tools: {} } }
|
|
426
|
-
);
|
|
427
|
-
|
|
428
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
429
|
-
tools: [
|
|
430
|
-
{
|
|
431
|
-
name: 'spawn_check_messages',
|
|
432
|
-
description: 'Check for new messages from the Spawn.wtf iOS app',
|
|
433
|
-
inputSchema: { type: 'object', properties: {}, required: [] }
|
|
434
|
-
},
|
|
435
|
-
{
|
|
436
|
-
name: 'spawn_respond',
|
|
437
|
-
description: 'Send a response back to the user through Spawn.wtf',
|
|
438
|
-
inputSchema: {
|
|
439
|
-
type: 'object',
|
|
440
|
-
properties: {
|
|
441
|
-
text: { type: 'string', description: 'Message to send' },
|
|
442
|
-
format: { type: 'string', enum: ['plain', 'markdown'], default: 'plain' }
|
|
443
|
-
},
|
|
444
|
-
required: ['text']
|
|
445
|
-
}
|
|
446
|
-
},
|
|
447
|
-
{
|
|
448
|
-
name: 'spawn_status',
|
|
449
|
-
description: 'Update your status in Spawn.wtf (idle/thinking/working)',
|
|
450
|
-
inputSchema: {
|
|
451
|
-
type: 'object',
|
|
452
|
-
properties: {
|
|
453
|
-
status: { type: 'string', enum: ['idle', 'thinking', 'working'] },
|
|
454
|
-
label: { type: 'string', description: 'Status label' }
|
|
455
|
-
},
|
|
456
|
-
required: ['status']
|
|
457
|
-
}
|
|
458
|
-
},
|
|
459
|
-
{
|
|
460
|
-
name: 'spawn_connection_info',
|
|
461
|
-
description: 'Get Spawn.wtf connection status',
|
|
462
|
-
inputSchema: { type: 'object', properties: {}, required: [] }
|
|
463
|
-
}
|
|
464
|
-
]
|
|
465
|
-
}));
|
|
466
|
-
|
|
467
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
468
|
-
const { name, arguments: args } = request.params;
|
|
469
|
-
|
|
470
|
-
switch (name) {
|
|
471
|
-
case 'spawn_check_messages': {
|
|
472
|
-
const messages = [...messageQueue];
|
|
473
|
-
messageQueue.length = 0;
|
|
474
|
-
if (messages.length > 0) {
|
|
475
|
-
sendMessage('status_update', { status: 'thinking', label: 'Reading messages' });
|
|
476
|
-
}
|
|
477
|
-
return { content: [{ type: 'text', text: JSON.stringify({ messages, count: messages.length }) }] };
|
|
478
|
-
}
|
|
479
|
-
case 'spawn_respond': {
|
|
480
|
-
if (!connected) {
|
|
481
|
-
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: 'Not connected' }) }] };
|
|
482
|
-
}
|
|
483
|
-
sendMessage('message', { content_type: 'text', text: args.text, format: args.format || 'plain' });
|
|
484
|
-
sendMessage('status_update', { status: 'idle', label: 'Ready' });
|
|
485
|
-
return { content: [{ type: 'text', text: JSON.stringify({ success: true }) }] };
|
|
486
|
-
}
|
|
487
|
-
case 'spawn_status': {
|
|
488
|
-
if (!connected) {
|
|
489
|
-
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: 'Not connected' }) }] };
|
|
490
|
-
}
|
|
491
|
-
sendMessage('status_update', { status: args.status, label: args.label });
|
|
492
|
-
return { content: [{ type: 'text', text: JSON.stringify({ success: true }) }] };
|
|
493
|
-
}
|
|
494
|
-
case 'spawn_connection_info': {
|
|
495
|
-
return { content: [{ type: 'text', text: JSON.stringify({ connected, error: connectionError, pendingMessages: messageQueue.length }) }] };
|
|
496
|
-
}
|
|
497
|
-
default:
|
|
498
|
-
throw new Error(\\\`Unknown tool: \\\${name}\\\`);
|
|
499
|
-
}
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
const transport = new StdioServerTransport();
|
|
503
|
-
server.connect(transport);
|
|
504
|
-
`;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
341
|
function getPythonSDK() {
|
|
508
342
|
return `"""
|
|
509
343
|
Spawn.wtf Python SDK
|
|
@@ -639,7 +473,113 @@ class SpawnAgent:
|
|
|
639
473
|
`;
|
|
640
474
|
}
|
|
641
475
|
|
|
642
|
-
|
|
476
|
+
function getMoltbotBridge(token, agentName) {
|
|
477
|
+
return `/**
|
|
478
|
+
* Spawn.wtf → Moltbot Bridge
|
|
479
|
+
* Routes messages from Spawn iOS app to your Moltbot backend
|
|
480
|
+
* Run with: node connect.js
|
|
481
|
+
*/
|
|
482
|
+
|
|
483
|
+
import WebSocket from 'ws';
|
|
484
|
+
import { spawn } from 'child_process';
|
|
485
|
+
|
|
486
|
+
const TOKEN = '${token}';
|
|
487
|
+
const NAME = '${agentName}';
|
|
488
|
+
const RELAY = 'wss://spawn-relay.ngvsqdjj5r.workers.dev/v1/agent';
|
|
489
|
+
|
|
490
|
+
let ws;
|
|
491
|
+
|
|
492
|
+
function send(type, payload) {
|
|
493
|
+
if (ws?.readyState === WebSocket.OPEN) {
|
|
494
|
+
ws.send(JSON.stringify({
|
|
495
|
+
type,
|
|
496
|
+
id: \`msg_\${Date.now()}\`,
|
|
497
|
+
ts: Date.now(),
|
|
498
|
+
payload
|
|
499
|
+
}));
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function sendText(text) {
|
|
504
|
+
send('message', { content_type: 'text', text, format: 'plain' });
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
function updateStatus(status, label) {
|
|
508
|
+
send('status_update', { status, label });
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// Forward message to Moltbot and return response
|
|
512
|
+
async function askMoltbot(message) {
|
|
513
|
+
return new Promise((resolve, reject) => {
|
|
514
|
+
console.log('📨 Forwarding to Moltbot:', message);
|
|
515
|
+
updateStatus('thinking', 'Asking Moltbot...');
|
|
516
|
+
|
|
517
|
+
const moltbot = spawn('moltbot', ['agent', '--message', message, '--thinking', 'high']);
|
|
518
|
+
let response = '';
|
|
519
|
+
let error = '';
|
|
520
|
+
|
|
521
|
+
moltbot.stdout.on('data', (data) => response += data.toString());
|
|
522
|
+
moltbot.stderr.on('data', (data) => error += data.toString());
|
|
523
|
+
|
|
524
|
+
moltbot.on('close', (code) => {
|
|
525
|
+
if (code === 0) {
|
|
526
|
+
console.log('✓ Moltbot responded');
|
|
527
|
+
resolve(response.trim());
|
|
528
|
+
} else {
|
|
529
|
+
console.error('✗ Moltbot error:', error);
|
|
530
|
+
reject(new Error(error || \`Exit code \${code}\`));
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
function connect() {
|
|
537
|
+
ws = new WebSocket(RELAY, {
|
|
538
|
+
headers: { 'Authorization': \`Bearer \${TOKEN}\` }
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
ws.on('open', () => {
|
|
542
|
+
console.log('🦞 Connected to Spawn.wtf (Moltbot bridge mode)');
|
|
543
|
+
sendText(\`\${NAME} is online (powered by Moltbot 🦞)\`);
|
|
544
|
+
updateStatus('idle', 'Ready for commands');
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
ws.on('message', async (data) => {
|
|
548
|
+
const msg = JSON.parse(data.toString());
|
|
549
|
+
|
|
550
|
+
if (msg.type === 'message') {
|
|
551
|
+
const text = msg.payload?.text || '';
|
|
552
|
+
console.log('📱 From Spawn:', text);
|
|
553
|
+
|
|
554
|
+
try {
|
|
555
|
+
const response = await askMoltbot(text);
|
|
556
|
+
sendText(response);
|
|
557
|
+
updateStatus('idle', 'Ready');
|
|
558
|
+
} catch (err) {
|
|
559
|
+
sendText(\`Error: \${err.message}\`);
|
|
560
|
+
updateStatus('idle', 'Ready');
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
ws.on('close', () => {
|
|
566
|
+
console.log('Disconnected, reconnecting in 5s...');
|
|
567
|
+
setTimeout(connect, 5000);
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
ws.on('error', (err) => console.error('WebSocket error:', err.message));
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
setInterval(() => ws?.readyState === WebSocket.OPEN && send('ping', {}), 30000);
|
|
574
|
+
|
|
575
|
+
console.log('🦞 Starting Spawn → Moltbot bridge...');
|
|
576
|
+
connect();
|
|
577
|
+
|
|
578
|
+
process.on('SIGINT', () => { ws?.close(); process.exit(0); });
|
|
579
|
+
`;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
async function createSkillFiles(token, agentName, language, useMoltbot = false) {
|
|
643
583
|
const skillDir = path.join(process.cwd(), 'spawn');
|
|
644
584
|
|
|
645
585
|
// Create spawn directory
|
|
@@ -655,14 +595,17 @@ async function createSkillFiles(token, agentName, language, claudeCode = false)
|
|
|
655
595
|
name: agentName,
|
|
656
596
|
token: token,
|
|
657
597
|
relay: 'wss://spawn-relay.ngvsqdjj5r.workers.dev/v1/agent',
|
|
658
|
-
language: language
|
|
659
|
-
claudeCode: claudeCode
|
|
598
|
+
language: language
|
|
660
599
|
};
|
|
661
600
|
fs.writeFileSync(path.join(skillDir, 'config.json'), JSON.stringify(config, null, 2));
|
|
662
601
|
|
|
663
602
|
if (language === 'typescript') {
|
|
664
603
|
// TypeScript/Node setup
|
|
665
|
-
|
|
604
|
+
if (useMoltbot) {
|
|
605
|
+
fs.writeFileSync(path.join(skillDir, 'connect.js'), getMoltbotBridge(token, agentName));
|
|
606
|
+
} else {
|
|
607
|
+
fs.writeFileSync(path.join(skillDir, 'connect.js'), getTypeScriptConnector(token, agentName));
|
|
608
|
+
}
|
|
666
609
|
|
|
667
610
|
const packageJson = {
|
|
668
611
|
name: "spawn-agent",
|
|
@@ -681,45 +624,7 @@ async function createSkillFiles(token, agentName, language, claudeCode = false)
|
|
|
681
624
|
fs.writeFileSync(path.join(skillDir, 'requirements.txt'), 'websockets>=12.0\n');
|
|
682
625
|
}
|
|
683
626
|
|
|
684
|
-
|
|
685
|
-
if (claudeCode) {
|
|
686
|
-
const mcpDir = path.join(skillDir, 'mcp');
|
|
687
|
-
if (!fs.existsSync(mcpDir)) {
|
|
688
|
-
fs.mkdirSync(mcpDir, { recursive: true });
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
// Create MCP server
|
|
692
|
-
fs.writeFileSync(path.join(mcpDir, 'server.js'), getMCPServer(token));
|
|
693
|
-
|
|
694
|
-
// Create MCP package.json
|
|
695
|
-
const mcpPackageJson = {
|
|
696
|
-
name: "spawn-mcp-server",
|
|
697
|
-
version: "1.0.0",
|
|
698
|
-
type: "module",
|
|
699
|
-
dependencies: {
|
|
700
|
-
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
701
|
-
"ws": "^8.16.0"
|
|
702
|
-
}
|
|
703
|
-
};
|
|
704
|
-
fs.writeFileSync(path.join(mcpDir, 'package.json'), JSON.stringify(mcpPackageJson, null, 2));
|
|
705
|
-
|
|
706
|
-
// Create Claude Code settings snippet
|
|
707
|
-
const mcpFullPath = path.resolve(mcpDir, 'server.js');
|
|
708
|
-
const settingsSnippet = {
|
|
709
|
-
mcpServers: {
|
|
710
|
-
spawn: {
|
|
711
|
-
command: "node",
|
|
712
|
-
args: [mcpFullPath],
|
|
713
|
-
env: {
|
|
714
|
-
SPAWN_TOKEN: token
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
};
|
|
719
|
-
fs.writeFileSync(path.join(mcpDir, 'claude-settings.json'), JSON.stringify(settingsSnippet, null, 2));
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
return { skillDir, language, claudeCode };
|
|
627
|
+
return { skillDir, language, useMoltbot };
|
|
723
628
|
}
|
|
724
629
|
|
|
725
630
|
async function main() {
|
|
@@ -785,9 +690,9 @@ async function main() {
|
|
|
785
690
|
|
|
786
691
|
questions.push({
|
|
787
692
|
type: 'confirm',
|
|
788
|
-
name: '
|
|
789
|
-
message: '
|
|
790
|
-
default:
|
|
693
|
+
name: 'useMoltbot',
|
|
694
|
+
message: 'Use Moltbot as your AI backend? (recommended)',
|
|
695
|
+
default: false
|
|
791
696
|
});
|
|
792
697
|
|
|
793
698
|
const answers = await inquirer.prompt(questions);
|
|
@@ -795,14 +700,29 @@ async function main() {
|
|
|
795
700
|
token = token || answers.token;
|
|
796
701
|
agentName = answers.agentName || agentName;
|
|
797
702
|
language = language || answers.language;
|
|
798
|
-
const
|
|
703
|
+
const useMoltbot = answers.useMoltbot || false;
|
|
799
704
|
|
|
800
705
|
console.log('');
|
|
801
706
|
|
|
707
|
+
// Check for Moltbot if needed
|
|
708
|
+
if (useMoltbot) {
|
|
709
|
+
const moltbotCheck = ora('Checking for Moltbot...').start();
|
|
710
|
+
try {
|
|
711
|
+
const { execSync } = await import('child_process');
|
|
712
|
+
execSync('which moltbot', { stdio: 'pipe' });
|
|
713
|
+
moltbotCheck.succeed('Moltbot found');
|
|
714
|
+
} catch {
|
|
715
|
+
moltbotCheck.warn('Moltbot not installed');
|
|
716
|
+
console.log(dim(' Install with: npm install -g moltbot@latest'));
|
|
717
|
+
console.log(dim(' Then run: moltbot onboard'));
|
|
718
|
+
console.log('');
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
802
722
|
// Create files
|
|
803
723
|
const createSpinner = ora('Creating skill files...').start();
|
|
804
724
|
try {
|
|
805
|
-
const { skillDir } = await createSkillFiles(token, agentName, language,
|
|
725
|
+
const { skillDir } = await createSkillFiles(token, agentName, language, useMoltbot);
|
|
806
726
|
createSpinner.succeed('Created skill files');
|
|
807
727
|
} catch (err) {
|
|
808
728
|
createSpinner.fail('Failed to create skill files');
|
|
@@ -810,18 +730,6 @@ async function main() {
|
|
|
810
730
|
process.exit(1);
|
|
811
731
|
}
|
|
812
732
|
|
|
813
|
-
// Install MCP dependencies if needed
|
|
814
|
-
if (claudeCode) {
|
|
815
|
-
const mcpSpinner = ora('Installing MCP dependencies...').start();
|
|
816
|
-
try {
|
|
817
|
-
const { execSync } = await import('child_process');
|
|
818
|
-
execSync('npm install', { cwd: path.join(process.cwd(), 'spawn', 'mcp'), stdio: 'pipe' });
|
|
819
|
-
mcpSpinner.succeed('Installed MCP dependencies');
|
|
820
|
-
} catch (err) {
|
|
821
|
-
mcpSpinner.warn('Run "cd spawn/mcp && npm install" to finish MCP setup');
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
|
|
825
733
|
console.log('');
|
|
826
734
|
console.log(chalk.green.bold('✓ Spawn.wtf skill installed!'));
|
|
827
735
|
console.log('');
|
|
@@ -832,20 +740,14 @@ async function main() {
|
|
|
832
740
|
console.log(dim(' spawn/config.json'));
|
|
833
741
|
console.log(dim(' spawn/connect.js'));
|
|
834
742
|
console.log(dim(' spawn/package.json'));
|
|
835
|
-
if (claudeCode) {
|
|
836
|
-
console.log(dim(' spawn/mcp/server.js'));
|
|
837
|
-
console.log(dim(' spawn/mcp/package.json'));
|
|
838
|
-
console.log(dim(' spawn/mcp/claude-settings.json'));
|
|
839
|
-
}
|
|
840
743
|
console.log('');
|
|
841
744
|
console.log(' Next steps:');
|
|
842
745
|
console.log('');
|
|
843
746
|
console.log(' 1. ' + chalk.cyan('Install dependencies:'));
|
|
844
|
-
console.log(' ' + dim('cd spawn'));
|
|
845
|
-
console.log(' ' + dim('npm install'));
|
|
747
|
+
console.log(' ' + dim('cd spawn && npm install'));
|
|
846
748
|
console.log('');
|
|
847
749
|
console.log(' 2. ' + chalk.cyan('Run the connector:'));
|
|
848
|
-
console.log(' ' + dim('node connect.js'));
|
|
750
|
+
console.log(' ' + dim('node spawn/connect.js'));
|
|
849
751
|
} else {
|
|
850
752
|
console.log(' Files created:');
|
|
851
753
|
console.log(dim(' spawn/SKILL.md'));
|
|
@@ -853,49 +755,18 @@ async function main() {
|
|
|
853
755
|
console.log(dim(' spawn/connect.py'));
|
|
854
756
|
console.log(dim(' spawn/spawn_sdk.py'));
|
|
855
757
|
console.log(dim(' spawn/requirements.txt'));
|
|
856
|
-
if (claudeCode) {
|
|
857
|
-
console.log(dim(' spawn/mcp/server.js'));
|
|
858
|
-
console.log(dim(' spawn/mcp/package.json'));
|
|
859
|
-
console.log(dim(' spawn/mcp/claude-settings.json'));
|
|
860
|
-
}
|
|
861
758
|
console.log('');
|
|
862
759
|
console.log(' Next steps:');
|
|
863
760
|
console.log('');
|
|
864
761
|
console.log(' 1. ' + chalk.cyan('Install dependencies:'));
|
|
865
|
-
console.log(' ' + dim('cd spawn'));
|
|
866
|
-
console.log(' ' + dim('pip install -r requirements.txt'));
|
|
762
|
+
console.log(' ' + dim('cd spawn && pip install -r requirements.txt'));
|
|
867
763
|
console.log('');
|
|
868
764
|
console.log(' 2. ' + chalk.cyan('Run the connector:'));
|
|
869
|
-
console.log(' ' + dim('python connect.py'));
|
|
765
|
+
console.log(' ' + dim('python spawn/connect.py'));
|
|
870
766
|
}
|
|
871
767
|
|
|
872
768
|
console.log('');
|
|
873
769
|
console.log(' 3. ' + chalk.cyan('Open Spawn.wtf app') + ' - your agent should appear!');
|
|
874
|
-
|
|
875
|
-
if (claudeCode) {
|
|
876
|
-
console.log('');
|
|
877
|
-
console.log(pink(' ═══ Claude Code Integration ═══'));
|
|
878
|
-
console.log('');
|
|
879
|
-
console.log(' Add to your ' + chalk.cyan('.claude/settings.json') + ':');
|
|
880
|
-
console.log('');
|
|
881
|
-
const mcpPath = path.resolve(process.cwd(), 'spawn', 'mcp', 'server.js');
|
|
882
|
-
console.log(dim(' {'));
|
|
883
|
-
console.log(dim(' "mcpServers": {'));
|
|
884
|
-
console.log(dim(' "spawn": {'));
|
|
885
|
-
console.log(dim(' "command": "node",'));
|
|
886
|
-
console.log(dim(` "args": ["${mcpPath}"],`));
|
|
887
|
-
console.log(dim(' "env": { "SPAWN_TOKEN": "' + token.slice(0, 12) + '..." }'));
|
|
888
|
-
console.log(dim(' }'));
|
|
889
|
-
console.log(dim(' }'));
|
|
890
|
-
console.log(dim(' }'));
|
|
891
|
-
console.log('');
|
|
892
|
-
console.log(' Or copy from: ' + dim('spawn/mcp/claude-settings.json'));
|
|
893
|
-
console.log('');
|
|
894
|
-
console.log(' Then restart Claude Code and ask:');
|
|
895
|
-
console.log(' ' + chalk.white('"Check Spawn messages"'));
|
|
896
|
-
console.log(' ' + chalk.white('"Respond: Hello from Claude!"'));
|
|
897
|
-
}
|
|
898
|
-
|
|
899
770
|
console.log('');
|
|
900
771
|
console.log(' Docs: ' + pink('https://github.com/SpawnWTF/spawn'));
|
|
901
772
|
console.log('');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spawn-skill",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Connect your AI agent to Spawn.wtf",
|
|
5
5
|
"bin": {
|
|
6
6
|
"spawn-skill": "./bin/cli.js"
|
|
@@ -9,7 +9,14 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"bin"
|
|
11
11
|
],
|
|
12
|
-
"keywords": [
|
|
12
|
+
"keywords": [
|
|
13
|
+
"spawn",
|
|
14
|
+
"ai",
|
|
15
|
+
"agent",
|
|
16
|
+
"claude",
|
|
17
|
+
"monitoring",
|
|
18
|
+
"moltbot"
|
|
19
|
+
],
|
|
13
20
|
"author": "Spawn.wtf",
|
|
14
21
|
"license": "MIT",
|
|
15
22
|
"repository": {
|
|
@@ -21,4 +28,4 @@
|
|
|
21
28
|
"inquirer": "^9.2.12",
|
|
22
29
|
"ora": "^8.0.1"
|
|
23
30
|
}
|
|
24
|
-
}
|
|
31
|
+
}
|