diff --git a/README.md b/README.md index 84f6f71..ae297fe 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,23 @@ Command-line interface for Firecrawl. Scrape, crawl, and extract data from any w npm install -g firecrawl-cli ``` -If you are using in any AI agent like Claude Code, you can install the skill with: +If you are using an AI coding agent like Claude Code, you can install the skill with: + +```bash +firecrawl init skills +``` + +To install the Firecrawl MCP server into your editors (Cursor, Claude Code, VS Code, etc.): + +```bash +firecrawl init mcp +``` + +Or directly via npx: ```bash npx skills add firecrawl/cli +npx add-mcp "npx -y firecrawl-mcp" --name firecrawl ``` ## Quick Start diff --git a/package.json b/package.json index 415f702..3e85afb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "firecrawl-cli", - "version": "1.4.1", + "version": "1.5.0", "description": "Command-line interface for Firecrawl. Scrape, crawl, and extract data from any website directly from your terminal.", "main": "dist/index.js", "bin": { diff --git a/src/commands/init.ts b/src/commands/init.ts new file mode 100644 index 0000000..8d1a4fe --- /dev/null +++ b/src/commands/init.ts @@ -0,0 +1,98 @@ +/** + * Init command implementation + * Installs firecrawl skill files and MCP server into AI coding agents + */ + +import { execSync } from 'child_process'; +import { getApiKey } from '../utils/config'; + +export type InitSubcommand = 'skills' | 'mcp'; + +export interface InitOptions { + global?: boolean; + agent?: string; +} + +/** + * Main init command handler + */ +export async function handleInitCommand( + subcommand: InitSubcommand, + options: InitOptions = {} +): Promise { + switch (subcommand) { + case 'skills': + await installSkills(options); + break; + case 'mcp': + await installMcp(options); + break; + default: + console.error(`Unknown init subcommand: ${subcommand}`); + console.log('\nAvailable subcommands:'); + console.log(' skills Install firecrawl skill into AI coding agents'); + console.log( + ' mcp Install firecrawl MCP server into editors (Cursor, Claude Code, VS Code, etc.)' + ); + process.exit(1); + } +} + +async function installSkills(options: InitOptions): Promise { + const args = ['npx', 'skills', 'add', 'firecrawl/cli']; + + if (options.global) { + args.push('--global'); + } + + if (options.agent) { + args.push('--agent', options.agent); + } + + const cmd = args.join(' '); + console.log(`Running: ${cmd}\n`); + + try { + execSync(cmd, { stdio: 'inherit' }); + } catch { + process.exit(1); + } +} + +async function installMcp(options: InitOptions): Promise { + const apiKey = getApiKey(); + if (!apiKey) { + console.error( + 'No API key found. Please run `firecrawl login` first, or set FIRECRAWL_API_KEY.' + ); + process.exit(1); + } + + const args = [ + 'npx', + 'add-mcp', + `"npx -y firecrawl-mcp"`, + '--name', + 'firecrawl', + ]; + + if (options.global) { + args.push('--global'); + } + + if (options.agent) { + args.push('--agent', options.agent); + } + + const cmd = args.join(' '); + console.log(`Running: ${cmd}\n`); + + try { + execSync(cmd, { + stdio: 'inherit', + env: { ...process.env, FIRECRAWL_API_KEY: apiKey }, + }); + } catch { + process.exit(1); + } +} diff --git a/src/index.ts b/src/index.ts index e92bb70..7169e1d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -25,6 +25,7 @@ import { import { handleVersionCommand } from './commands/version'; import { handleLoginCommand } from './commands/login'; import { handleLogoutCommand } from './commands/logout'; +import { handleInitCommand } from './commands/init'; import { handleStatusCommand } from './commands/status'; import { isUrl, normalizeUrl } from './utils/url'; import { parseScrapeOptions } from './utils/options'; @@ -944,6 +945,16 @@ program await handleLogoutCommand(); }); +program + .command('init') + .description('Initialize firecrawl integrations (skills, mcp)') + .argument('', 'What to initialize: "skills" or "mcp"') + .option('-g, --global', 'Install globally (user-level)') + .option('-a, --agent ', 'Install to a specific agent') + .action(async (subcommand, options) => { + await handleInitCommand(subcommand, options); + }); + program .command('credit-usage') .description('Get team credit usage information')