Part of #338. Depends on gap #1 (per-parameter flags).
Today
Once gap #1 lands, each operation gets its own per-property flag list. For schemas reused across multiple operations (Firecrawl's ScrapeOptions is used by scrape, batch-scrape, and embedded in crawl), that produces:
- duplicated
Option<T> field definitions across multiple .g.cs files (drift risk)
- no way to share a single
--flag set under a prefix (--scrape-* in crawl)
Firecrawl's hand-written CliOptions.CreateScrapeOptionSet() returns a record with 28 options, used bare in scrape and prefixed --scrape-* in crawl. ~250 lines of careful manual wiring.
Target
When the generator detects a schema used as a request body or nested-in-request-body in 2+ operations:
- Emit a single
OptionSet static class with all the per-property Option<T> fields.
- Each consuming command imports the option set bare or prefixed.
# bare (when ScrapeOptions IS the body)
firecrawl scrape <url> --only-main-content --formats markdown
# prefixed (when ScrapeOptions is nested inside CrawlRequest.scrapeOptions)
firecrawl crawl <url> --scrape-only-main-content --scrape-formats markdown
Proposed approach
- Detect reuse: walk all operation request bodies (plus recursive into nested objects); any
ModelData referenced 2+ times qualifies as an option set candidate.
- Generate
<ModelName>OptionSet class with one static Option<T?> per scalar/array/enum property and a Bind(parseResult) method returning the populated model.
- Per-command consumption:
- bare:
command.Options.Add(ScrapeOptionsOptionSet.OnlyMainContent); ...
- prefixed: a
WithPrefix(\"scrape-\") factory that returns aliased Option<T> instances pointing at the same backing schema.
- Vendor extension
x-cli-option-set: false to opt out (always inline).
- Collision rule: when both a top-level body property and a prefixed nested property would produce
--max-depth, the top-level wins and the nested becomes --<prefix>-max-depth.
Acceptance criteria
- Regenerating Firecrawl produces one
ScrapeOptionsOptionSet.g.cs shared between scrape and crawl.
firecrawl crawl <url> --scrape-only-main-content --scrape-formats markdown works.
- No duplicated
Option<T> field definitions across .g.cs files for the same schema property.
Part of #338. Depends on gap #1 (per-parameter flags).
Today
Once gap #1 lands, each operation gets its own per-property flag list. For schemas reused across multiple operations (Firecrawl's
ScrapeOptionsis used byscrape,batch-scrape, and embedded incrawl), that produces:Option<T>field definitions across multiple.g.csfiles (drift risk)--flagset under a prefix (--scrape-*incrawl)Firecrawl's hand-written
CliOptions.CreateScrapeOptionSet()returns arecordwith 28 options, used bare inscrapeand prefixed--scrape-*incrawl. ~250 lines of careful manual wiring.Target
When the generator detects a schema used as a request body or nested-in-request-body in 2+ operations:
OptionSetstatic class with all the per-propertyOption<T>fields.Proposed approach
ModelDatareferenced 2+ times qualifies as an option set candidate.<ModelName>OptionSetclass with one staticOption<T?>per scalar/array/enum property and aBind(parseResult)method returning the populated model.command.Options.Add(ScrapeOptionsOptionSet.OnlyMainContent); ...WithPrefix(\"scrape-\")factory that returns aliasedOption<T>instances pointing at the same backing schema.x-cli-option-set: falseto opt out (always inline).--max-depth, the top-level wins and the nested becomes--<prefix>-max-depth.Acceptance criteria
ScrapeOptionsOptionSet.g.csshared betweenscrapeandcrawl.firecrawl crawl <url> --scrape-only-main-content --scrape-formats markdownworks.Option<T>field definitions across.g.csfiles for the same schema property.