spaceshipai 0.1.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/init.js ADDED
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { detect } from '../src/detect.js'
4
+ import {
5
+ installClaudeCode,
6
+ installCursor,
7
+ installVscode,
8
+ installWindsurf,
9
+ } from '../src/install.js'
10
+ import { promptApiKey } from '../src/prompt.js'
11
+
12
+ const TEAL = '\x1b[36m'
13
+ const GREEN = '\x1b[32m'
14
+ const DIM = '\x1b[2m'
15
+ const BOLD = '\x1b[1m'
16
+ const RESET = '\x1b[0m'
17
+
18
+ async function main() {
19
+ console.log(`\n${BOLD}${TEAL}Spaceship AI${RESET} — MCP installer\n`)
20
+
21
+ // Resolve API key: env var → prompt
22
+ let apiKey = process.env.SPACESHIP_API_KEY
23
+ if (!apiKey) {
24
+ apiKey = await promptApiKey()
25
+ }
26
+
27
+ if (!apiKey || !apiKey.startsWith('sk_')) {
28
+ console.error('\nInvalid API key. Keys must start with sk_live_ or sk_test_.')
29
+ process.exit(1)
30
+ }
31
+
32
+ // Detect installed tools
33
+ const tools = detect()
34
+ const anyDetected = Object.values(tools).some(Boolean)
35
+
36
+ if (!anyDetected) {
37
+ console.log(
38
+ `${DIM}No supported AI coding tools detected.${RESET}\n` +
39
+ `Supported tools: Claude Code, Cursor, VS Code, Windsurf\n`
40
+ )
41
+ process.exit(0)
42
+ }
43
+
44
+ console.log('Installing Spaceship MCP server...\n')
45
+
46
+ const results = []
47
+
48
+ if (tools.claudeCode) {
49
+ try {
50
+ installClaudeCode(apiKey)
51
+ results.push(`${GREEN}✓${RESET} Claude Code`)
52
+ } catch {
53
+ results.push(`✗ Claude Code ${DIM}(install failed — run: claude mcp add --transport stdio spaceship --env SPACESHIP_API_KEY=${apiKey} -- uvx spaceship-mcp)${RESET}`)
54
+ }
55
+ } else {
56
+ results.push(`${DIM}— Claude Code not detected (skipped)${RESET}`)
57
+ }
58
+
59
+ if (tools.cursor) {
60
+ try {
61
+ installCursor(apiKey)
62
+ results.push(`${GREEN}✓${RESET} Cursor`)
63
+ } catch (e) {
64
+ results.push(`✗ Cursor ${DIM}(${e.message})${RESET}`)
65
+ }
66
+ } else {
67
+ results.push(`${DIM}— Cursor not detected (skipped)${RESET}`)
68
+ }
69
+
70
+ if (tools.vscode) {
71
+ try {
72
+ installVscode(apiKey)
73
+ results.push(`${GREEN}✓${RESET} VS Code`)
74
+ } catch (e) {
75
+ results.push(`✗ VS Code ${DIM}(${e.message})${RESET}`)
76
+ }
77
+ } else {
78
+ results.push(`${DIM}— VS Code not detected (skipped)${RESET}`)
79
+ }
80
+
81
+ if (tools.windsurf) {
82
+ try {
83
+ installWindsurf(apiKey)
84
+ results.push(`${GREEN}✓${RESET} Windsurf`)
85
+ } catch (e) {
86
+ results.push(`✗ Windsurf ${DIM}(${e.message})${RESET}`)
87
+ }
88
+ } else {
89
+ results.push(`${DIM}— Windsurf not detected (skipped)${RESET}`)
90
+ }
91
+
92
+ console.log(results.join('\n'))
93
+ console.log(`\n${TEAL}Spaceship MCP is ready.${RESET} Restart your IDE if it was open.\n`)
94
+ }
95
+
96
+ main().catch((err) => {
97
+ console.error('Error:', err.message)
98
+ process.exit(1)
99
+ })
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "spaceshipai",
3
+ "version": "0.1.0",
4
+ "description": "Spaceship AI CLI — connect your AI coding tools, manage agents, and more",
5
+ "type": "module",
6
+ "bin": {
7
+ "spaceshipai": "bin/init.js"
8
+ },
9
+ "engines": {
10
+ "node": ">=18"
11
+ },
12
+ "keywords": [
13
+ "spaceship",
14
+ "ai",
15
+ "mcp",
16
+ "agents",
17
+ "claude",
18
+ "cursor"
19
+ ],
20
+ "license": "MIT",
21
+ "homepage": "https://spaceshipai.io",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/Spaceship-AI/spaceshipai-cli.git"
25
+ }
26
+ }
package/src/detect.js ADDED
@@ -0,0 +1,23 @@
1
+ import { existsSync } from 'fs'
2
+ import { homedir } from 'os'
3
+ import { execSync } from 'child_process'
4
+
5
+ const home = homedir()
6
+
7
+ function cliExists(cmd) {
8
+ try {
9
+ execSync(`which ${cmd}`, { stdio: 'ignore' })
10
+ return true
11
+ } catch {
12
+ return false
13
+ }
14
+ }
15
+
16
+ export function detect() {
17
+ return {
18
+ claudeCode: cliExists('claude') || existsSync(`${home}/.claude`),
19
+ cursor: existsSync(`${home}/.cursor`),
20
+ vscode: cliExists('code') || existsSync(`${home}/.vscode`),
21
+ windsurf: existsSync(`${home}/.codeium/windsurf`),
22
+ }
23
+ }
package/src/install.js ADDED
@@ -0,0 +1,58 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs'
2
+ import { homedir } from 'os'
3
+ import { execSync } from 'child_process'
4
+ import { dirname } from 'path'
5
+
6
+ const home = homedir()
7
+
8
+ const MCP_ENTRY = (key) => ({
9
+ command: 'uvx',
10
+ args: ['spaceship-mcp'],
11
+ env: { SPACESHIP_API_KEY: key },
12
+ })
13
+
14
+ function readJsonFile(path, fallback = {}) {
15
+ if (!existsSync(path)) return fallback
16
+ try {
17
+ return JSON.parse(readFileSync(path, 'utf8'))
18
+ } catch {
19
+ return fallback
20
+ }
21
+ }
22
+
23
+ function writeJsonFile(path, data) {
24
+ mkdirSync(dirname(path), { recursive: true })
25
+ writeFileSync(path, JSON.stringify(data, null, 2) + '\n', 'utf8')
26
+ }
27
+
28
+ export function installClaudeCode(key) {
29
+ execSync(
30
+ `claude mcp add --transport stdio spaceship --env SPACESHIP_API_KEY=${key} -- uvx spaceship-mcp`,
31
+ { stdio: 'ignore' }
32
+ )
33
+ }
34
+
35
+ export function installCursor(key) {
36
+ const configPath = `${home}/.cursor/mcp.json`
37
+ const config = readJsonFile(configPath, { mcpServers: {} })
38
+ config.mcpServers = config.mcpServers || {}
39
+ config.mcpServers.spaceship = MCP_ENTRY(key)
40
+ writeJsonFile(configPath, config)
41
+ }
42
+
43
+ export function installVscode(key) {
44
+ // VS Code user-level MCP config (cross-platform compatible path)
45
+ const configPath = `${home}/.vscode/mcp.json`
46
+ const config = readJsonFile(configPath, { servers: {} })
47
+ config.servers = config.servers || {}
48
+ config.servers.spaceship = MCP_ENTRY(key)
49
+ writeJsonFile(configPath, config)
50
+ }
51
+
52
+ export function installWindsurf(key) {
53
+ const configPath = `${home}/.codeium/windsurf/mcp_config.json`
54
+ const config = readJsonFile(configPath, { mcpServers: {} })
55
+ config.mcpServers = config.mcpServers || {}
56
+ config.mcpServers.spaceship = MCP_ENTRY(key)
57
+ writeJsonFile(configPath, config)
58
+ }
package/src/prompt.js ADDED
@@ -0,0 +1,12 @@
1
+ import { createInterface } from 'readline'
2
+
3
+ export async function promptApiKey() {
4
+ const rl = createInterface({ input: process.stdin, output: process.stderr })
5
+
6
+ return new Promise((resolve) => {
7
+ rl.question('Enter your Spaceship API key (sk_live_...): ', (answer) => {
8
+ rl.close()
9
+ resolve(answer.trim())
10
+ })
11
+ })
12
+ }