Part of #338.
Today
Every generated command calls CliRuntime.WriteJsonAsync(...) — raw JSON is the only output. Users who want a readable terminal view (let alone scrubbing structured data into a pipeline) have to write custom formatters per response type.
Firecrawl's Commands/ ships FormatScrapeResponse, FormatCrawlStatus, FormatStartResult, etc. — hundreds of lines of hand-written formatting. The pattern is uniform: walk the response, highlight key scalars, render arrays as bullets, render dates with a sensible format.
Target
Default to a generic schema-walking formatter; opt out to raw JSON with --json.
$ firecrawl scrape https://example.com
URL: https://example.com
Status: success
Markdown: # Example Domain ...
Metadata:
- title: Example Domain
- language: en
- statusCode: 200
$ firecrawl scrape https://example.com --json
{"url":"...","markdown":"...",...}
Proposed approach
- Generate a
Format<TResponse>(TResponse value) method per response type that walks the model's PropertyData:
- scalar →
key: value line
- string > 80 chars → truncate with ellipsis (full text behind
--json or --output file.txt)
- array of scalar → multi-line bullets
- nested object → indented sub-section
- array of object → numbered entries with two-level indent
- dates →
yyyy-MM-dd HH:mm:ss UTC
--json recursive option at the root command level (added to existing --api-key/--base-url set) flips output mode. Already half-present: CliRuntime.WriteJsonAsync exists; needs a sibling WriteFormattedAsync.
- Vendor extension
x-cli-format on a property:
key → render at the top of the output
hidden → skip from formatted view (still in --json)
code → render in a code-block style (preformatted)
- Partial-class hook for full override:
partial class ScrapeCommand
{
static partial Task<string> CustomizeFormatAsync(Response response, ParseResult ctx);
}
- Mirror to
CliGenerator.cs.
Acceptance criteria
- Default
firecrawl scrape <url> shows human-readable output, --json shows raw JSON.
x-cli-format: key on a property promotes it to the top of the output.
- Partial-class override works without touching the generated
.g.cs file.
- Snapshot tests cover at least: simple scalar response, nested object, array of objects, mixed.
Part of #338.
Today
Every generated command calls
CliRuntime.WriteJsonAsync(...)— raw JSON is the only output. Users who want a readable terminal view (let alone scrubbing structured data into a pipeline) have to write custom formatters per response type.Firecrawl's
Commands/shipsFormatScrapeResponse,FormatCrawlStatus,FormatStartResult, etc. — hundreds of lines of hand-written formatting. The pattern is uniform: walk the response, highlight key scalars, render arrays as bullets, render dates with a sensible format.Target
Default to a generic schema-walking formatter; opt out to raw JSON with
--json.Proposed approach
Format<TResponse>(TResponse value)method per response type that walks the model'sPropertyData:key: valueline--jsonor--output file.txt)yyyy-MM-dd HH:mm:ss UTC--jsonrecursive option at the root command level (added to existing--api-key/--base-urlset) flips output mode. Already half-present:CliRuntime.WriteJsonAsyncexists; needs a siblingWriteFormattedAsync.x-cli-formaton a property:key→ render at the top of the outputhidden→ skip from formatted view (still in--json)code→ render in a code-block style (preformatted)CliGenerator.cs.Acceptance criteria
firecrawl scrape <url>shows human-readable output,--jsonshows raw JSON.x-cli-format: keyon a property promotes it to the top of the output..g.csfile.