spawn-skill 1.1.0 → 1.2.1
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 +147 -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,122 @@ 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
|
+
// Use shell: true to inherit PATH and find globally installed moltbot
|
|
518
|
+
const moltbot = spawn('moltbot', ['agent', '--message', message, '--thinking', 'high'], {
|
|
519
|
+
shell: true,
|
|
520
|
+
env: { ...process.env }
|
|
521
|
+
});
|
|
522
|
+
let response = '';
|
|
523
|
+
let error = '';
|
|
524
|
+
|
|
525
|
+
moltbot.stdout.on('data', (data) => response += data.toString());
|
|
526
|
+
moltbot.stderr.on('data', (data) => error += data.toString());
|
|
527
|
+
|
|
528
|
+
moltbot.on('error', (err) => {
|
|
529
|
+
console.error('✗ Failed to start Moltbot:', err.message);
|
|
530
|
+
reject(new Error('Moltbot not found. Install with: npm install -g moltbot@latest'));
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
moltbot.on('close', (code) => {
|
|
534
|
+
if (code === 0) {
|
|
535
|
+
console.log('✓ Moltbot responded');
|
|
536
|
+
resolve(response.trim());
|
|
537
|
+
} else {
|
|
538
|
+
console.error('✗ Moltbot error:', error);
|
|
539
|
+
reject(new Error(error || \`Exit code \${code}\`));
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
function connect() {
|
|
546
|
+
ws = new WebSocket(RELAY, {
|
|
547
|
+
headers: { 'Authorization': \`Bearer \${TOKEN}\` }
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
ws.on('open', () => {
|
|
551
|
+
console.log('🦞 Connected to Spawn.wtf (Moltbot bridge mode)');
|
|
552
|
+
sendText(\`\${NAME} is online (powered by Moltbot 🦞)\`);
|
|
553
|
+
updateStatus('idle', 'Ready for commands');
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
ws.on('message', async (data) => {
|
|
557
|
+
const msg = JSON.parse(data.toString());
|
|
558
|
+
|
|
559
|
+
if (msg.type === 'message') {
|
|
560
|
+
const text = msg.payload?.text || '';
|
|
561
|
+
console.log('📱 From Spawn:', text);
|
|
562
|
+
|
|
563
|
+
try {
|
|
564
|
+
const response = await askMoltbot(text);
|
|
565
|
+
sendText(response);
|
|
566
|
+
updateStatus('idle', 'Ready');
|
|
567
|
+
} catch (err) {
|
|
568
|
+
sendText(\`Error: \${err.message}\`);
|
|
569
|
+
updateStatus('idle', 'Ready');
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
ws.on('close', () => {
|
|
575
|
+
console.log('Disconnected, reconnecting in 5s...');
|
|
576
|
+
setTimeout(connect, 5000);
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
ws.on('error', (err) => console.error('WebSocket error:', err.message));
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
setInterval(() => ws?.readyState === WebSocket.OPEN && send('ping', {}), 30000);
|
|
583
|
+
|
|
584
|
+
console.log('🦞 Starting Spawn → Moltbot bridge...');
|
|
585
|
+
connect();
|
|
586
|
+
|
|
587
|
+
process.on('SIGINT', () => { ws?.close(); process.exit(0); });
|
|
588
|
+
`;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
async function createSkillFiles(token, agentName, language, useMoltbot = false) {
|
|
643
592
|
const skillDir = path.join(process.cwd(), 'spawn');
|
|
644
593
|
|
|
645
594
|
// Create spawn directory
|
|
@@ -655,14 +604,17 @@ async function createSkillFiles(token, agentName, language, claudeCode = false)
|
|
|
655
604
|
name: agentName,
|
|
656
605
|
token: token,
|
|
657
606
|
relay: 'wss://spawn-relay.ngvsqdjj5r.workers.dev/v1/agent',
|
|
658
|
-
language: language
|
|
659
|
-
claudeCode: claudeCode
|
|
607
|
+
language: language
|
|
660
608
|
};
|
|
661
609
|
fs.writeFileSync(path.join(skillDir, 'config.json'), JSON.stringify(config, null, 2));
|
|
662
610
|
|
|
663
611
|
if (language === 'typescript') {
|
|
664
612
|
// TypeScript/Node setup
|
|
665
|
-
|
|
613
|
+
if (useMoltbot) {
|
|
614
|
+
fs.writeFileSync(path.join(skillDir, 'connect.js'), getMoltbotBridge(token, agentName));
|
|
615
|
+
} else {
|
|
616
|
+
fs.writeFileSync(path.join(skillDir, 'connect.js'), getTypeScriptConnector(token, agentName));
|
|
617
|
+
}
|
|
666
618
|
|
|
667
619
|
const packageJson = {
|
|
668
620
|
name: "spawn-agent",
|
|
@@ -681,45 +633,7 @@ async function createSkillFiles(token, agentName, language, claudeCode = false)
|
|
|
681
633
|
fs.writeFileSync(path.join(skillDir, 'requirements.txt'), 'websockets>=12.0\n');
|
|
682
634
|
}
|
|
683
635
|
|
|
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 };
|
|
636
|
+
return { skillDir, language, useMoltbot };
|
|
723
637
|
}
|
|
724
638
|
|
|
725
639
|
async function main() {
|
|
@@ -785,9 +699,9 @@ async function main() {
|
|
|
785
699
|
|
|
786
700
|
questions.push({
|
|
787
701
|
type: 'confirm',
|
|
788
|
-
name: '
|
|
789
|
-
message: '
|
|
790
|
-
default:
|
|
702
|
+
name: 'useMoltbot',
|
|
703
|
+
message: 'Use Moltbot as your AI backend? (recommended)',
|
|
704
|
+
default: false
|
|
791
705
|
});
|
|
792
706
|
|
|
793
707
|
const answers = await inquirer.prompt(questions);
|
|
@@ -795,14 +709,29 @@ async function main() {
|
|
|
795
709
|
token = token || answers.token;
|
|
796
710
|
agentName = answers.agentName || agentName;
|
|
797
711
|
language = language || answers.language;
|
|
798
|
-
const
|
|
712
|
+
const useMoltbot = answers.useMoltbot || false;
|
|
799
713
|
|
|
800
714
|
console.log('');
|
|
801
715
|
|
|
716
|
+
// Check for Moltbot if needed
|
|
717
|
+
if (useMoltbot) {
|
|
718
|
+
const moltbotCheck = ora('Checking for Moltbot...').start();
|
|
719
|
+
try {
|
|
720
|
+
const { execSync } = await import('child_process');
|
|
721
|
+
execSync('which moltbot', { stdio: 'pipe' });
|
|
722
|
+
moltbotCheck.succeed('Moltbot found');
|
|
723
|
+
} catch {
|
|
724
|
+
moltbotCheck.warn('Moltbot not installed');
|
|
725
|
+
console.log(dim(' Install with: npm install -g moltbot@latest'));
|
|
726
|
+
console.log(dim(' Then run: moltbot onboard'));
|
|
727
|
+
console.log('');
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
802
731
|
// Create files
|
|
803
732
|
const createSpinner = ora('Creating skill files...').start();
|
|
804
733
|
try {
|
|
805
|
-
const { skillDir } = await createSkillFiles(token, agentName, language,
|
|
734
|
+
const { skillDir } = await createSkillFiles(token, agentName, language, useMoltbot);
|
|
806
735
|
createSpinner.succeed('Created skill files');
|
|
807
736
|
} catch (err) {
|
|
808
737
|
createSpinner.fail('Failed to create skill files');
|
|
@@ -810,18 +739,6 @@ async function main() {
|
|
|
810
739
|
process.exit(1);
|
|
811
740
|
}
|
|
812
741
|
|
|
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
742
|
console.log('');
|
|
826
743
|
console.log(chalk.green.bold('✓ Spawn.wtf skill installed!'));
|
|
827
744
|
console.log('');
|
|
@@ -832,20 +749,14 @@ async function main() {
|
|
|
832
749
|
console.log(dim(' spawn/config.json'));
|
|
833
750
|
console.log(dim(' spawn/connect.js'));
|
|
834
751
|
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
752
|
console.log('');
|
|
841
753
|
console.log(' Next steps:');
|
|
842
754
|
console.log('');
|
|
843
755
|
console.log(' 1. ' + chalk.cyan('Install dependencies:'));
|
|
844
|
-
console.log(' ' + dim('cd spawn'));
|
|
845
|
-
console.log(' ' + dim('npm install'));
|
|
756
|
+
console.log(' ' + dim('cd spawn && npm install'));
|
|
846
757
|
console.log('');
|
|
847
758
|
console.log(' 2. ' + chalk.cyan('Run the connector:'));
|
|
848
|
-
console.log(' ' + dim('node connect.js'));
|
|
759
|
+
console.log(' ' + dim('node spawn/connect.js'));
|
|
849
760
|
} else {
|
|
850
761
|
console.log(' Files created:');
|
|
851
762
|
console.log(dim(' spawn/SKILL.md'));
|
|
@@ -853,49 +764,18 @@ async function main() {
|
|
|
853
764
|
console.log(dim(' spawn/connect.py'));
|
|
854
765
|
console.log(dim(' spawn/spawn_sdk.py'));
|
|
855
766
|
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
767
|
console.log('');
|
|
862
768
|
console.log(' Next steps:');
|
|
863
769
|
console.log('');
|
|
864
770
|
console.log(' 1. ' + chalk.cyan('Install dependencies:'));
|
|
865
|
-
console.log(' ' + dim('cd spawn'));
|
|
866
|
-
console.log(' ' + dim('pip install -r requirements.txt'));
|
|
771
|
+
console.log(' ' + dim('cd spawn && pip install -r requirements.txt'));
|
|
867
772
|
console.log('');
|
|
868
773
|
console.log(' 2. ' + chalk.cyan('Run the connector:'));
|
|
869
|
-
console.log(' ' + dim('python connect.py'));
|
|
774
|
+
console.log(' ' + dim('python spawn/connect.py'));
|
|
870
775
|
}
|
|
871
776
|
|
|
872
777
|
console.log('');
|
|
873
778
|
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
779
|
console.log('');
|
|
900
780
|
console.log(' Docs: ' + pink('https://github.com/SpawnWTF/spawn'));
|
|
901
781
|
console.log('');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spawn-skill",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
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
|
+
}
|