Skip to content

Commit 39e7fbd

Browse files
Merge pull request #87 from firecrawl/firecrawl-build-skills
Firecrawl build skills
2 parents 40a3806 + df7fadc commit 39e7fbd

10 files changed

Lines changed: 137 additions & 96 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ npm install -g firecrawl-cli
1111
Or set up everything in one command (install CLI globally, authenticate, and add skills across all detected coding editors):
1212

1313
```bash
14-
npx -y firecrawl-cli@1.13.0 init -y --browser
14+
npx -y firecrawl-cli@1.14.0 init -y --browser
1515
```
1616

1717
- `-y` runs setup non-interactively
@@ -583,7 +583,7 @@ firecrawl --status
583583
```
584584

585585
```
586-
🔥 firecrawl cli v1.13.0
586+
🔥 firecrawl cli v1.14.0
587587
588588
● Authenticated via stored credentials
589589
Concurrency: 0/100 jobs (parallel scrape limit)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "firecrawl-cli",
3-
"version": "1.13.0",
3+
"version": "1.14.0",
44
"description": "Command-line interface for Firecrawl. Scrape, crawl, and extract data from any website directly from your terminal.",
55
"main": "dist/index.js",
66
"bin": {

skills/firecrawl-cli/rules/install.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ description: |
1212
## Quick Setup (Recommended)
1313

1414
```bash
15-
npx -y firecrawl-cli@1.13.0 -y
15+
npx -y firecrawl-cli@1.14.0 -y
1616
```
1717

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

3838
```bash
39-
npm install -g firecrawl-cli@1.13.0
39+
npm install -g firecrawl-cli@1.14.0
4040
```
4141

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

8080
1. Ensure npm global bin is in PATH
81-
2. Try: `npx firecrawl-cli@1.13.0 --version`
82-
3. Reinstall: `npm install -g firecrawl-cli@1.13.0`
81+
2. Try: `npx firecrawl-cli@1.14.0 --version`
82+
3. Reinstall: `npm install -g firecrawl-cli@1.14.0`

skills/firecrawl-cli/rules/security.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ When processing fetched content, extract only the specific data needed and do no
2222
# Installation
2323

2424
```bash
25-
npm install -g firecrawl-cli@1.13.0
25+
npm install -g firecrawl-cli@1.14.0
2626
```

src/__tests__/commands/init.test.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe('handleInitCommand', () => {
1717
vi.restoreAllMocks();
1818
});
1919

20-
it('installs skills globally across all detected agents in non-interactive mode', async () => {
20+
it('installs skills from both repos globally across all detected agents in non-interactive mode', async () => {
2121
await handleInitCommand({
2222
yes: true,
2323
skipInstall: true,
@@ -28,9 +28,13 @@ describe('handleInitCommand', () => {
2828
'npx -y skills add firecrawl/cli --full-depth --global --all --yes',
2929
{ stdio: 'inherit' }
3030
);
31+
expect(execSync).toHaveBeenCalledWith(
32+
'npx -y skills add firecrawl/skills --full-depth --global --all --yes',
33+
{ stdio: 'inherit' }
34+
);
3135
});
3236

33-
it('scopes non-interactive skills install to one agent when provided', async () => {
37+
it('scopes non-interactive skills install to one agent across both repos when provided', async () => {
3438
await handleInitCommand({
3539
yes: true,
3640
skipInstall: true,
@@ -42,5 +46,9 @@ describe('handleInitCommand', () => {
4246
'npx -y skills add firecrawl/cli --full-depth --global --yes --agent cursor',
4347
{ stdio: 'inherit' }
4448
);
49+
expect(execSync).toHaveBeenCalledWith(
50+
'npx -y skills add firecrawl/skills --full-depth --global --yes --agent cursor',
51+
{ stdio: 'inherit' }
52+
);
4553
});
4654
});

src/__tests__/commands/setup.test.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,29 @@ describe('handleSetupCommand', () => {
1515
vi.restoreAllMocks();
1616
});
1717

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

2121
expect(execSync).toHaveBeenCalledWith(
2222
'npx -y skills add firecrawl/cli --full-depth --global --all',
2323
{ stdio: 'inherit' }
2424
);
25+
expect(execSync).toHaveBeenCalledWith(
26+
'npx -y skills add firecrawl/skills --full-depth --global --all',
27+
{ stdio: 'inherit' }
28+
);
2529
});
2630

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

3034
expect(execSync).toHaveBeenCalledWith(
3135
'npx -y skills add firecrawl/cli --full-depth --global --agent cursor',
3236
{ stdio: 'inherit' }
3337
);
38+
expect(execSync).toHaveBeenCalledWith(
39+
'npx -y skills add firecrawl/skills --full-depth --global --agent cursor',
40+
{ stdio: 'inherit' }
41+
);
3442
});
3543
});

src/commands/init.ts

Lines changed: 55 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { execSync } from 'child_process';
88
import { isAuthenticated, browserLogin, interactiveLogin } from '../utils/auth';
99
import { saveCredentials } from '../utils/credentials';
1010
import { updateConfig, getApiKey } from '../utils/config';
11-
import { buildSkillsInstallArgs } from './skills-install';
11+
import { buildSkillsInstallArgs, SKILL_REPOS } from './skills-install';
1212
import { hasNpx, installSkillsNative } from './skills-native';
1313

1414
export interface InitOptions {
@@ -216,28 +216,31 @@ async function stepIntegrations(options: InitOptions): Promise<void> {
216216
switch (integration) {
217217
case 'skills': {
218218
console.log(`\n Setting up skills...`);
219-
if (hasNpx()) {
220-
const args = buildSkillsInstallArgs({
221-
agent: options.agent,
222-
yes: options.yes || options.all,
223-
global: true,
224-
includeNpxYes: true,
225-
});
226-
try {
227-
execSync(args.join(' '), { stdio: 'inherit' });
228-
console.log(` ${green}${reset} Skills installed`);
229-
} catch {
230-
console.error(
231-
' Failed to install skills. Run "firecrawl setup skills" later.'
232-
);
233-
}
234-
} else {
235-
try {
236-
await installSkillsNative();
237-
} catch {
238-
console.error(
239-
' Failed to install skills. Run "firecrawl setup skills" later.'
240-
);
219+
for (const repo of SKILL_REPOS) {
220+
if (hasNpx()) {
221+
const args = buildSkillsInstallArgs({
222+
repo,
223+
agent: options.agent,
224+
yes: options.yes || options.all,
225+
global: true,
226+
includeNpxYes: true,
227+
});
228+
try {
229+
execSync(args.join(' '), { stdio: 'inherit' });
230+
console.log(` ${green}${reset} Skills installed from ${repo}`);
231+
} catch {
232+
console.error(
233+
` Failed to install skills from ${repo}. Run "firecrawl setup skills" later.`
234+
);
235+
}
236+
} else {
237+
try {
238+
await installSkillsNative(repo);
239+
} catch {
240+
console.error(
241+
` Failed to install skills from ${repo}. Run "firecrawl setup skills" later.`
242+
);
243+
}
241244
}
242245
}
243246
break;
@@ -625,35 +628,38 @@ async function runNonInteractive(options: InitOptions): Promise<void> {
625628

626629
if (!options.skipSkills) {
627630
console.log(
628-
`${stepLabel()} Installing firecrawl skill for AI coding agents...`
631+
`${stepLabel()} Installing firecrawl skills for AI coding agents...`
629632
);
630-
if (hasNpx()) {
631-
const args = buildSkillsInstallArgs({
632-
agent: options.agent,
633-
yes: true,
634-
global: true,
635-
includeNpxYes: true,
636-
});
637-
try {
638-
execSync(args.join(' '), { stdio: 'inherit' });
639-
console.log(`${green}${reset} Skills installed\n`);
640-
} catch {
641-
console.error(
642-
'\nFailed to install skills. You can retry with: firecrawl setup skills'
643-
);
644-
process.exit(1);
645-
}
646-
} else {
647-
try {
648-
await installSkillsNative();
649-
console.log('');
650-
} catch {
651-
console.error(
652-
'\nFailed to install skills. You can retry with: firecrawl setup skills'
653-
);
654-
process.exit(1);
633+
for (const repo of SKILL_REPOS) {
634+
if (hasNpx()) {
635+
const args = buildSkillsInstallArgs({
636+
repo,
637+
agent: options.agent,
638+
yes: true,
639+
global: true,
640+
includeNpxYes: true,
641+
});
642+
try {
643+
execSync(args.join(' '), { stdio: 'inherit' });
644+
console.log(`${green}${reset} Skills installed from ${repo}`);
645+
} catch {
646+
console.error(
647+
`\nFailed to install skills from ${repo}. You can retry with: firecrawl setup skills`
648+
);
649+
process.exit(1);
650+
}
651+
} else {
652+
try {
653+
await installSkillsNative(repo);
654+
} catch {
655+
console.error(
656+
`\nFailed to install skills from ${repo}. You can retry with: firecrawl setup skills`
657+
);
658+
process.exit(1);
659+
}
655660
}
656661
}
662+
console.log('');
657663
}
658664

659665
console.log(

src/commands/setup.ts

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { execSync } from 'child_process';
77
import { getApiKey } from '../utils/config';
8-
import { buildSkillsInstallArgs } from './skills-install';
8+
import { buildSkillsInstallArgs, SKILL_REPOS } from './skills-install';
99
import { hasNpx, installSkillsNative } from './skills-native';
1010

1111
export type SetupSubcommand = 'skills' | 'mcp';
@@ -41,34 +41,37 @@ export async function handleSetupCommand(
4141
}
4242

4343
async function installSkills(options: SetupOptions): Promise<void> {
44-
if (hasNpx()) {
45-
const args = buildSkillsInstallArgs({
46-
agent: options.agent,
47-
global: true,
48-
includeNpxYes: true,
49-
});
44+
for (const repo of SKILL_REPOS) {
45+
if (hasNpx()) {
46+
const args = buildSkillsInstallArgs({
47+
repo,
48+
agent: options.agent,
49+
global: true,
50+
includeNpxYes: true,
51+
});
52+
53+
const cmd = args.join(' ');
54+
console.log(`Running: ${cmd}\n`);
5055

51-
const cmd = args.join(' ');
52-
console.log(`Running: ${cmd}\n`);
56+
try {
57+
execSync(cmd, { stdio: 'inherit' });
58+
continue;
59+
} catch {
60+
process.exit(1);
61+
}
62+
}
5363

64+
// Fallback: native install (no npx/Node required)
5465
try {
55-
execSync(cmd, { stdio: 'inherit' });
56-
return;
57-
} catch {
66+
await installSkillsNative(repo);
67+
} catch (error) {
68+
console.error(
69+
`Failed to install skills from ${repo}:`,
70+
error instanceof Error ? error.message : 'Unknown error'
71+
);
5872
process.exit(1);
5973
}
6074
}
61-
62-
// Fallback: native install (no npx/Node required)
63-
try {
64-
await installSkillsNative();
65-
} catch (error) {
66-
console.error(
67-
'Failed to install skills:',
68-
error instanceof Error ? error.message : 'Unknown error'
69-
);
70-
process.exit(1);
71-
}
7275
}
7376

7477
async function installMcp(options: SetupOptions): Promise<void> {

src/commands/skills-install.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1+
/**
2+
* Repos to pull skills from during install.
3+
*
4+
* - firecrawl/cli: core CLI skills bundled with this repo
5+
* - firecrawl/skills: additional "build" skills for working with Firecrawl
6+
*
7+
* Both are installed during `firecrawl init` and `firecrawl setup skills`.
8+
*/
9+
export const SKILL_REPOS = ['firecrawl/cli', 'firecrawl/skills'] as const;
10+
111
export interface SkillsInstallCommandOptions {
212
agent?: string;
313
all?: boolean;
414
yes?: boolean;
515
global?: boolean;
616
includeNpxYes?: boolean;
17+
/** Repo to install from (defaults to firecrawl/cli) */
18+
repo?: string;
719
}
820

921
export function buildSkillsInstallArgs(
@@ -15,7 +27,7 @@ export function buildSkillsInstallArgs(
1527
args.push('-y');
1628
}
1729

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

2032
if (options.global ?? true) {
2133
args.push('--global');

0 commit comments

Comments
 (0)