Skip to content

Commit 6817b00

Browse files
committed
Merge branch 'nsc/v2'
2 parents 16dad07 + dc6fbf9 commit 6817b00

3 files changed

Lines changed: 81 additions & 8 deletions

File tree

‎skills/firecrawl-cli/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Always use the `firecrawl` CLI instead of WebFetch and WebSearch or similar tool
1818

1919
## Installation
2020

21-
Install the CLI if not already installed.
21+
Install the CLI if not already installed. Run `firecrawl --version` to check the version first.
2222

2323
```bash
2424
npm install -g firecrawl-cli@beta

‎src/index.ts‎

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,18 @@ function createScrapeCommand(): Command {
7070
const scrapeCmd = new Command('scrape')
7171
.description('Scrape a URL using Firecrawl')
7272
.argument('[url]', 'URL to scrape')
73+
.argument(
74+
'[formats...]',
75+
'Output format(s) as positional args (e.g., markdown screenshot links)'
76+
)
7377
.option(
7478
'-u, --url <url>',
7579
'URL to scrape (alternative to positional argument)'
7680
)
7781
.option('-H, --html', 'Output raw HTML (shortcut for --format html)')
7882
.option(
7983
'-f, --format <formats>',
80-
'Output format(s). Multiple formats can be specified with commas (e.g., "markdown,links,images"). Available: markdown, html, rawHtml, links, images, screenshot, summary, changeTracking, json, attributes, branding. Single format outputs raw content; multiple formats output JSON.',
81-
'markdown'
84+
'Output format(s). Multiple formats can be specified with commas (e.g., "markdown,links,images"). Available: markdown, html, rawHtml, links, images, screenshot, summary, changeTracking, json, attributes, branding. Single format outputs raw content; multiple formats output JSON.'
8285
)
8386
.option('--only-main-content', 'Include only main content', false)
8487
.option(
@@ -100,7 +103,7 @@ function createScrapeCommand(): Command {
100103
'Show request timing and other useful information',
101104
false
102105
)
103-
.action(async (positionalUrl, options) => {
106+
.action(async (positionalUrl, positionalFormats, options) => {
104107
// Use positional URL if provided, otherwise use --url option
105108
const url = positionalUrl || options.url;
106109
if (!url) {
@@ -110,8 +113,21 @@ function createScrapeCommand(): Command {
110113
process.exit(1);
111114
}
112115

113-
// Handle --html shortcut flag
114-
const format = options.html ? 'html' : options.format;
116+
// Merge formats: positional formats take precedence, then --format flag, then default to markdown
117+
let format: string;
118+
if (positionalFormats && positionalFormats.length > 0) {
119+
// Positional formats: join them with commas for parseFormats
120+
format = positionalFormats.join(',');
121+
} else if (options.html) {
122+
// Handle --html shortcut flag
123+
format = 'html';
124+
} else if (options.format) {
125+
// Use --format option
126+
format = options.format;
127+
} else {
128+
// Default to markdown
129+
format = 'markdown';
130+
}
115131

116132
const scrapeOptions = parseScrapeOptions({ ...options, url, format });
117133
await handleScrapeCommand(scrapeOptions);
@@ -547,14 +563,33 @@ async function main() {
547563
// Treat as scrape command with URL - reuse commander's parsing
548564
const url = normalizeUrl(args[0]);
549565

550-
// Modify argv to include scrape command with URL as positional argument
566+
// Collect any positional format arguments (non-flag arguments after the URL)
567+
const remainingArgs = args.slice(1);
568+
const positionalFormats: string[] = [];
569+
const otherArgs: string[] = [];
570+
571+
for (const arg of remainingArgs) {
572+
// If it starts with a dash, it's a flag (and everything after goes to otherArgs)
573+
if (arg.startsWith('-')) {
574+
otherArgs.push(arg);
575+
} else if (otherArgs.length === 0) {
576+
// Only treat as positional format if we haven't hit a flag yet
577+
positionalFormats.push(arg);
578+
} else {
579+
// This is an argument to a flag
580+
otherArgs.push(arg);
581+
}
582+
}
583+
584+
// Modify argv to include scrape command with URL and formats as positional arguments
551585
// This allows commander to parse it normally with all hooks and options
552586
const modifiedArgv = [
553587
process.argv[0],
554588
process.argv[1],
555589
'scrape',
556590
url,
557-
...args.slice(1),
591+
...positionalFormats,
592+
...otherArgs,
558593
];
559594

560595
// Parse using the main program (which includes hooks and global options)

‎src/utils/output.ts‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,33 @@ const RAW_TEXT_FORMATS: ScrapeFormat[] = [
1818
'summary',
1919
];
2020

21+
/**
22+
* Format screenshot output nicely
23+
*/
24+
function formatScreenshotOutput(data: any): string {
25+
const lines: string[] = [];
26+
27+
// Screenshot URL
28+
if (data.screenshot) {
29+
lines.push(`Screenshot: ${data.screenshot}`);
30+
}
31+
32+
// Page info from metadata
33+
if (data.metadata) {
34+
if (data.metadata.title) {
35+
lines.push(`Title: ${data.metadata.title}`);
36+
}
37+
if (data.metadata.sourceURL || data.metadata.url) {
38+
lines.push(`URL: ${data.metadata.sourceURL || data.metadata.url}`);
39+
}
40+
if (data.metadata.description) {
41+
lines.push(`Description: ${data.metadata.description}`);
42+
}
43+
}
44+
45+
return lines.join('\n');
46+
}
47+
2148
/**
2249
* Extract content from Firecrawl Document based on format
2350
*/
@@ -158,6 +185,17 @@ export function handleScrapeOutput(
158185
}
159186
}
160187

188+
// Single screenshot format: output nicely formatted
189+
if (
190+
isSingleFormat &&
191+
singleFormat === 'screenshot' &&
192+
result.data.screenshot
193+
) {
194+
const content = formatScreenshotOutput(result.data);
195+
writeOutput(content, outputPath, !!outputPath);
196+
return;
197+
}
198+
161199
// Multiple formats or complex format: output JSON
162200
let outputData: any;
163201

0 commit comments

Comments
 (0)