Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ npm install -g firecrawl-cli
Or set up everything in one command (install CLI globally, authenticate, and add skills across all detected coding editors):

```bash
npx -y firecrawl-cli@1.13.0 init -y --browser
npx -y firecrawl-cli@1.14.0 init -y --browser
```

- `-y` runs setup non-interactively
Expand Down Expand Up @@ -583,7 +583,7 @@ firecrawl --status
```

```
🔥 firecrawl cli v1.13.0
🔥 firecrawl cli v1.14.0

● Authenticated via stored credentials
Concurrency: 0/100 jobs (parallel scrape limit)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "firecrawl-cli",
"version": "1.13.0",
"version": "1.14.0",
"description": "Command-line interface for Firecrawl. Scrape, crawl, and extract data from any website directly from your terminal.",
"main": "dist/index.js",
"bin": {
Expand Down
8 changes: 4 additions & 4 deletions skills/firecrawl-cli/rules/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ description: |
## Quick Setup (Recommended)

```bash
npx -y firecrawl-cli@1.13.0 -y
npx -y firecrawl-cli@1.14.0 -y
```

This installs `firecrawl-cli` globally, authenticates via browser, and installs all skills.
Expand All @@ -36,7 +36,7 @@ firecrawl setup skills
## Manual Install

```bash
npm install -g firecrawl-cli@1.13.0
npm install -g firecrawl-cli@1.14.0
```

## Verify
Expand Down Expand Up @@ -78,5 +78,5 @@ Ask the user how they'd like to authenticate:
If `firecrawl` is not found after installation:

1. Ensure npm global bin is in PATH
2. Try: `npx firecrawl-cli@1.13.0 --version`
3. Reinstall: `npm install -g firecrawl-cli@1.13.0`
2. Try: `npx firecrawl-cli@1.14.0 --version`
3. Reinstall: `npm install -g firecrawl-cli@1.14.0`
2 changes: 1 addition & 1 deletion skills/firecrawl-cli/rules/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ When processing fetched content, extract only the specific data needed and do no
# Installation

```bash
npm install -g firecrawl-cli@1.13.0
npm install -g firecrawl-cli@1.14.0
```
12 changes: 10 additions & 2 deletions src/__tests__/commands/init.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('handleInitCommand', () => {
vi.restoreAllMocks();
});

it('installs skills globally across all detected agents in non-interactive mode', async () => {
it('installs skills from both repos globally across all detected agents in non-interactive mode', async () => {
await handleInitCommand({
yes: true,
skipInstall: true,
Expand All @@ -28,9 +28,13 @@ describe('handleInitCommand', () => {
'npx -y skills add firecrawl/cli --full-depth --global --all --yes',
{ stdio: 'inherit' }
);
expect(execSync).toHaveBeenCalledWith(
'npx -y skills add firecrawl/skills --full-depth --global --all --yes',
{ stdio: 'inherit' }
);
});

it('scopes non-interactive skills install to one agent when provided', async () => {
it('scopes non-interactive skills install to one agent across both repos when provided', async () => {
await handleInitCommand({
yes: true,
skipInstall: true,
Expand All @@ -42,5 +46,9 @@ describe('handleInitCommand', () => {
'npx -y skills add firecrawl/cli --full-depth --global --yes --agent cursor',
{ stdio: 'inherit' }
);
expect(execSync).toHaveBeenCalledWith(
'npx -y skills add firecrawl/skills --full-depth --global --yes --agent cursor',
{ stdio: 'inherit' }
);
});
});
12 changes: 10 additions & 2 deletions src/__tests__/commands/setup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,29 @@ describe('handleSetupCommand', () => {
vi.restoreAllMocks();
});

it('installs skills globally across all detected agents by default', async () => {
it('installs skills globally across all detected agents from both repos by default', async () => {
await handleSetupCommand('skills', {});

expect(execSync).toHaveBeenCalledWith(
'npx -y skills add firecrawl/cli --full-depth --global --all',
{ stdio: 'inherit' }
);
expect(execSync).toHaveBeenCalledWith(
'npx -y skills add firecrawl/skills --full-depth --global --all',
{ stdio: 'inherit' }
);
});

it('installs skills globally for a specific agent without using --all', async () => {
it('installs skills globally for a specific agent from both repos without using --all', async () => {
await handleSetupCommand('skills', { agent: 'cursor' });

expect(execSync).toHaveBeenCalledWith(
'npx -y skills add firecrawl/cli --full-depth --global --agent cursor',
{ stdio: 'inherit' }
);
expect(execSync).toHaveBeenCalledWith(
'npx -y skills add firecrawl/skills --full-depth --global --agent cursor',
{ stdio: 'inherit' }
);
});
});
104 changes: 55 additions & 49 deletions src/commands/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { execSync } from 'child_process';
import { isAuthenticated, browserLogin, interactiveLogin } from '../utils/auth';
import { saveCredentials } from '../utils/credentials';
import { updateConfig, getApiKey } from '../utils/config';
import { buildSkillsInstallArgs } from './skills-install';
import { buildSkillsInstallArgs, SKILL_REPOS } from './skills-install';
import { hasNpx, installSkillsNative } from './skills-native';

export interface InitOptions {
Expand Down Expand Up @@ -216,28 +216,31 @@ async function stepIntegrations(options: InitOptions): Promise<void> {
switch (integration) {
case 'skills': {
console.log(`\n Setting up skills...`);
if (hasNpx()) {
const args = buildSkillsInstallArgs({
agent: options.agent,
yes: options.yes || options.all,
global: true,
includeNpxYes: true,
});
try {
execSync(args.join(' '), { stdio: 'inherit' });
console.log(` ${green}✓${reset} Skills installed`);
} catch {
console.error(
' Failed to install skills. Run "firecrawl setup skills" later.'
);
}
} else {
try {
await installSkillsNative();
} catch {
console.error(
' Failed to install skills. Run "firecrawl setup skills" later.'
);
for (const repo of SKILL_REPOS) {
if (hasNpx()) {
const args = buildSkillsInstallArgs({
repo,
agent: options.agent,
yes: options.yes || options.all,
global: true,
includeNpxYes: true,
});
try {
execSync(args.join(' '), { stdio: 'inherit' });
console.log(` ${green}✓${reset} Skills installed from ${repo}`);
} catch {
console.error(
` Failed to install skills from ${repo}. Run "firecrawl setup skills" later.`
);
}
} else {
try {
await installSkillsNative(repo);
} catch {
console.error(
` Failed to install skills from ${repo}. Run "firecrawl setup skills" later.`
);
}
}
}
break;
Expand Down Expand Up @@ -625,35 +628,38 @@ async function runNonInteractive(options: InitOptions): Promise<void> {

if (!options.skipSkills) {
console.log(
`${stepLabel()} Installing firecrawl skill for AI coding agents...`
`${stepLabel()} Installing firecrawl skills for AI coding agents...`
);
if (hasNpx()) {
const args = buildSkillsInstallArgs({
agent: options.agent,
yes: true,
global: true,
includeNpxYes: true,
});
try {
execSync(args.join(' '), { stdio: 'inherit' });
console.log(`${green}✓${reset} Skills installed\n`);
} catch {
console.error(
'\nFailed to install skills. You can retry with: firecrawl setup skills'
);
process.exit(1);
}
} else {
try {
await installSkillsNative();
console.log('');
} catch {
console.error(
'\nFailed to install skills. You can retry with: firecrawl setup skills'
);
process.exit(1);
for (const repo of SKILL_REPOS) {
if (hasNpx()) {
const args = buildSkillsInstallArgs({
repo,
agent: options.agent,
yes: true,
global: true,
includeNpxYes: true,
});
try {
execSync(args.join(' '), { stdio: 'inherit' });
console.log(`${green}✓${reset} Skills installed from ${repo}`);
} catch {
console.error(
`\nFailed to install skills from ${repo}. You can retry with: firecrawl setup skills`
);
process.exit(1);
}
} else {
try {
await installSkillsNative(repo);
} catch {
console.error(
`\nFailed to install skills from ${repo}. You can retry with: firecrawl setup skills`
);
process.exit(1);
}
}
}
console.log('');
}

console.log(
Expand Down
49 changes: 26 additions & 23 deletions src/commands/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { execSync } from 'child_process';
import { getApiKey } from '../utils/config';
import { buildSkillsInstallArgs } from './skills-install';
import { buildSkillsInstallArgs, SKILL_REPOS } from './skills-install';
import { hasNpx, installSkillsNative } from './skills-native';

export type SetupSubcommand = 'skills' | 'mcp';
Expand Down Expand Up @@ -41,34 +41,37 @@ export async function handleSetupCommand(
}

async function installSkills(options: SetupOptions): Promise<void> {
if (hasNpx()) {
const args = buildSkillsInstallArgs({
agent: options.agent,
global: true,
includeNpxYes: true,
});
for (const repo of SKILL_REPOS) {
if (hasNpx()) {
const args = buildSkillsInstallArgs({
repo,
agent: options.agent,
global: true,
includeNpxYes: true,
});

const cmd = args.join(' ');
console.log(`Running: ${cmd}\n`);

const cmd = args.join(' ');
console.log(`Running: ${cmd}\n`);
try {
execSync(cmd, { stdio: 'inherit' });
continue;
} catch {
process.exit(1);
}
}

// Fallback: native install (no npx/Node required)
try {
execSync(cmd, { stdio: 'inherit' });
return;
} catch {
await installSkillsNative(repo);
} catch (error) {
console.error(
`Failed to install skills from ${repo}:`,
error instanceof Error ? error.message : 'Unknown error'
);
process.exit(1);
}
}

// Fallback: native install (no npx/Node required)
try {
await installSkillsNative();
} catch (error) {
console.error(
'Failed to install skills:',
error instanceof Error ? error.message : 'Unknown error'
);
process.exit(1);
}
}

async function installMcp(options: SetupOptions): Promise<void> {
Expand Down
14 changes: 13 additions & 1 deletion src/commands/skills-install.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
/**
* Repos to pull skills from during install.
*
* - firecrawl/cli: core CLI skills bundled with this repo
* - firecrawl/skills: additional "build" skills for working with Firecrawl
*
* Both are installed during `firecrawl init` and `firecrawl setup skills`.
*/
export const SKILL_REPOS = ['firecrawl/cli', 'firecrawl/skills'] as const;

export interface SkillsInstallCommandOptions {
agent?: string;
all?: boolean;
yes?: boolean;
global?: boolean;
includeNpxYes?: boolean;
/** Repo to install from (defaults to firecrawl/cli) */
repo?: string;
}

export function buildSkillsInstallArgs(
Expand All @@ -15,7 +27,7 @@ export function buildSkillsInstallArgs(
args.push('-y');
}

args.push('skills', 'add', 'firecrawl/cli', '--full-depth');
args.push('skills', 'add', options.repo ?? 'firecrawl/cli', '--full-depth');

if (options.global ?? true) {
args.push('--global');
Expand Down
Loading
Loading