@recursiv/cli 0.1.10 → 0.1.12
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.
|
@@ -113,15 +113,31 @@ var DASHBOARD_URL = "https://recursiv.io/dashboard/api-keys";
|
|
|
113
113
|
var DEFAULT_SCOPES = [
|
|
114
114
|
"posts:read",
|
|
115
115
|
"posts:write",
|
|
116
|
+
"users:read",
|
|
117
|
+
"users:write",
|
|
118
|
+
"communities:read",
|
|
119
|
+
"communities:write",
|
|
116
120
|
"chat:read",
|
|
117
121
|
"chat:write",
|
|
118
|
-
"agents:read",
|
|
119
|
-
"agents:write",
|
|
120
122
|
"projects:read",
|
|
121
123
|
"projects:write",
|
|
122
|
-
"
|
|
123
|
-
"
|
|
124
|
-
"
|
|
124
|
+
"agents:read",
|
|
125
|
+
"agents:write",
|
|
126
|
+
"organizations:read",
|
|
127
|
+
"organizations:write",
|
|
128
|
+
"memory:read",
|
|
129
|
+
"memory:write",
|
|
130
|
+
"notifications:read",
|
|
131
|
+
"notifications:write",
|
|
132
|
+
"settings:read",
|
|
133
|
+
"settings:write",
|
|
134
|
+
"tags:read",
|
|
135
|
+
"tags:write",
|
|
136
|
+
"uploads:write",
|
|
137
|
+
"commands:read",
|
|
138
|
+
"commands:write",
|
|
139
|
+
"billing:read",
|
|
140
|
+
"billing:write"
|
|
125
141
|
];
|
|
126
142
|
function isValidKeyFormat(key) {
|
|
127
143
|
return API_KEY_PATTERN.test(key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bin/create-recursiv-app.ts","../../src/commands/init.ts","../../src/lib/logger.ts","../../src/lib/config.ts","../../src/lib/env.ts","../../src/lib/templates.ts","../../src/lib/auth-flow.ts","../../src/lib/package-manager.ts","../../src/templates/registry.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { initCommand } from '../commands/init.js';\n\nconst program = new Command();\n\nprogram\n .name('create-recursiv-app')\n .description('Create a new Recursiv application')\n .version('0.1.0')\n .argument('[name]', 'project name')\n .action(async (name?: string) => {\n try {\n await initCommand(name);\n } catch (err) {\n console.error(err instanceof Error ? err.message : err);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","import { existsSync } from 'node:fs';\nimport { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { resolve, basename } from 'node:path';\nimport { execSync } from 'node:child_process';\nimport prompts from 'prompts';\nimport pc from 'picocolors';\nimport ora from 'ora';\nimport { log, banner } from '../lib/logger.js';\nimport { createConfig, writeConfig } from '../lib/config.js';\nimport { writeEnvFile } from '../lib/env.js';\nimport { cloneTemplate } from '../lib/templates.js';\nimport { getOrCreateApiKey } from '../lib/auth-flow.js';\nimport { detectFromUserAgent, installCommand, runCommand } from '../lib/package-manager.js';\nimport { templates, type Template } from '../templates/registry.js';\n\nexport async function initCommand(nameArg?: string): Promise<void> {\n banner();\n\n const totalSteps = 7;\n\n // 1. Project name\n log.step(1, totalSteps, 'Project setup');\n let projectName: string;\n if (nameArg) {\n projectName = nameArg;\n } else {\n const { name } = await prompts(\n {\n type: 'text',\n name: 'name',\n message: 'Project name',\n initial: 'my-recursiv-app',\n validate: (v: string) => (v.trim() ? true : 'Name is required'),\n },\n { onCancel: () => process.exit(1) }\n );\n projectName = name;\n }\n\n const projectDir = resolve(process.cwd(), projectName);\n\n if (existsSync(projectDir)) {\n log.error(`Directory ${pc.bold(projectName)} already exists`);\n process.exit(1);\n }\n\n // 2. Template selection\n log.step(2, totalSteps, 'Choose a template');\n const templateChoices = templates.map((t) => ({\n title: t.recommended ? `${t.name} ${pc.dim('(recommended)')}` : t.name,\n description: t.description,\n value: t.id,\n }));\n\n const { templateId } = await prompts(\n {\n type: 'select',\n name: 'templateId',\n message: 'Template',\n choices: templateChoices,\n initial: 0,\n },\n { onCancel: () => process.exit(1) }\n );\n\n const template = templates.find((t) => t.id === templateId) as Template;\n\n // 3. API key\n log.step(3, totalSteps, 'Authentication');\n const apiKey = await getOrCreateApiKey('https://api.recursiv.io/api/v1');\n\n // 4. Clone template\n log.step(4, totalSteps, 'Creating project');\n await mkdir(projectDir, { recursive: true });\n await cloneTemplate(template, projectDir);\n\n // Fix: ensure next.config is valid JS (templates may ship TypeScript syntax in .mjs/.ts)\n const nextConfigTs = resolve(projectDir, 'next.config.ts');\n const nextConfigMjs = resolve(projectDir, 'next.config.mjs');\n const cleanNextConfig = '/** @type {import(\"next\").NextConfig} */\\nconst nextConfig = {};\\nexport default nextConfig;\\n';\n\n if (existsSync(nextConfigTs)) {\n await unlink(nextConfigTs);\n // Remove stale .mjs if template shipped both\n if (existsSync(nextConfigMjs)) await unlink(nextConfigMjs);\n await writeFile(nextConfigMjs, cleanNextConfig, 'utf-8');\n } else if (existsSync(nextConfigMjs)) {\n // Template may have .mjs with TypeScript syntax (import type) — replace it\n const content = await readFile(nextConfigMjs, 'utf-8');\n if (content.includes('import type') || content.includes(': NextConfig')) {\n await writeFile(nextConfigMjs, cleanNextConfig, 'utf-8');\n }\n }\n\n // 5. Write config files\n log.step(5, totalSteps, 'Writing config');\n const pm = detectFromUserAgent();\n\n const config = createConfig({\n name: projectName,\n template: template.id,\n framework: template.framework,\n port: template.devPort,\n devCommand: runCommand(pm, 'dev'),\n });\n await writeConfig(projectDir, config);\n\n if (apiKey) {\n await writeEnvFile(projectDir, apiKey);\n }\n\n // Write .gitignore if it doesn't exist\n const gitignorePath = resolve(projectDir, '.gitignore');\n if (!existsSync(gitignorePath)) {\n await writeFile(\n gitignorePath,\n ['node_modules', 'dist', '.env', '.env.local', '.next', '.turbo', ''].join('\\n'),\n 'utf-8'\n );\n }\n\n // 6. Install dependencies\n log.step(6, totalSteps, 'Installing dependencies');\n const installSpinner = ora(`Running ${pc.bold(installCommand(pm))}...`).start();\n try {\n execSync(installCommand(pm), {\n cwd: projectDir,\n stdio: 'pipe',\n timeout: 120_000,\n });\n installSpinner.succeed('Dependencies installed');\n } catch {\n installSpinner.warn('Could not install dependencies — run install manually');\n }\n\n // 7. Init git\n log.step(7, totalSteps, 'Initializing git');\n try {\n execSync('git init', { cwd: projectDir, stdio: 'pipe' });\n execSync('git add -A', { cwd: projectDir, stdio: 'pipe' });\n execSync('git commit -m \"Initial commit from create-recursiv-app\"', {\n cwd: projectDir,\n stdio: 'pipe',\n });\n log.success('Git repository initialized');\n } catch {\n log.warn('Could not initialize git repository');\n }\n\n // Done!\n log.blank();\n console.log(pc.bold(pc.green('Your Recursiv app is ready!')));\n log.blank();\n console.log(' Next steps:');\n console.log();\n console.log(` ${pc.dim('$')} cd ${projectName}`);\n if (!apiKey) {\n console.log(` ${pc.dim('$')} ${pc.dim('# Add your API key to .env')}`);\n }\n console.log(` ${pc.dim('$')} ${runCommand(pm, 'dev')}`);\n log.blank();\n console.log(pc.dim('Docs: https://docs.recursiv.io'));\n console.log(pc.dim('Dashboard: https://recursiv.io/dashboard'));\n log.blank();\n}\n","import pc from 'picocolors';\n\nexport const log = {\n info(msg: string) {\n console.log(pc.cyan('info') + ' ' + msg);\n },\n success(msg: string) {\n console.log(pc.green('ok') + ' ' + msg);\n },\n warn(msg: string) {\n console.log(pc.yellow('warn') + ' ' + msg);\n },\n error(msg: string) {\n console.error(pc.red('error') + ' ' + msg);\n },\n step(n: number, total: number, msg: string) {\n console.log(pc.dim(`[${n}/${total}]`) + ' ' + msg);\n },\n blank() {\n console.log();\n },\n};\n\nexport function banner() {\n console.log();\n console.log(pc.bold('Recursiv') + pc.dim(' — build and ship apps with AI'));\n console.log();\n}\n","import { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport interface RecursivConfig {\n version: number;\n project: {\n name: string;\n template: string;\n framework: string;\n };\n api: {\n baseUrl: string;\n };\n dev: {\n port: number;\n command: string;\n };\n}\n\nconst CONFIG_FILE = '.recursiv.json';\n\nexport function configPath(dir: string): string {\n return join(dir, CONFIG_FILE);\n}\n\nexport async function readConfig(dir: string): Promise<RecursivConfig | null> {\n try {\n const raw = await readFile(configPath(dir), 'utf-8');\n return JSON.parse(raw) as RecursivConfig;\n } catch {\n return null;\n }\n}\n\nexport async function writeConfig(dir: string, config: RecursivConfig): Promise<void> {\n await writeFile(configPath(dir), JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function createConfig(opts: {\n name: string;\n template: string;\n framework: string;\n port?: number;\n devCommand?: string;\n}): RecursivConfig {\n return {\n version: 1,\n project: {\n name: opts.name,\n template: opts.template,\n framework: opts.framework,\n },\n api: {\n baseUrl: 'https://api.recursiv.io/api/v1',\n },\n dev: {\n port: opts.port ?? 3000,\n command: opts.devCommand ?? 'npm run dev',\n },\n };\n}\n","import { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport async function writeEnvFile(dir: string, apiKey: string): Promise<void> {\n const envPath = join(dir, '.env');\n const content = [\n '# Recursiv API key',\n `RECURSIV_API_KEY=${apiKey}`,\n '',\n ].join('\\n');\n await writeFile(envPath, content, 'utf-8');\n}\n\nexport async function readApiKeyFromEnv(dir: string): Promise<string | null> {\n try {\n const raw = await readFile(join(dir, '.env'), 'utf-8');\n const match = raw.match(/^RECURSIV_API_KEY=(.+)$/m);\n return match?.[1]?.trim() ?? null;\n } catch {\n return null;\n }\n}\n\nexport async function updateApiKeyInEnv(dir: string, apiKey: string): Promise<void> {\n const envPath = join(dir, '.env');\n let content: string;\n try {\n content = await readFile(envPath, 'utf-8');\n if (content.includes('RECURSIV_API_KEY=')) {\n content = content.replace(/^RECURSIV_API_KEY=.+$/m, `RECURSIV_API_KEY=${apiKey}`);\n } else {\n content += `\\nRECURSIV_API_KEY=${apiKey}\\n`;\n }\n } catch {\n content = `RECURSIV_API_KEY=${apiKey}\\n`;\n }\n await writeFile(envPath, content, 'utf-8');\n}\n","import degit from 'degit';\nimport ora from 'ora';\nimport type { Template } from '../templates/registry.js';\n\nexport async function cloneTemplate(template: Template, dest: string): Promise<void> {\n const spinner = ora(`Cloning ${template.name} template...`).start();\n try {\n const emitter = degit(template.repo, {\n cache: false,\n force: true,\n verbose: false,\n });\n\n await emitter.clone(dest);\n spinner.succeed(`Template cloned successfully`);\n } catch (err) {\n spinner.fail('Failed to clone template');\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `Could not clone template from ${template.repo}.\\n` +\n `Make sure you have internet access and the repo exists.\\n` +\n `Details: ${message}`\n );\n }\n}\n","import prompts from 'prompts';\nimport pc from 'picocolors';\nimport { log } from './logger.js';\n\nconst API_KEY_PATTERN = /^sk_(live|test)_[a-zA-Z0-9]{20,}$/;\nconst DASHBOARD_URL = 'https://recursiv.io/dashboard/api-keys';\n\nconst DEFAULT_SCOPES = [\n 'posts:read',\n 'posts:write',\n 'chat:read',\n 'chat:write',\n 'agents:read',\n 'agents:write',\n 'projects:read',\n 'projects:write',\n 'communities:read',\n 'communities:write',\n 'users:read',\n];\n\nexport function isValidKeyFormat(key: string): boolean {\n return API_KEY_PATTERN.test(key);\n}\n\nexport async function validateApiKey(apiKey: string, baseUrl: string): Promise<boolean> {\n try {\n const res = await fetch(`${baseUrl}/users/me`, {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n Accept: 'application/json',\n },\n });\n return res.ok;\n } catch {\n return false;\n }\n}\n\n/**\n * Terminal signup flow — create a Recursiv account and API key without a browser.\n *\n * Flow (passwordless OTP):\n * 1. Prompt for email\n * 2. Send 6-digit OTP code via server\n * 3. Prompt user to enter the code\n * 4. Verify OTP → get session cookie\n * 5. Use session cookie to create an API key via REST endpoint\n * 6. Return the API key string\n */\nexport async function terminalSignup(baseUrl: string): Promise<string | null> {\n // baseUrl is like https://recursiv.io/api/v1 — we need the root for auth endpoints\n const rootUrl = baseUrl.replace(/\\/api\\/v1\\/?$/, '');\n\n console.log();\n console.log(pc.bold('Sign in to Recursiv'));\n console.log(pc.dim('We\\'ll send a 6-digit code to your email — no password needed.'));\n console.log(pc.dim('If your email isn\\'t registered yet, we\\'ll create a free account.'));\n console.log(pc.dim('Free tier: 1,000 API calls/day, 1 agent, 3 projects'));\n console.log();\n\n const { email } = await prompts(\n {\n type: 'text',\n name: 'email',\n message: 'Email',\n validate: (v: string) => {\n if (!v || !v.includes('@')) return 'Valid email required';\n return true;\n },\n },\n { onCancel: () => process.exit(1) },\n );\n\n // Better Auth requires an Origin header for CSRF protection\n const origin = rootUrl || 'https://api.recursiv.io';\n const authHeaders = { 'Content-Type': 'application/json', Origin: origin };\n\n // Send OTP code\n try {\n const sendRes = await fetch(`${rootUrl}/api/auth/email-otp/send-verification-otp`, {\n method: 'POST',\n headers: authHeaders,\n body: JSON.stringify({ email, type: 'sign-in' }),\n });\n\n if (!sendRes.ok) {\n const errBody = await sendRes.text().catch(() => '');\n log.error(`Failed to send code (${sendRes.status}): ${errBody || 'Unknown error'}`);\n return null;\n }\n } catch (err) {\n log.error(\n `Could not reach ${rootUrl} — ${err instanceof Error ? err.message : 'network error'}`,\n );\n log.info(`You can create an API key manually at ${pc.underline(DASHBOARD_URL)}`);\n return null;\n }\n\n log.success(`Verification code sent to ${email}`);\n console.log();\n\n // Prompt for OTP code\n const { code } = await prompts(\n {\n type: 'text',\n name: 'code',\n message: 'Enter the 6-digit code',\n validate: (v: string) => {\n if (!v || !/^\\d{6}$/.test(v.trim())) return 'Enter the 6-digit code from your email';\n return true;\n },\n },\n { onCancel: () => process.exit(1) },\n );\n\n // Verify OTP and sign in. better-auth's email-OTP plugin exposes two\n // separate endpoints:\n // - /api/auth/sign-in/email-otp → signs an existing user in (returns\n // a session), or creates the account if disableSignUp is false (our\n // config). This is the right endpoint for both first-time signup and\n // returning sign-in.\n // - /api/auth/email-otp/verify-email → strictly for confirming an\n // already-signed-in user's email address. Existing users hit\n // \"Invalid OTP\" here because the OTP was minted with type='sign-in'.\n let sessionCookie: string | null = null;\n\n try {\n const verifyRes = await fetch(`${rootUrl}/api/auth/sign-in/email-otp`, {\n method: 'POST',\n headers: authHeaders,\n body: JSON.stringify({ email, otp: code.trim() }),\n redirect: 'manual',\n });\n\n if (verifyRes.ok || verifyRes.status === 302) {\n sessionCookie = extractSessionCookie(verifyRes);\n } else {\n const errBody = await verifyRes.text().catch(() => '');\n log.error(`Verification failed (${verifyRes.status}): ${errBody || 'Invalid or expired code'}`);\n return null;\n }\n } catch (err) {\n log.error(\n `Verification failed — ${err instanceof Error ? err.message : 'network error'}`,\n );\n return null;\n }\n\n if (!sessionCookie) {\n log.error('No session returned from server');\n log.info(`Create an API key manually at ${pc.underline(DASHBOARD_URL)}`);\n return null;\n }\n\n log.success('Authenticated');\n\n // Create an API key using the session\n try {\n const keyRes = await fetch(`${baseUrl}/api-keys`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Cookie: sessionCookie,\n },\n body: JSON.stringify({\n name: 'CLI (auto-created)',\n scopes: DEFAULT_SCOPES,\n }),\n });\n\n if (!keyRes.ok) {\n const errBody = await keyRes.text().catch(() => '');\n log.error(`Failed to create API key (${keyRes.status}): ${errBody}`);\n log.info(`Create one manually at ${pc.underline(DASHBOARD_URL)}`);\n return null;\n }\n\n const { data } = (await keyRes.json()) as { data: { key: string } };\n log.success(`API key created (free tier: 1,000 calls/day)`);\n return data.key;\n } catch (err) {\n log.error(\n `Failed to create API key: ${err instanceof Error ? err.message : 'unknown error'}`,\n );\n log.info(`Create one manually at ${pc.underline(DASHBOARD_URL)}`);\n return null;\n }\n}\n\n/**\n * Extract session cookie from a Better Auth response.\n * Better Auth sets cookies via set-cookie header.\n */\nfunction extractSessionCookie(res: Response): string | null {\n // In Node.js, getSetCookie() returns individual cookie strings\n const setCookieHeaders =\n 'getSetCookie' in res.headers\n ? (res.headers as { getSetCookie(): string[] }).getSetCookie()\n : [];\n\n // Fall back to raw header if getSetCookie not available\n if (setCookieHeaders.length === 0) {\n const raw = res.headers.get('set-cookie');\n if (raw) {\n // Multiple cookies may be comma-separated (though non-standard)\n return raw\n .split(',')\n .map((c) => c.split(';')[0].trim())\n .join('; ');\n }\n return null;\n }\n\n // Extract cookie name=value pairs (strip attributes)\n return setCookieHeaders.map((c) => c.split(';')[0].trim()).join('; ');\n}\n\nexport async function promptApiKey(): Promise<string | null> {\n console.log(\n pc.dim(\n `Get your API key from ${pc.underline(DASHBOARD_URL)}\\n` +\n `Keys start with sk_live_ or sk_test_`,\n ),\n );\n console.log();\n\n const { apiKey } = await prompts(\n {\n type: 'text',\n name: 'apiKey',\n message: 'API key (or press Enter to skip)',\n validate: (value: string) => {\n if (!value) return true; // allow skip\n if (!isValidKeyFormat(value)) {\n return 'Invalid key format. Keys start with sk_live_ or sk_test_';\n }\n return true;\n },\n },\n { onCancel: () => process.exit(1) },\n );\n\n if (!apiKey) {\n log.warn('No API key provided — you can add one later in .env');\n return null;\n }\n\n return apiKey;\n}\n\nexport async function promptAndValidateApiKey(baseUrl: string): Promise<string | null> {\n const apiKey = await promptApiKey();\n if (!apiKey) return null;\n\n const valid = await validateApiKey(apiKey, baseUrl);\n if (!valid) {\n log.warn('Could not validate API key (server unreachable or invalid key)');\n log.info('Key saved to .env — you can update it later');\n } else {\n log.success('API key validated');\n }\n\n return apiKey;\n}\n\n/**\n * Get an API key — either from env, by prompting for an existing key,\n * or by creating a new account via terminal signup.\n */\nexport async function getOrCreateApiKey(baseUrl: string): Promise<string | null> {\n console.log();\n\n const { method } = await prompts(\n {\n type: 'select',\n name: 'method',\n message: 'How would you like to authenticate?',\n choices: [\n {\n title: 'Sign in or create an account with my email',\n description: 'We\\'ll send a 6-digit code. Works whether you\\'re new or returning.',\n value: 'signup',\n },\n {\n title: 'Paste an existing API key',\n description: 'Use a key you\\'ve already saved from the dashboard',\n value: 'paste',\n },\n {\n title: 'Skip for now',\n description: 'Add an API key later in .env',\n value: 'skip',\n },\n ],\n },\n { onCancel: () => process.exit(1) },\n );\n\n if (method === 'signup') {\n return terminalSignup(baseUrl);\n }\n\n if (method === 'paste') {\n return promptAndValidateApiKey(baseUrl);\n }\n\n log.warn('No API key — you can add one later in .env');\n return null;\n}\n","import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';\n\nexport function detectPackageManager(dir: string): PackageManager {\n if (existsSync(join(dir, 'bun.lockb')) || existsSync(join(dir, 'bun.lock'))) return 'bun';\n if (existsSync(join(dir, 'pnpm-lock.yaml'))) return 'pnpm';\n if (existsSync(join(dir, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n\nexport function detectFromUserAgent(): PackageManager {\n const ua = process.env.npm_config_user_agent ?? '';\n if (ua.startsWith('bun')) return 'bun';\n if (ua.startsWith('pnpm')) return 'pnpm';\n if (ua.startsWith('yarn')) return 'yarn';\n return 'npm';\n}\n\nexport function installCommand(pm: PackageManager): string {\n return pm === 'yarn' ? 'yarn' : `${pm} install`;\n}\n\nexport function runCommand(pm: PackageManager, script: string): string {\n if (pm === 'npm') return `npm run ${script}`;\n return `${pm} ${script}`;\n}\n","export interface Template {\n id: string;\n name: string;\n description: string;\n repo: string;\n framework: string;\n devCommand: string;\n devPort: number;\n recommended?: boolean;\n}\n\nexport const templates: Template[] = [\n {\n id: 'nextjs',\n name: 'Next.js + Recursiv',\n description: 'Full-stack Next.js app with feeds, chat, and agents',\n repo: 'recursivlabs/template-nextjs',\n framework: 'nextjs',\n devCommand: 'next dev',\n devPort: 3000,\n recommended: true,\n },\n {\n id: 'node',\n name: 'Node.js + Express',\n description: 'Express API server with Recursiv SDK',\n repo: 'recursivlabs/template-node',\n framework: 'express',\n devCommand: 'node --watch src/index.js',\n devPort: 4000,\n },\n {\n id: 'vite',\n name: 'Vite + React',\n description: 'React SPA with social feed components',\n repo: 'recursivlabs/template-vite',\n framework: 'vite',\n devCommand: 'vite',\n devPort: 5173,\n },\n];\n\nexport function getTemplate(id: string): Template | undefined {\n return templates.find((t) => t.id === id);\n}\n\nexport function getDefaultTemplate(): Template {\n return templates.find((t) => t.recommended) ?? templates[0]!;\n}\n"],"mappings":"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","names":["existsSync","readFile","writeFile","prompts","pc","ora","readFile","writeFile","join","pc","pc","join","prompts","existsSync","pc","writeFile","readFile","ora"]}
|
|
1
|
+
{"version":3,"sources":["../../src/bin/create-recursiv-app.ts","../../src/commands/init.ts","../../src/lib/logger.ts","../../src/lib/config.ts","../../src/lib/env.ts","../../src/lib/templates.ts","../../src/lib/auth-flow.ts","../../src/lib/package-manager.ts","../../src/templates/registry.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { initCommand } from '../commands/init.js';\n\nconst program = new Command();\n\nprogram\n .name('create-recursiv-app')\n .description('Create a new Recursiv application')\n .version('0.1.0')\n .argument('[name]', 'project name')\n .action(async (name?: string) => {\n try {\n await initCommand(name);\n } catch (err) {\n console.error(err instanceof Error ? err.message : err);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","import { existsSync } from 'node:fs';\nimport { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { resolve, basename } from 'node:path';\nimport { execSync } from 'node:child_process';\nimport prompts from 'prompts';\nimport pc from 'picocolors';\nimport ora from 'ora';\nimport { log, banner } from '../lib/logger.js';\nimport { createConfig, writeConfig } from '../lib/config.js';\nimport { writeEnvFile } from '../lib/env.js';\nimport { cloneTemplate } from '../lib/templates.js';\nimport { getOrCreateApiKey } from '../lib/auth-flow.js';\nimport { detectFromUserAgent, installCommand, runCommand } from '../lib/package-manager.js';\nimport { templates, type Template } from '../templates/registry.js';\n\nexport async function initCommand(nameArg?: string): Promise<void> {\n banner();\n\n const totalSteps = 7;\n\n // 1. Project name\n log.step(1, totalSteps, 'Project setup');\n let projectName: string;\n if (nameArg) {\n projectName = nameArg;\n } else {\n const { name } = await prompts(\n {\n type: 'text',\n name: 'name',\n message: 'Project name',\n initial: 'my-recursiv-app',\n validate: (v: string) => (v.trim() ? true : 'Name is required'),\n },\n { onCancel: () => process.exit(1) }\n );\n projectName = name;\n }\n\n const projectDir = resolve(process.cwd(), projectName);\n\n if (existsSync(projectDir)) {\n log.error(`Directory ${pc.bold(projectName)} already exists`);\n process.exit(1);\n }\n\n // 2. Template selection\n log.step(2, totalSteps, 'Choose a template');\n const templateChoices = templates.map((t) => ({\n title: t.recommended ? `${t.name} ${pc.dim('(recommended)')}` : t.name,\n description: t.description,\n value: t.id,\n }));\n\n const { templateId } = await prompts(\n {\n type: 'select',\n name: 'templateId',\n message: 'Template',\n choices: templateChoices,\n initial: 0,\n },\n { onCancel: () => process.exit(1) }\n );\n\n const template = templates.find((t) => t.id === templateId) as Template;\n\n // 3. API key\n log.step(3, totalSteps, 'Authentication');\n const apiKey = await getOrCreateApiKey('https://api.recursiv.io/api/v1');\n\n // 4. Clone template\n log.step(4, totalSteps, 'Creating project');\n await mkdir(projectDir, { recursive: true });\n await cloneTemplate(template, projectDir);\n\n // Fix: ensure next.config is valid JS (templates may ship TypeScript syntax in .mjs/.ts)\n const nextConfigTs = resolve(projectDir, 'next.config.ts');\n const nextConfigMjs = resolve(projectDir, 'next.config.mjs');\n const cleanNextConfig = '/** @type {import(\"next\").NextConfig} */\\nconst nextConfig = {};\\nexport default nextConfig;\\n';\n\n if (existsSync(nextConfigTs)) {\n await unlink(nextConfigTs);\n // Remove stale .mjs if template shipped both\n if (existsSync(nextConfigMjs)) await unlink(nextConfigMjs);\n await writeFile(nextConfigMjs, cleanNextConfig, 'utf-8');\n } else if (existsSync(nextConfigMjs)) {\n // Template may have .mjs with TypeScript syntax (import type) — replace it\n const content = await readFile(nextConfigMjs, 'utf-8');\n if (content.includes('import type') || content.includes(': NextConfig')) {\n await writeFile(nextConfigMjs, cleanNextConfig, 'utf-8');\n }\n }\n\n // 5. Write config files\n log.step(5, totalSteps, 'Writing config');\n const pm = detectFromUserAgent();\n\n const config = createConfig({\n name: projectName,\n template: template.id,\n framework: template.framework,\n port: template.devPort,\n devCommand: runCommand(pm, 'dev'),\n });\n await writeConfig(projectDir, config);\n\n if (apiKey) {\n await writeEnvFile(projectDir, apiKey);\n }\n\n // Write .gitignore if it doesn't exist\n const gitignorePath = resolve(projectDir, '.gitignore');\n if (!existsSync(gitignorePath)) {\n await writeFile(\n gitignorePath,\n ['node_modules', 'dist', '.env', '.env.local', '.next', '.turbo', ''].join('\\n'),\n 'utf-8'\n );\n }\n\n // 6. Install dependencies\n log.step(6, totalSteps, 'Installing dependencies');\n const installSpinner = ora(`Running ${pc.bold(installCommand(pm))}...`).start();\n try {\n execSync(installCommand(pm), {\n cwd: projectDir,\n stdio: 'pipe',\n timeout: 120_000,\n });\n installSpinner.succeed('Dependencies installed');\n } catch {\n installSpinner.warn('Could not install dependencies — run install manually');\n }\n\n // 7. Init git\n log.step(7, totalSteps, 'Initializing git');\n try {\n execSync('git init', { cwd: projectDir, stdio: 'pipe' });\n execSync('git add -A', { cwd: projectDir, stdio: 'pipe' });\n execSync('git commit -m \"Initial commit from create-recursiv-app\"', {\n cwd: projectDir,\n stdio: 'pipe',\n });\n log.success('Git repository initialized');\n } catch {\n log.warn('Could not initialize git repository');\n }\n\n // Done!\n log.blank();\n console.log(pc.bold(pc.green('Your Recursiv app is ready!')));\n log.blank();\n console.log(' Next steps:');\n console.log();\n console.log(` ${pc.dim('$')} cd ${projectName}`);\n if (!apiKey) {\n console.log(` ${pc.dim('$')} ${pc.dim('# Add your API key to .env')}`);\n }\n console.log(` ${pc.dim('$')} ${runCommand(pm, 'dev')}`);\n log.blank();\n console.log(pc.dim('Docs: https://docs.recursiv.io'));\n console.log(pc.dim('Dashboard: https://recursiv.io/dashboard'));\n log.blank();\n}\n","import pc from 'picocolors';\n\nexport const log = {\n info(msg: string) {\n console.log(pc.cyan('info') + ' ' + msg);\n },\n success(msg: string) {\n console.log(pc.green('ok') + ' ' + msg);\n },\n warn(msg: string) {\n console.log(pc.yellow('warn') + ' ' + msg);\n },\n error(msg: string) {\n console.error(pc.red('error') + ' ' + msg);\n },\n step(n: number, total: number, msg: string) {\n console.log(pc.dim(`[${n}/${total}]`) + ' ' + msg);\n },\n blank() {\n console.log();\n },\n};\n\nexport function banner() {\n console.log();\n console.log(pc.bold('Recursiv') + pc.dim(' — build and ship apps with AI'));\n console.log();\n}\n","import { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport interface RecursivConfig {\n version: number;\n project: {\n name: string;\n template: string;\n framework: string;\n };\n api: {\n baseUrl: string;\n };\n dev: {\n port: number;\n command: string;\n };\n}\n\nconst CONFIG_FILE = '.recursiv.json';\n\nexport function configPath(dir: string): string {\n return join(dir, CONFIG_FILE);\n}\n\nexport async function readConfig(dir: string): Promise<RecursivConfig | null> {\n try {\n const raw = await readFile(configPath(dir), 'utf-8');\n return JSON.parse(raw) as RecursivConfig;\n } catch {\n return null;\n }\n}\n\nexport async function writeConfig(dir: string, config: RecursivConfig): Promise<void> {\n await writeFile(configPath(dir), JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function createConfig(opts: {\n name: string;\n template: string;\n framework: string;\n port?: number;\n devCommand?: string;\n}): RecursivConfig {\n return {\n version: 1,\n project: {\n name: opts.name,\n template: opts.template,\n framework: opts.framework,\n },\n api: {\n baseUrl: 'https://api.recursiv.io/api/v1',\n },\n dev: {\n port: opts.port ?? 3000,\n command: opts.devCommand ?? 'npm run dev',\n },\n };\n}\n","import { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport async function writeEnvFile(dir: string, apiKey: string): Promise<void> {\n const envPath = join(dir, '.env');\n const content = [\n '# Recursiv API key',\n `RECURSIV_API_KEY=${apiKey}`,\n '',\n ].join('\\n');\n await writeFile(envPath, content, 'utf-8');\n}\n\nexport async function readApiKeyFromEnv(dir: string): Promise<string | null> {\n try {\n const raw = await readFile(join(dir, '.env'), 'utf-8');\n const match = raw.match(/^RECURSIV_API_KEY=(.+)$/m);\n return match?.[1]?.trim() ?? null;\n } catch {\n return null;\n }\n}\n\nexport async function updateApiKeyInEnv(dir: string, apiKey: string): Promise<void> {\n const envPath = join(dir, '.env');\n let content: string;\n try {\n content = await readFile(envPath, 'utf-8');\n if (content.includes('RECURSIV_API_KEY=')) {\n content = content.replace(/^RECURSIV_API_KEY=.+$/m, `RECURSIV_API_KEY=${apiKey}`);\n } else {\n content += `\\nRECURSIV_API_KEY=${apiKey}\\n`;\n }\n } catch {\n content = `RECURSIV_API_KEY=${apiKey}\\n`;\n }\n await writeFile(envPath, content, 'utf-8');\n}\n","import degit from 'degit';\nimport ora from 'ora';\nimport type { Template } from '../templates/registry.js';\n\nexport async function cloneTemplate(template: Template, dest: string): Promise<void> {\n const spinner = ora(`Cloning ${template.name} template...`).start();\n try {\n const emitter = degit(template.repo, {\n cache: false,\n force: true,\n verbose: false,\n });\n\n await emitter.clone(dest);\n spinner.succeed(`Template cloned successfully`);\n } catch (err) {\n spinner.fail('Failed to clone template');\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `Could not clone template from ${template.repo}.\\n` +\n `Make sure you have internet access and the repo exists.\\n` +\n `Details: ${message}`\n );\n }\n}\n","import prompts from 'prompts';\nimport pc from 'picocolors';\nimport { log } from './logger.js';\n\nconst API_KEY_PATTERN = /^sk_(live|test)_[a-zA-Z0-9]{20,}$/;\nconst DASHBOARD_URL = 'https://recursiv.io/dashboard/api-keys';\n\n// Mirror the server's AVAILABLE_SCOPES list (packages/server/src/features/\n// api-keys/apiKeys.router.ts). The dashboard's create-key form defaults to\n// all-selected; keep the CLI quickstart in lockstep so a freshly-minted\n// key works for the full build-your-first-app flow (which needs at minimum\n// organizations:write for provision_app + projects:write for deploy).\nconst DEFAULT_SCOPES = [\n 'posts:read',\n 'posts:write',\n 'users:read',\n 'users:write',\n 'communities:read',\n 'communities:write',\n 'chat:read',\n 'chat:write',\n 'projects:read',\n 'projects:write',\n 'agents:read',\n 'agents:write',\n 'organizations:read',\n 'organizations:write',\n 'memory:read',\n 'memory:write',\n 'notifications:read',\n 'notifications:write',\n 'settings:read',\n 'settings:write',\n 'tags:read',\n 'tags:write',\n 'uploads:write',\n 'commands:read',\n 'commands:write',\n 'billing:read',\n 'billing:write',\n];\n\nexport function isValidKeyFormat(key: string): boolean {\n return API_KEY_PATTERN.test(key);\n}\n\nexport async function validateApiKey(apiKey: string, baseUrl: string): Promise<boolean> {\n try {\n const res = await fetch(`${baseUrl}/users/me`, {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n Accept: 'application/json',\n },\n });\n return res.ok;\n } catch {\n return false;\n }\n}\n\n/**\n * Terminal signup flow — create a Recursiv account and API key without a browser.\n *\n * Flow (passwordless OTP):\n * 1. Prompt for email\n * 2. Send 6-digit OTP code via server\n * 3. Prompt user to enter the code\n * 4. Verify OTP → get session cookie\n * 5. Use session cookie to create an API key via REST endpoint\n * 6. Return the API key string\n */\nexport async function terminalSignup(baseUrl: string): Promise<string | null> {\n // baseUrl is like https://recursiv.io/api/v1 — we need the root for auth endpoints\n const rootUrl = baseUrl.replace(/\\/api\\/v1\\/?$/, '');\n\n console.log();\n console.log(pc.bold('Sign in to Recursiv'));\n console.log(pc.dim('We\\'ll send a 6-digit code to your email — no password needed.'));\n console.log(pc.dim('If your email isn\\'t registered yet, we\\'ll create a free account.'));\n console.log(pc.dim('Free tier: 1,000 API calls/day, 1 agent, 3 projects'));\n console.log();\n\n const { email } = await prompts(\n {\n type: 'text',\n name: 'email',\n message: 'Email',\n validate: (v: string) => {\n if (!v || !v.includes('@')) return 'Valid email required';\n return true;\n },\n },\n { onCancel: () => process.exit(1) },\n );\n\n // Better Auth requires an Origin header for CSRF protection\n const origin = rootUrl || 'https://api.recursiv.io';\n const authHeaders = { 'Content-Type': 'application/json', Origin: origin };\n\n // Send OTP code\n try {\n const sendRes = await fetch(`${rootUrl}/api/auth/email-otp/send-verification-otp`, {\n method: 'POST',\n headers: authHeaders,\n body: JSON.stringify({ email, type: 'sign-in' }),\n });\n\n if (!sendRes.ok) {\n const errBody = await sendRes.text().catch(() => '');\n log.error(`Failed to send code (${sendRes.status}): ${errBody || 'Unknown error'}`);\n return null;\n }\n } catch (err) {\n log.error(\n `Could not reach ${rootUrl} — ${err instanceof Error ? err.message : 'network error'}`,\n );\n log.info(`You can create an API key manually at ${pc.underline(DASHBOARD_URL)}`);\n return null;\n }\n\n log.success(`Verification code sent to ${email}`);\n console.log();\n\n // Prompt for OTP code\n const { code } = await prompts(\n {\n type: 'text',\n name: 'code',\n message: 'Enter the 6-digit code',\n validate: (v: string) => {\n if (!v || !/^\\d{6}$/.test(v.trim())) return 'Enter the 6-digit code from your email';\n return true;\n },\n },\n { onCancel: () => process.exit(1) },\n );\n\n // Verify OTP and sign in. better-auth's email-OTP plugin exposes two\n // separate endpoints:\n // - /api/auth/sign-in/email-otp → signs an existing user in (returns\n // a session), or creates the account if disableSignUp is false (our\n // config). This is the right endpoint for both first-time signup and\n // returning sign-in.\n // - /api/auth/email-otp/verify-email → strictly for confirming an\n // already-signed-in user's email address. Existing users hit\n // \"Invalid OTP\" here because the OTP was minted with type='sign-in'.\n let sessionCookie: string | null = null;\n\n try {\n const verifyRes = await fetch(`${rootUrl}/api/auth/sign-in/email-otp`, {\n method: 'POST',\n headers: authHeaders,\n body: JSON.stringify({ email, otp: code.trim() }),\n redirect: 'manual',\n });\n\n if (verifyRes.ok || verifyRes.status === 302) {\n sessionCookie = extractSessionCookie(verifyRes);\n } else {\n const errBody = await verifyRes.text().catch(() => '');\n log.error(`Verification failed (${verifyRes.status}): ${errBody || 'Invalid or expired code'}`);\n return null;\n }\n } catch (err) {\n log.error(\n `Verification failed — ${err instanceof Error ? err.message : 'network error'}`,\n );\n return null;\n }\n\n if (!sessionCookie) {\n log.error('No session returned from server');\n log.info(`Create an API key manually at ${pc.underline(DASHBOARD_URL)}`);\n return null;\n }\n\n log.success('Authenticated');\n\n // Create an API key using the session\n try {\n const keyRes = await fetch(`${baseUrl}/api-keys`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Cookie: sessionCookie,\n },\n body: JSON.stringify({\n name: 'CLI (auto-created)',\n scopes: DEFAULT_SCOPES,\n }),\n });\n\n if (!keyRes.ok) {\n const errBody = await keyRes.text().catch(() => '');\n log.error(`Failed to create API key (${keyRes.status}): ${errBody}`);\n log.info(`Create one manually at ${pc.underline(DASHBOARD_URL)}`);\n return null;\n }\n\n const { data } = (await keyRes.json()) as { data: { key: string } };\n log.success(`API key created (free tier: 1,000 calls/day)`);\n return data.key;\n } catch (err) {\n log.error(\n `Failed to create API key: ${err instanceof Error ? err.message : 'unknown error'}`,\n );\n log.info(`Create one manually at ${pc.underline(DASHBOARD_URL)}`);\n return null;\n }\n}\n\n/**\n * Extract session cookie from a Better Auth response.\n * Better Auth sets cookies via set-cookie header.\n */\nfunction extractSessionCookie(res: Response): string | null {\n // In Node.js, getSetCookie() returns individual cookie strings\n const setCookieHeaders =\n 'getSetCookie' in res.headers\n ? (res.headers as { getSetCookie(): string[] }).getSetCookie()\n : [];\n\n // Fall back to raw header if getSetCookie not available\n if (setCookieHeaders.length === 0) {\n const raw = res.headers.get('set-cookie');\n if (raw) {\n // Multiple cookies may be comma-separated (though non-standard)\n return raw\n .split(',')\n .map((c) => c.split(';')[0].trim())\n .join('; ');\n }\n return null;\n }\n\n // Extract cookie name=value pairs (strip attributes)\n return setCookieHeaders.map((c) => c.split(';')[0].trim()).join('; ');\n}\n\nexport async function promptApiKey(): Promise<string | null> {\n console.log(\n pc.dim(\n `Get your API key from ${pc.underline(DASHBOARD_URL)}\\n` +\n `Keys start with sk_live_ or sk_test_`,\n ),\n );\n console.log();\n\n const { apiKey } = await prompts(\n {\n type: 'text',\n name: 'apiKey',\n message: 'API key (or press Enter to skip)',\n validate: (value: string) => {\n if (!value) return true; // allow skip\n if (!isValidKeyFormat(value)) {\n return 'Invalid key format. Keys start with sk_live_ or sk_test_';\n }\n return true;\n },\n },\n { onCancel: () => process.exit(1) },\n );\n\n if (!apiKey) {\n log.warn('No API key provided — you can add one later in .env');\n return null;\n }\n\n return apiKey;\n}\n\nexport async function promptAndValidateApiKey(baseUrl: string): Promise<string | null> {\n const apiKey = await promptApiKey();\n if (!apiKey) return null;\n\n const valid = await validateApiKey(apiKey, baseUrl);\n if (!valid) {\n log.warn('Could not validate API key (server unreachable or invalid key)');\n log.info('Key saved to .env — you can update it later');\n } else {\n log.success('API key validated');\n }\n\n return apiKey;\n}\n\n/**\n * Get an API key — either from env, by prompting for an existing key,\n * or by creating a new account via terminal signup.\n */\nexport async function getOrCreateApiKey(baseUrl: string): Promise<string | null> {\n console.log();\n\n const { method } = await prompts(\n {\n type: 'select',\n name: 'method',\n message: 'How would you like to authenticate?',\n choices: [\n {\n title: 'Sign in or create an account with my email',\n description: 'We\\'ll send a 6-digit code. Works whether you\\'re new or returning.',\n value: 'signup',\n },\n {\n title: 'Paste an existing API key',\n description: 'Use a key you\\'ve already saved from the dashboard',\n value: 'paste',\n },\n {\n title: 'Skip for now',\n description: 'Add an API key later in .env',\n value: 'skip',\n },\n ],\n },\n { onCancel: () => process.exit(1) },\n );\n\n if (method === 'signup') {\n return terminalSignup(baseUrl);\n }\n\n if (method === 'paste') {\n return promptAndValidateApiKey(baseUrl);\n }\n\n log.warn('No API key — you can add one later in .env');\n return null;\n}\n","import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';\n\nexport function detectPackageManager(dir: string): PackageManager {\n if (existsSync(join(dir, 'bun.lockb')) || existsSync(join(dir, 'bun.lock'))) return 'bun';\n if (existsSync(join(dir, 'pnpm-lock.yaml'))) return 'pnpm';\n if (existsSync(join(dir, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n\nexport function detectFromUserAgent(): PackageManager {\n const ua = process.env.npm_config_user_agent ?? '';\n if (ua.startsWith('bun')) return 'bun';\n if (ua.startsWith('pnpm')) return 'pnpm';\n if (ua.startsWith('yarn')) return 'yarn';\n return 'npm';\n}\n\nexport function installCommand(pm: PackageManager): string {\n return pm === 'yarn' ? 'yarn' : `${pm} install`;\n}\n\nexport function runCommand(pm: PackageManager, script: string): string {\n if (pm === 'npm') return `npm run ${script}`;\n return `${pm} ${script}`;\n}\n","export interface Template {\n id: string;\n name: string;\n description: string;\n repo: string;\n framework: string;\n devCommand: string;\n devPort: number;\n recommended?: boolean;\n}\n\nexport const templates: Template[] = [\n {\n id: 'nextjs',\n name: 'Next.js + Recursiv',\n description: 'Full-stack Next.js app with feeds, chat, and agents',\n repo: 'recursivlabs/template-nextjs',\n framework: 'nextjs',\n devCommand: 'next dev',\n devPort: 3000,\n recommended: true,\n },\n {\n id: 'node',\n name: 'Node.js + Express',\n description: 'Express API server with Recursiv SDK',\n repo: 'recursivlabs/template-node',\n framework: 'express',\n devCommand: 'node --watch src/index.js',\n devPort: 4000,\n },\n {\n id: 'vite',\n name: 'Vite + React',\n description: 'React SPA with social feed components',\n repo: 'recursivlabs/template-vite',\n framework: 'vite',\n devCommand: 'vite',\n devPort: 5173,\n },\n];\n\nexport function getTemplate(id: string): Template | undefined {\n return templates.find((t) => t.id === id);\n}\n\nexport function getDefaultTemplate(): Template {\n return templates.find((t) => t.recommended) ?? templates[0]!;\n}\n"],"mappings":"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","names":["existsSync","readFile","writeFile","prompts","pc","ora","readFile","writeFile","join","pc","pc","join","prompts","existsSync","pc","writeFile","readFile","ora"]}
|
package/dist/bin/recursiv.js
CHANGED
|
@@ -379,15 +379,31 @@ var init_auth_flow = __esm({
|
|
|
379
379
|
DEFAULT_SCOPES = [
|
|
380
380
|
"posts:read",
|
|
381
381
|
"posts:write",
|
|
382
|
+
"users:read",
|
|
383
|
+
"users:write",
|
|
384
|
+
"communities:read",
|
|
385
|
+
"communities:write",
|
|
382
386
|
"chat:read",
|
|
383
387
|
"chat:write",
|
|
384
|
-
"agents:read",
|
|
385
|
-
"agents:write",
|
|
386
388
|
"projects:read",
|
|
387
389
|
"projects:write",
|
|
388
|
-
"
|
|
389
|
-
"
|
|
390
|
-
"
|
|
390
|
+
"agents:read",
|
|
391
|
+
"agents:write",
|
|
392
|
+
"organizations:read",
|
|
393
|
+
"organizations:write",
|
|
394
|
+
"memory:read",
|
|
395
|
+
"memory:write",
|
|
396
|
+
"notifications:read",
|
|
397
|
+
"notifications:write",
|
|
398
|
+
"settings:read",
|
|
399
|
+
"settings:write",
|
|
400
|
+
"tags:read",
|
|
401
|
+
"tags:write",
|
|
402
|
+
"uploads:write",
|
|
403
|
+
"commands:read",
|
|
404
|
+
"commands:write",
|
|
405
|
+
"billing:read",
|
|
406
|
+
"billing:write"
|
|
391
407
|
];
|
|
392
408
|
}
|
|
393
409
|
});
|
|
@@ -556,7 +572,9 @@ async function installCodex(apiKey) {
|
|
|
556
572
|
'args = ["-y", "@recursiv/mcp"]',
|
|
557
573
|
"",
|
|
558
574
|
"[mcp_servers.recursiv.env]",
|
|
559
|
-
`RECURSIV_API_KEY = "${apiKey}"
|
|
575
|
+
`RECURSIV_API_KEY = "${apiKey}"`,
|
|
576
|
+
// Opt into the full tool surface — see mcpServerEntry() for context.
|
|
577
|
+
`RECURSIV_API_KEY_SCOPES = "*"`
|
|
560
578
|
].join("\n");
|
|
561
579
|
const final = existing.trimEnd() + "\n" + tomlBlock + "\n";
|
|
562
580
|
await writeFile6(configPath2, final, "utf-8");
|
|
@@ -577,7 +595,9 @@ async function installOpenCode(apiKey, global) {
|
|
|
577
595
|
type: "local",
|
|
578
596
|
command: ["npx", "-y", "@recursiv/mcp"],
|
|
579
597
|
enabled: true,
|
|
598
|
+
// Opt into the full tool surface — see mcpServerEntry() for context.
|
|
580
599
|
environment: {
|
|
600
|
+
RECURSIV_API_KEY_SCOPES: "*",
|
|
581
601
|
RECURSIV_API_KEY: apiKey
|
|
582
602
|
}
|
|
583
603
|
};
|
|
@@ -660,7 +680,14 @@ function mcpServerEntry(apiKey) {
|
|
|
660
680
|
command: "npx",
|
|
661
681
|
args: ["-y", "@recursiv/mcp"],
|
|
662
682
|
env: {
|
|
663
|
-
RECURSIV_API_KEY: apiKey
|
|
683
|
+
RECURSIV_API_KEY: apiKey,
|
|
684
|
+
// The MCP server defaults to read-only tool registration when
|
|
685
|
+
// RECURSIV_API_KEY_SCOPES is absent (a safety default for ambient
|
|
686
|
+
// keys with unknown scope). The CLI mints a key with the full
|
|
687
|
+
// scope set on purpose — explicitly opt in so the user gets the
|
|
688
|
+
// tools they expect (create_project, provision_app, deploy_project,
|
|
689
|
+
// etc.). The wildcard says "all scopes the key actually has."
|
|
690
|
+
RECURSIV_API_KEY_SCOPES: "*"
|
|
664
691
|
}
|
|
665
692
|
};
|
|
666
693
|
}
|
|
@@ -709,6 +736,7 @@ __export(quickstart_exports, {
|
|
|
709
736
|
import { execFile } from "child_process";
|
|
710
737
|
import { promisify } from "util";
|
|
711
738
|
import { platform as platform2 } from "os";
|
|
739
|
+
import prompts3 from "prompts";
|
|
712
740
|
import pc13 from "picocolors";
|
|
713
741
|
async function checkGitHubCli() {
|
|
714
742
|
try {
|
|
@@ -744,9 +772,28 @@ async function fetchUsername(apiKey, baseUrl) {
|
|
|
744
772
|
return null;
|
|
745
773
|
}
|
|
746
774
|
}
|
|
775
|
+
async function pickClient(preferred) {
|
|
776
|
+
if (preferred) {
|
|
777
|
+
const match2 = CLIENT_CHOICES.find((c) => c.target === preferred);
|
|
778
|
+
if (match2) return match2;
|
|
779
|
+
}
|
|
780
|
+
const { target } = await prompts3(
|
|
781
|
+
{
|
|
782
|
+
type: "select",
|
|
783
|
+
name: "target",
|
|
784
|
+
message: "Which AI client are you pasting the build prompt into?",
|
|
785
|
+
choices: CLIENT_CHOICES.map((c) => ({ title: c.label, value: c.target })),
|
|
786
|
+
initial: 0
|
|
787
|
+
},
|
|
788
|
+
{ onCancel: () => process.exit(1) }
|
|
789
|
+
);
|
|
790
|
+
const match = CLIENT_CHOICES.find((c) => c.target === target);
|
|
791
|
+
if (!match) throw new Error(`Unexpected client selection: ${target}`);
|
|
792
|
+
return match;
|
|
793
|
+
}
|
|
747
794
|
async function quickstartCommand(opts = {}) {
|
|
748
795
|
console.log();
|
|
749
|
-
console.log(pc13.bold(" Setting up Recursiv on this machine") + pc13.dim(" \u2014
|
|
796
|
+
console.log(pc13.bold(" Setting up Recursiv on this machine") + pc13.dim(" \u2014 GitHub CLI + Recursiv account + MCP config. ~3 minutes."));
|
|
750
797
|
console.log();
|
|
751
798
|
log.step(1, 3, "Checking GitHub CLI");
|
|
752
799
|
const ghCheck = opts.ghCheck ?? checkGitHubCli;
|
|
@@ -790,22 +837,24 @@ async function quickstartCommand(opts = {}) {
|
|
|
790
837
|
await saveCredentials({ recursivApiKey: apiKey });
|
|
791
838
|
log.success("Credentials saved to ~/.recursiv/credentials");
|
|
792
839
|
}
|
|
793
|
-
log.step(3, 3, "Configuring Recursiv MCP
|
|
794
|
-
await
|
|
840
|
+
log.step(3, 3, "Configuring Recursiv MCP");
|
|
841
|
+
const client = await pickClient(opts.target);
|
|
842
|
+
await mcpInstallCommand({ target: client.target, apiKey });
|
|
843
|
+
const isWindows = platform2() === "win32";
|
|
844
|
+
const quitHint = isWindows ? `fully quit ${client.productName} (exit from the system tray)` : `fully quit ${client.productName} (Cmd-Q on macOS)`;
|
|
795
845
|
console.log();
|
|
796
846
|
console.log(pc13.green(pc13.bold(" Done.")) + pc13.dim(" Next steps:"));
|
|
797
847
|
console.log();
|
|
798
|
-
const quitHint = platform2() === "win32" ? "fully quit Claude Code (exit from the system tray)" : "fully quit Claude Code (Cmd-Q on macOS)";
|
|
799
848
|
console.log(" 1. " + quitHint);
|
|
800
|
-
console.log(
|
|
849
|
+
console.log(` 2. Reopen ${client.productName} in this folder`);
|
|
801
850
|
console.log(" 3. Paste the prompt from " + pc13.underline(TUTORIAL_URL));
|
|
802
|
-
console.log("
|
|
851
|
+
console.log(" as your first chat message");
|
|
803
852
|
console.log();
|
|
804
|
-
console.log(pc13.dim(" Tip: when
|
|
853
|
+
console.log(pc13.dim(" Tip: when the client asks to approve the first Recursiv tool call,"));
|
|
805
854
|
console.log(pc13.dim(' choose "Always allow recursiv" so you are not prompted again.'));
|
|
806
855
|
console.log();
|
|
807
856
|
}
|
|
808
|
-
var execFileAsync, TUTORIAL_URL;
|
|
857
|
+
var execFileAsync, TUTORIAL_URL, CLIENT_CHOICES;
|
|
809
858
|
var init_quickstart = __esm({
|
|
810
859
|
"src/commands/quickstart.ts"() {
|
|
811
860
|
"use strict";
|
|
@@ -816,6 +865,12 @@ var init_quickstart = __esm({
|
|
|
816
865
|
init_mcp_install();
|
|
817
866
|
execFileAsync = promisify(execFile);
|
|
818
867
|
TUTORIAL_URL = "https://docs.recursiv.io/guides/tutorials/build-your-first-app";
|
|
868
|
+
CLIENT_CHOICES = [
|
|
869
|
+
{ target: "claude-code", label: "Claude Code (terminal CLI)", productName: "Claude Code" },
|
|
870
|
+
{ target: "claude-desktop", label: "Claude Desktop (chat app)", productName: "Claude Desktop" },
|
|
871
|
+
{ target: "codex", label: "Codex", productName: "Codex" },
|
|
872
|
+
{ target: "opencode", label: "OpenCode", productName: "OpenCode" }
|
|
873
|
+
];
|
|
819
874
|
}
|
|
820
875
|
});
|
|
821
876
|
|
|
@@ -4217,10 +4272,15 @@ program.command("studio").description("Legacy alias for brain").option("--no-ani
|
|
|
4217
4272
|
process.exit(1);
|
|
4218
4273
|
}
|
|
4219
4274
|
});
|
|
4220
|
-
program.command("quickstart").description("Set up
|
|
4275
|
+
program.command("quickstart").description("Set up Recursiv on this machine (GitHub CLI + account + MCP for an AI client). ~3 min").option(
|
|
4276
|
+
"--target <client>",
|
|
4277
|
+
"Skip the client prompt and install MCP for this client (claude-code, claude-desktop, codex, opencode)"
|
|
4278
|
+
).action(async (opts) => {
|
|
4221
4279
|
try {
|
|
4222
4280
|
const { quickstartCommand: quickstartCommand2 } = await Promise.resolve().then(() => (init_quickstart(), quickstart_exports));
|
|
4223
|
-
|
|
4281
|
+
const allowed = ["claude-code", "claude-desktop", "codex", "opencode"];
|
|
4282
|
+
const target = opts.target && allowed.includes(opts.target) ? opts.target : void 0;
|
|
4283
|
+
await quickstartCommand2({ target });
|
|
4224
4284
|
} catch (err) {
|
|
4225
4285
|
printCliError(err);
|
|
4226
4286
|
process.exit(1);
|
|
@@ -4251,7 +4311,7 @@ async function launchChatAgent(opts) {
|
|
|
4251
4311
|
const { resolveRecursivKey: resolveRecursivKey2, resolveAnthropicKey: resolveAnthropicKey2, saveCredentials: saveCredentials2 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
|
|
4252
4312
|
const { getOrCreateApiKey: getOrCreateApiKey2 } = await Promise.resolve().then(() => (init_auth_flow(), auth_flow_exports));
|
|
4253
4313
|
const pc16 = (await import("picocolors")).default;
|
|
4254
|
-
const
|
|
4314
|
+
const prompts4 = (await import("prompts")).default;
|
|
4255
4315
|
const cwd = process.cwd();
|
|
4256
4316
|
const config = await readConfig2(cwd);
|
|
4257
4317
|
const baseUrl = config?.api.baseUrl ?? "https://api.recursiv.io/api/v1";
|