Skip to main content

eli_cli/
args.rs

1#[derive(Parser, Debug)]
2#[command(name = "market-search", version, about = "Market Search: MCP server for finance data + a terminal coding agent")]
3struct Cli {
4    #[command(subcommand)]
5    cmd: Option<Command>,
6
7    /// Provider: openrouter | openai | anthropic | ollama | mock
8    #[arg(long, global = true)]
9    provider: Option<String>,
10
11    /// Model name (provider-specific)
12    #[arg(long, global = true)]
13    model: Option<String>,
14}
15
16#[derive(Subcommand, Debug)]
17enum Command {
18    /// Interactive setup - configure provider, model, and API key
19    Setup,
20
21    /// Create a default config file (if missing)
22    Init,
23
24    /// Print or set config values
25    Config {
26        /// Set a config value: provider, model, mem_steps, key, sec_user_agent, compact, compact_trigger, compact_keep, summary_model, parallel_commands, parallel_subagents, scrollback_max_lines
27        #[arg(long)]
28        set: Option<String>,
29
30        /// Value to set
31        #[arg(long)]
32        value: Option<String>,
33    },
34
35    /// Emit JSON schema for a CLI subcommand (hidden)
36    #[command(hide = true)]
37    ToolInfo {
38        /// Subcommand path (e.g., finance timeseries)
39        #[arg(value_name = "PATH", num_args = 0..)]
40        path: Vec<String>,
41    },
42
43    /// Financial data tools (for raw time-series exploration)
44    Finance {
45        #[command(subcommand)]
46        cmd: FinanceCommand,
47    },
48
49    /// Web tools (crawl, search, read)
50    Web {
51        #[command(subcommand)]
52        cmd: WebCommand,
53    },
54
55    /// Start MCP (Model Context Protocol) server — exposes market-search tools as native Claude Code tools via JSON-RPC stdio.
56    Mcp(McpArgs),
57
58    /// Log research picks for a report to track performance over time.
59    Picks {
60        #[command(subcommand)]
61        cmd: PicksCommand,
62    },
63}
64
65#[derive(Subcommand, Debug)]
66enum PicksCommand {
67    /// Record ticker/market picks at current prices for a given report.
68    Log(PicksLogArgs),
69}
70
71#[derive(clap::Args, Debug)]
72struct PicksLogArgs {
73    /// Path to the HTML report file (supports ~/).
74    #[arg(long)]
75    report: String,
76
77    /// Equity ticker(s) to track at current price (comma-separated or repeatable).
78    #[arg(long, value_delimiter = ',')]
79    ticker: Vec<String>,
80
81    /// Prediction market slug(s) to track at current probability (comma-separated or repeatable).
82    #[arg(long, value_delimiter = ',')]
83    market: Vec<String>,
84}
85
86#[derive(clap::Args, Debug)]
87struct McpArgs {
88    #[command(subcommand)]
89    cmd: Option<McpSubcommand>,
90
91    /// Run as HTTP server instead of stdio (MCP Streamable HTTP transport).
92    #[arg(long, default_value_t = false)]
93    http: bool,
94
95    /// Port for HTTP mode.
96    #[arg(long, default_value = "8484")]
97    port: u16,
98}
99
100#[derive(Subcommand, Debug)]
101enum McpSubcommand {
102    /// Get a public HTTPS /mcp URL (boots local HTTP MCP + spawns a tunnel).
103    Share(ShareArgs),
104}
105
106#[derive(clap::Args, Debug)]
107struct ShareArgs {
108    /// Tunnel provider: cloudflare | ngrok | tunnelmole | self-host
109    #[arg(long, default_value = "cloudflare")]
110    provider: String,
111
112    /// Local port the MCP HTTP server is bound to.
113    #[arg(long, default_value = "8484")]
114    port: u16,
115
116    /// For ngrok: reserved subdomain (e.g. mysub.ngrok-free.dev or just mysub).
117    #[arg(long)]
118    domain: Option<String>,
119
120    /// For ngrok: authtoken if not already configured globally.
121    #[arg(long)]
122    authtoken: Option<String>,
123}
124
125#[derive(Subcommand, Debug)]
126enum FinanceCommand {
127    /// Fetch OHLCV time-series for one or more tickers.
128    Timeseries(FinanceTimeseriesArgs),
129    /// Largest day movers by percent move, market cap, dollar volume, or estimated value change.
130    Movers(FinanceMoversArgs),
131    /// Current snapshot of income/balance/cashflow + 32 trailing ratios + company profile (sector, industry, employees). Single ticker returns object; multi-ticker returns array.
132    Fundamentals(FinanceFundamentalsArgs),
133    /// Search for ticker symbols or macro series IDs.
134    Search(FinanceSearchArgs),
135    /// Fetch recent SEC filings (8-K, 10-K, 10-Q) for a ticker.
136    Filings(FinanceFilingsArgs),
137    /// Alias for filings.
138    Sec(FinanceFilingsArgs),
139    /// Fetch earnings and macro release schedules (no-auth public endpoints).
140    Schedule(FinanceScheduleArgs),
141    /// Aggregate implied Fed policy trajectory from local prediction-market cache.
142    RatePath(FinanceRatePathArgs),
143    /// Prediction market discovery + pricing (Kalshi default; falls back to Polymarket).
144    Odds(FinanceOddsArgs),
145    /// Listed options chains with IV/skew summaries (Yahoo Finance).
146    Options(FinanceOptionsArgs),
147    /// Deprecated alias for `finance odds sync` (canonical). Same flags, same backend; kept for cron compatibility.
148    Sync(FinanceSyncArgs),
149    /// Local paper trading sandbox using live Kalshi/Polymarket prices.
150    Paper(FinancePaperArgs),
151    /// Interactive Brokers via local TWS / IB Gateway.
152    Ibkr(FinanceIbkrArgs),
153    /// Recent US Treasury auction results (bid-to-cover, tails, bidder breakdown).
154    Auctions(FinanceAuctionsArgs),
155    /// CFTC Commitment of Traders positioning (spec vs commercial, weekly).
156    Cot(FinanceCotArgs),
157    /// Futures term structure (forward curve) for commodities.
158    Curve(FinanceCurveArgs),
159    /// NY Fed Markets: overnight rates (SOFR/EFFR), reverse repo, SOMA holdings, dealer positions.
160    Nyfed(FinanceNyfedArgs),
161    /// CBOE volatility indices / term structure: VIX, VVIX, OVX, GVZ, SKEW.
162    #[command(name = "volatility", visible_alias = "volsurface")]
163    Volsurface(FinanceVolsurfaceArgs),
164    /// OFR Financial Stress Index: composite + credit/equity/funding/vol decomposition.
165    Stress(FinanceStressArgs),
166    /// Treasury fiscal data: national debt, daily statement, average interest rates.
167    Fiscal(FinanceFiscalArgs),
168    /// ECB Statistical Data Warehouse: EUR/USD, Euro STR, M3, EURIBOR, yield curve, balance sheet.
169    Ecb(FinanceEcbArgs),
170    /// EIA: US petroleum inventories (crude, gasoline, distillate), natural gas storage.
171    Eia(FinanceEiaArgs),
172    /// BIS: global central bank policy rates, total assets, credit-to-GDP gaps, property prices.
173    Bis(FinanceBisArgs),
174    /// BOJ: Bank of Japan monetary base, balance sheet, TANKAN, call rate, money stock.
175    Boj(FinanceBojArgs),
176    /// BOE: Bank of England Bank Rate, SONIA, gilt yields, M4, GBP FX rates.
177    Boe(FinanceBoeArgs),
178}
179
180#[derive(Subcommand, Debug)]
181enum WebCommand {
182    /// Crawl a website and extract content from all discovered pages.
183    Crawl(WebCrawlArgs),
184    /// Ingestion-focused web search for URL candidates + diagnostics.
185    Search(WebSearchArgs),
186    /// Read and extract content from one or many URLs.
187    Read(WebReadArgs),
188    /// Extract key facts from content (URL, file, or text).
189    Extract(WebExtractArgs),
190}
191
192#[derive(Subcommand, Debug)]
193enum AgentCommand {
194    /// Generate a market intelligence report (JSON + HTML) using Eli tools and optional model synthesis.
195    Report(AgentReportArgs),
196    /// Run a single Eli worker from a natural-language task.
197    Run(AgentRunArgs),
198    /// Run many Eli workers in parallel from a task template and vars file.
199    Fanout(AgentFanoutArgs),
200    /// Chunk a large input and orchestrate map/reduce/critic swarm synthesis.
201    Swarm(AgentSwarmArgs),
202    /// Critique a lead thesis/report using worker fanout.
203    Critique(AgentModeArgs),
204    /// Find additional evidence for/against a thesis via worker fanout.
205    Evidence(AgentModeArgs),
206    /// Run competitive workers to find the best answer.
207    Compete(AgentModeArgs),
208    /// Run worker debate and synthesize consensus.
209    Debate(AgentModeArgs),
210}
211
212#[derive(Subcommand, Debug)]
213enum SentinelCommand {
214    /// Start the sentinel daemon in the background.
215    Start(SentinelStartArgs),
216    /// Stop the sentinel daemon.
217    Stop(SentinelStopArgs),
218    /// Print sentinel daemon status.
219    Status(SentinelStatusArgs),
220    /// Register a new sentinel trigger subscription.
221    Subscribe(SentinelSubscribeArgs),
222    /// Remove a sentinel subscription by id or name.
223    Unsubscribe(SentinelUnsubscribeArgs),
224    /// List configured sentinel subscriptions.
225    List(SentinelListArgs),
226    /// Emit a synthetic alert packet for wiring tests.
227    Test(SentinelTestArgs),
228    /// Replay recent packets from queue file.
229    Replay(SentinelReplayArgs),
230    /// Internal daemon process entrypoint.
231    #[command(hide = true)]
232    DaemonRun(SentinelDaemonRunArgs),
233}
234
235#[derive(Debug, Serialize)]
236struct RustFileSummary {
237    items_total: usize,
238    functions: usize,
239    function_names: Vec<String>,
240    /// Full signatures: "pub async fn name(param: Type) -> ReturnType"
241    /// Lets an AI caller understand the API contract without reading source.
242    function_signatures: Vec<String>,
243    structs: usize,
244    struct_names: Vec<String>,
245    /// Per-struct field list: {struct_name: ["field: Type", ...]}
246    struct_fields: std::collections::BTreeMap<String, Vec<String>>,
247    enums: usize,
248    enum_names: Vec<String>,
249    impls: usize,
250    impl_targets: Vec<String>,
251    /// Methods per impl block: {"LlmAdapter for AnthropicAdapter": ["pub async fn chat(...)  -> ..."]}
252    impl_methods: std::collections::BTreeMap<String, Vec<String>>,
253    traits: usize,
254    trait_names: Vec<String>,
255    modules: usize,
256    module_names: Vec<String>,
257    uses: usize,
258    use_paths: Vec<String>,
259    consts: usize,
260    const_names: Vec<String>,
261    statics: usize,
262    type_aliases: usize,
263    type_alias_names: Vec<String>,
264    macros: usize,
265    others: usize,
266}
267
268#[derive(Copy, Clone, Debug, ValueEnum, Eq, PartialEq)]
269enum CrawlViewMode {
270    Summary,
271    Raw,
272    Path,
273}
274
275#[derive(Copy, Clone, Debug, ValueEnum, Eq, PartialEq)]
276enum CrawlSaveMode {
277    Auto,
278    Off,
279}
280
281#[derive(Copy, Clone, Debug, ValueEnum, Eq, PartialEq)]
282enum WebSearchModeArg {
283    Auto,
284    News,
285    Finance,
286    Research,
287    Tech,
288    Encyclopedia,
289}
290
291#[derive(Copy, Clone, Debug, ValueEnum, Eq, PartialEq)]
292enum WebSearchRecencyArg {
293    Day,
294    Week,
295    Month,
296    Year,
297}
298
299#[derive(Copy, Clone, Debug, ValueEnum, Eq, PartialEq)]
300enum FinancePaperCommandArg {
301    Trade,
302    Positions,
303    Trades,
304    Mark,
305    Reset,
306}
307
308#[derive(Copy, Clone, Debug, ValueEnum, Eq, PartialEq)]
309enum FinancePaperModeArg {
310    Simulated,
311    #[value(alias = "live_like")]
312    LiveLike,
313    #[value(alias = "kalshi_demo")]
314    KalshiDemo,
315    #[value(alias = "polymarket_demo")]
316    PolymarketDemo,
317}
318
319#[derive(Copy, Clone, Debug, ValueEnum, Eq, PartialEq)]
320enum FinancePaperSideArg {
321    Yes,
322    No,
323}
324
325#[derive(Copy, Clone, Debug, ValueEnum, Eq, PartialEq)]
326enum FinancePaperOrderActionArg {
327    Buy,
328    Sell,
329}
330
331#[derive(Copy, Clone, Debug, ValueEnum, Eq, PartialEq)]
332enum FinanceIbkrCommandArg {
333    Snapshot,
334    Timeseries,
335    AccountSummary,
336    Positions,
337    Portfolio,
338    OpenOrders,
339    PlaceOrder,
340    CancelOrder,
341}
342
343#[derive(Copy, Clone, Debug, ValueEnum, Eq, PartialEq)]
344enum SentinelSeverityArg {
345    Low,
346    Medium,
347    High,
348    Critical,
349}
350
351#[derive(Copy, Clone, Debug, ValueEnum, Eq, PartialEq)]
352enum SentinelSpawnTargetArg {
353    Default,
354    Codex,
355    Claude,
356    Gemini,
357    Both,
358}
359
360#[derive(clap::Args, Debug)]
361struct SentinelPathArgs {
362    /// Sentinel root directory.
363    #[arg(long = "sentinel-dir")]
364    sentinel_dir: Option<PathBuf>,
365
366    /// Queue JSONL file override.
367    #[arg(long = "queue-file")]
368    queue_file: Option<PathBuf>,
369
370    /// Intelligence packets JSONL file override.
371    #[arg(long = "packets-file")]
372    packets_file: Option<PathBuf>,
373}
374
375#[derive(clap::Args, Debug)]
376struct SentinelStartArgs {
377    #[command(flatten)]
378    paths: SentinelPathArgs,
379
380    /// Daemon evaluation interval in seconds.
381    #[arg(long = "interval-secs", default_value_t = 15)]
382    interval_secs: u64,
383}
384
385#[derive(clap::Args, Debug)]
386struct SentinelStopArgs {
387    #[command(flatten)]
388    paths: SentinelPathArgs,
389}
390
391#[derive(clap::Args, Debug)]
392struct SentinelStatusArgs {
393    #[command(flatten)]
394    paths: SentinelPathArgs,
395}
396
397#[derive(clap::Args, Debug)]
398struct SentinelSubscribeArgs {
399    #[command(flatten)]
400    paths: SentinelPathArgs,
401
402    /// Human-readable subscription name (internal slug).
403    #[arg(long)]
404    name: String,
405
406    /// Human-readable prediction statement shown in the UI.
407    /// Example: "Gold will reach 5200 before Friday close"
408    #[arg(long)]
409    title: Option<String>,
410
411    /// Title of the report that authored this prediction.
412    #[arg(long = "source-report")]
413    source_report_title: Option<String>,
414
415    /// Date of the source report (ISO format, e.g. 2026-03-06).
416    #[arg(long = "source-date")]
417    source_report_date: Option<String>,
418
419    /// Filename of the source report (relative to reports_dir) for opening in the UI.
420    #[arg(long = "source-file")]
421    source_report_file: Option<String>,
422
423    /// Key evidence snippet or quote from the source report justifying this prediction.
424    #[arg(long = "source-evidence")]
425    source_evidence: Option<String>,
426
427    /// Trigger expression, e.g. \"pyth_wti > 80 && poly_hormuz_yes > 0.50\".
428    /// Optional when --fire-at is set (defaults to "true" for pure checkpoint daemons).
429    #[arg(long)]
430    expr: Option<String>,
431
432    /// Optional variable mapping (repeatable): var=provider:query
433    #[arg(long = "var")]
434    vars: Vec<String>,
435
436    /// Why this alert matters (stored in packet/playbook).
437    #[arg(long = "why")]
438    why: Option<String>,
439
440    /// Prompt template for the follow-up playbook.
441    #[arg(long = "prompt-template")]
442    prompt_template: Option<String>,
443
444    /// Alert severity.
445    #[arg(long, value_enum, default_value = "medium")]
446    severity: SentinelSeverityArg,
447
448    /// Cooldown between repeated triggers (seconds).
449    #[arg(long = "cooldown-secs", default_value_t = 300)]
450    cooldown_secs: u64,
451
452    /// Start enabled (default true).
453    #[arg(long, default_value_t = true)]
454    enabled: bool,
455
456    /// Spawn headless AI agent (claude/codex) when this subscription triggers.
457    #[arg(long = "spawn-agent", default_value_t = false)]
458    spawn_agent: bool,
459
460    /// Which headless writer(s) should fire when this subscription triggers.
461    #[arg(long = "spawn-target", value_enum, default_value = "default")]
462    spawn_target: SentinelSpawnTargetArg,
463
464    /// Legacy spawn cooldown field retained for compatibility with existing subscriptions.
465    /// Spawn routing now uses rolling per-hour budgets instead.
466    #[arg(long = "spawn-cooldown-secs", default_value_t = 14400, hide = true)]
467    spawn_cooldown_secs: u64,
468
469    /// Human-readable prediction thesis this daemon encodes.
470    /// When set, fires on HIT (condition met) OR MISS (deadline elapsed without condition met).
471    #[arg(long = "prediction")]
472    prediction: Option<String>,
473
474    /// Which variable name in --expr to track as the prediction target (e.g., "pyth_wti").
475    #[arg(long = "target-var")]
476    target_var: Option<String>,
477
478    /// Predicted numeric target for target-var (e.g., 90.0).
479    #[arg(long = "target-value")]
480    target_value: Option<f64>,
481
482    /// Prediction deadline in RFC3339 format (e.g., 2026-04-01T00:00:00Z).
483    /// Fires MISS if condition not met by this time.
484    #[arg(long = "deadline")]
485    deadline: Option<String>,
486
487    /// Scheduled fire time in RFC3339 format (e.g., 2026-03-12T16:03:00Z).
488    /// Daemon fires ONCE at this exact time. Expr is evaluated at that moment for HIT/MISS.
489    /// Omit --expr for a pure checkpoint (always fires, no condition).
490    #[arg(long = "fire-at")]
491    fire_at: Option<String>,
492}
493
494#[derive(clap::Args, Debug)]
495struct SentinelUnsubscribeArgs {
496    #[command(flatten)]
497    paths: SentinelPathArgs,
498
499    /// Subscription id or exact name.
500    #[arg(long = "id")]
501    id_or_name: String,
502}
503
504#[derive(clap::Args, Debug)]
505struct SentinelListArgs {
506    #[command(flatten)]
507    paths: SentinelPathArgs,
508}
509
510#[derive(clap::Args, Debug)]
511struct SentinelTestArgs {
512    #[command(flatten)]
513    paths: SentinelPathArgs,
514
515    /// Synthetic test scenario.
516    #[arg(long, default_value = "generic")]
517    scenario: String,
518}
519
520#[derive(clap::Args, Debug)]
521struct SentinelReplayArgs {
522    #[command(flatten)]
523    paths: SentinelPathArgs,
524
525    /// Number of recent queue lines to replay.
526    #[arg(long = "max-lines", default_value_t = 50)]
527    max_lines: usize,
528}
529
530#[derive(clap::Args, Debug)]
531struct SentinelDaemonRunArgs {
532    #[command(flatten)]
533    paths: SentinelPathArgs,
534
535    /// Daemon evaluation interval in seconds.
536    #[arg(long = "interval-secs", default_value_t = 15)]
537    interval_secs: u64,
538}
539
540#[derive(clap::Args, Debug)]
541struct AgentReportArgs {
542    /// Report objective/prompt. Defaults to Eli three-pillar research framework.
543    #[arg(long)]
544    prompt: Option<String>,
545
546    /// Comma-separated market tickers for snapshot/timeseries.
547    #[arg(
548        long,
549        value_delimiter = ',',
550        default_value = "SPY,QQQ,IWM,DIA,^VIX,BTC-USD,ETH-USD,SOL-USD,DX-Y.NYB,GC=F,CL=F"
551    )]
552    tickers: Vec<String>,
553
554    /// Historical lookback span for timeseries (e.g. 14d, 30d, 3mo).
555    #[arg(long, default_value = "14d")]
556    lookback: String,
557
558    /// Timeseries granularity (e.g. 15min, 1h, 1d).
559    #[arg(long, default_value = "1h")]
560    granularity: String,
561
562    /// Lock clock-sensitive tools to N minutes before report start.
563    #[arg(long = "lock-minutes", conflicts_with = "as_of")]
564    lock_minutes: Option<u64>,
565
566    /// Explicit report anchor time (RFC3339 or YYYY-MM-DD).
567    #[arg(long = "as-of", conflicts_with = "lock_minutes")]
568    as_of: Option<String>,
569
570    /// Comma-separated odds search queries.
571    #[arg(
572        long,
573        value_delimiter = ',',
574        default_value = "recession,fed,inflation,iran,oil,china,taiwan"
575    )]
576    odds_queries: Vec<String>,
577
578    /// Number of top markets per odds query.
579    #[arg(long, default_value_t = 8)]
580    top: usize,
581
582    /// Comma-separated web queries for narrative context.
583    #[arg(
584        long,
585        value_delimiter = ',',
586        default_value = "stock market today,treasury yields today,fed policy outlook,oil geopolitical risk"
587    )]
588    web_queries: Vec<String>,
589
590    /// Max runtime budget per command invocation (milliseconds).
591    #[arg(long = "max-ms", default_value_t = 45000)]
592    max_ms: u64,
593
594    /// Comma-separated fallback models for synthesis worker.
595    #[arg(long = "fallback-models", value_delimiter = ',')]
596    fallback_models: Vec<String>,
597
598    /// Optional explicit HTML output path.
599    #[arg(long = "html-out")]
600    html_out: Option<PathBuf>,
601
602    /// Output JSON path for the report envelope.
603    #[arg(long)]
604    out: Option<PathBuf>,
605}
606
607#[derive(clap::Args, Debug)]
608struct AgentRunArgs {
609    /// Natural-language task for the worker.
610    #[arg(long)]
611    task: String,
612
613    /// Output file path (JSON).
614    #[arg(long)]
615    out: Option<PathBuf>,
616
617    /// Comma-separated fallback models (used on worker failure).
618    #[arg(long = "fallback-models", value_delimiter = ',')]
619    fallback_models: Vec<String>,
620
621    /// Max runtime budget per worker (milliseconds).
622    #[arg(long = "max-ms", default_value_t = 45000)]
623    max_ms: u64,
624
625    /// Max total attempts per worker across primary + fallbacks.
626    #[arg(long = "max-attempts", default_value_t = 4)]
627    max_attempts: usize,
628
629    /// Require the final report to cite these path prefixes (comma-separated).
630    #[arg(long = "must-cite", value_delimiter = ',')]
631    must_cite: Vec<String>,
632}
633
634#[derive(clap::Args, Debug)]
635struct AgentFanoutArgs {
636    /// Task template. Use placeholders like {{ticker}} or {{stance}}.
637    #[arg(long = "task-template")]
638    task_template: String,
639
640    /// JSON file containing an array of objects for template vars.
641    #[arg(long)]
642    vars: PathBuf,
643
644    /// Optional shared artifact manifest path all workers should read first.
645    #[arg(long = "shared-manifest")]
646    shared_manifest: Option<PathBuf>,
647
648    /// Max workers to run at once.
649    #[arg(long, default_value = "4")]
650    max_parallel: usize,
651
652    /// Output file path (JSON).
653    #[arg(long)]
654    out: Option<PathBuf>,
655
656    /// Comma-separated fallback models (used on worker failure).
657    #[arg(long = "fallback-models", value_delimiter = ',')]
658    fallback_models: Vec<String>,
659
660    /// Max runtime budget per worker (milliseconds).
661    #[arg(long = "max-ms", default_value_t = 45000)]
662    max_ms: u64,
663
664    /// Max total attempts per worker across primary + fallbacks.
665    #[arg(long = "max-attempts", default_value_t = 4)]
666    max_attempts: usize,
667
668    /// Require each successful worker report to cite these path prefixes (comma-separated).
669    #[arg(long = "must-cite", value_delimiter = ',')]
670    must_cite: Vec<String>,
671}
672
673#[derive(clap::Args, Debug)]
674struct AgentSwarmArgs {
675    /// High-level goal for the swarm.
676    #[arg(long)]
677    task: String,
678
679    /// Input file to process (txt/md/json/csv/ndjson/pdf).
680    #[arg(long)]
681    input: PathBuf,
682
683    /// Optional explicit number of chunk workers (X swarms).
684    #[arg(long)]
685    chunks: Option<usize>,
686
687    /// Approximate characters per chunk when --chunks is not provided.
688    #[arg(long = "chunk-chars", default_value_t = 20_000)]
689    chunk_chars: usize,
690
691    /// Character overlap between chunks to reduce boundary loss.
692    #[arg(long = "overlap-chars", default_value_t = 500)]
693    overlap_chars: usize,
694
695    /// Hard cap on produced chunks.
696    #[arg(long = "max-chunks", default_value_t = 64)]
697    max_chunks: usize,
698
699    /// Max workers to run at once for map stage.
700    #[arg(long, default_value = "4")]
701    max_parallel: usize,
702
703    /// Output file path (JSON).
704    #[arg(long)]
705    out: Option<PathBuf>,
706
707    /// Comma-separated fallback models (used on worker failure).
708    #[arg(long = "fallback-models", value_delimiter = ',')]
709    fallback_models: Vec<String>,
710
711    /// Max runtime budget per worker (milliseconds).
712    #[arg(long = "max-ms", default_value_t = 120_000)]
713    max_ms: u64,
714
715    /// Max total attempts per worker across primary + fallbacks.
716    #[arg(long = "max-attempts", default_value_t = 4)]
717    max_attempts: usize,
718
719    /// Require successful stage reports to cite these path prefixes (comma-separated).
720    #[arg(long = "must-cite", value_delimiter = ',')]
721    must_cite: Vec<String>,
722}
723
724#[derive(clap::Args, Debug)]
725struct AgentModeArgs {
726    /// User objective for this report mode.
727    #[arg(long)]
728    prompt: String,
729
730    /// Optional lead report or thesis file path.
731    #[arg(long)]
732    lead: Option<PathBuf>,
733
734    /// JSON file containing an array of worker objects (name/model/role/etc).
735    #[arg(long)]
736    vars: PathBuf,
737
738    /// Optional shared artifact manifest path all workers should read first.
739    #[arg(long = "shared-manifest")]
740    shared_manifest: Option<PathBuf>,
741
742    /// Allow workers to reference peer output in compete/debate modes.
743    #[arg(long, default_value_t = false)]
744    allow_cheat: bool,
745
746    /// Max workers to run at once.
747    #[arg(long, default_value = "4")]
748    max_parallel: usize,
749
750    /// Output file path (JSON).
751    #[arg(long)]
752    out: Option<PathBuf>,
753
754    /// Comma-separated fallback models (used on worker failure).
755    #[arg(long = "fallback-models", value_delimiter = ',')]
756    fallback_models: Vec<String>,
757
758    /// Max runtime budget per worker (milliseconds).
759    #[arg(long = "max-ms", default_value_t = 120_000)]
760    max_ms: u64,
761
762    /// Max total attempts per worker across primary + fallbacks.
763    #[arg(long = "max-attempts", default_value_t = 2)]
764    max_attempts: usize,
765
766    /// Require each successful worker report to cite these path prefixes (comma-separated).
767    #[arg(long = "must-cite", value_delimiter = ',')]
768    must_cite: Vec<String>,
769}
770
771#[derive(clap::Args, Debug)]
772struct CodeArgs {
773    /// Path to Rust source file or directory to analyze.
774    path: PathBuf,
775
776    /// Also generate code (e.g., getter methods for structs).
777    #[arg(long, default_value_t = false)]
778    generate: bool,
779
780    /// Minimum line count filter (directory mode only).
781    #[arg(long, default_value_t = 0)]
782    min_loc: usize,
783
784    /// Maximum number of files to analyze after sorting by path (directory mode only).
785    #[arg(long)]
786    max_files: Option<usize>,
787
788    /// Parallel worker count for Rust parsing (directory mode only).
789    #[arg(long)]
790    workers: Option<usize>,
791
792    /// Number of rows to include for each hotspot ranking (directory mode only).
793    #[arg(long, default_value_t = 20)]
794    top: usize,
795
796    /// Include per-file metrics in response (directory mode only).
797    #[arg(long, default_value_t = false)]
798    include_files: bool,
799
800    /// Search for symbol usages across all .rs files in path (comma-separated).
801    /// Uses multi-pattern matching. Returns every line containing any of the symbols
802    /// with file path and line number. Works on files and directories.
803    #[arg(long, value_delimiter = ',')]
804    find: Vec<String>,
805
806    /// Emit the complete public API surface for a directory: every pub fn (with full
807    /// signature), pub struct (with field types), pub enum (with variants), pub trait
808    /// (with method signatures), grouped by file. Ideal for understanding a module's
809    /// contract before writing new code.
810    #[arg(long, default_value_t = false)]
811    pub_api: bool,
812
813    /// Optional output file for JSON response.
814    #[arg(long)]
815    out: Option<PathBuf>,
816}
817
818#[derive(clap::Args, Debug)]
819struct WebCrawlArgs {
820    /// URL to start crawling from.
821    #[arg(long)]
822    url: String,
823
824    /// Maximum number of pages to crawl (default: 50).
825    #[arg(long, default_value = "50")]
826    max_pages: usize,
827
828    /// Respect robots.txt (default: true).
829    #[arg(long, default_value = "true")]
830    respect_robots: bool,
831
832    /// Include subdomains in crawl (default: false).
833    #[arg(long, default_value = "false")]
834    subdomains: bool,
835
836    /// Crawl via sitemap discovery mode.
837    #[arg(long, default_value = "false")]
838    sitemap: bool,
839
840    /// Smart crawl mode: HTTP first, render JS only when needed.
841    #[arg(long, default_value = "false", conflicts_with = "sitemap")]
842    smart: bool,
843
844    /// Terminal output view.
845    #[arg(long, value_enum, default_value_t = CrawlViewMode::Summary)]
846    view: CrawlViewMode,
847
848    /// Save policy when --out is not provided.
849    #[arg(long, value_enum, default_value_t = CrawlSaveMode::Auto)]
850    save: CrawlSaveMode,
851
852    /// Output file path (JSON).
853    #[arg(long)]
854    out: Option<PathBuf>,
855}
856
857#[derive(clap::Args, Debug)]
858struct WebSearchArgs {
859    /// Search query.
860    #[arg(long)]
861    query: String,
862
863    /// Search mode tuned for different ingestion workflows.
864    #[arg(long, value_enum, default_value_t = WebSearchModeArg::Auto)]
865    mode: WebSearchModeArg,
866
867    /// Include only these domains (comma-separated).
868    #[arg(long, value_delimiter = ',')]
869    domains: Vec<String>,
870
871    /// Exclude these domains (comma-separated).
872    #[arg(long = "exclude-domains", value_delimiter = ',')]
873    exclude_domains: Vec<String>,
874
875    /// Recency hint (day, week, month, year).
876    #[arg(long, value_enum)]
877    recency: Option<WebSearchRecencyArg>,
878
879    /// Earliest publication date (YYYY-MM-DD).
880    #[arg(long)]
881    since: Option<String>,
882
883    /// Latest publication date (YYYY-MM-DD).
884    #[arg(long)]
885    until: Option<String>,
886
887    /// Maximum items to return.
888    #[arg(long, default_value_t = 15)]
889    top: usize,
890
891    /// Number of top results to probe with web read diagnostics.
892    #[arg(long = "probe-top", default_value_t = 4)]
893    probe_top: usize,
894
895    /// Maximum parallel network operations.
896    #[arg(long = "max-parallel", default_value_t = 6)]
897    max_parallel: usize,
898
899    /// Optional run-tracking key for delta comparisons.
900    #[arg(long = "track-key")]
901    track_key: Option<String>,
902
903    /// Emit full verbose payload (snippets + detailed score components).
904    #[arg(long, default_value_t = false)]
905    full: bool,
906
907    /// Output file path (JSON).
908    #[arg(long)]
909    out: Option<PathBuf>,
910}
911
912#[derive(clap::Args, Debug)]
913struct WebReadArgs {
914    /// URL(s) to read content from (repeatable or comma-separated).
915    #[arg(long = "url", value_delimiter = ',')]
916    url: Vec<String>,
917
918    /// Optional file containing URLs (one per line, '#' comments allowed).
919    #[arg(long = "urls-file")]
920    urls_file: Option<PathBuf>,
921
922    /// Maximum parallel URL fetches.
923    #[arg(long = "max-parallel", default_value_t = 6)]
924    max_parallel: usize,
925
926    /// Max chars to keep per article text in default compact mode.
927    #[arg(long = "max-chars", default_value_t = 2400)]
928    max_chars: usize,
929
930    /// Emit full verbose payload (full text + attempt details).
931    #[arg(long, default_value_t = false)]
932    full: bool,
933
934    /// Output file path (JSON).
935    #[arg(long)]
936    out: Option<PathBuf>,
937}
938
939#[derive(clap::Args, Debug)]
940struct WebExtractArgs {
941    /// URL to fetch and extract from.
942    #[arg(long)]
943    url: Option<String>,
944
945    /// File path to extract from.
946    #[arg(long)]
947    file: Option<PathBuf>,
948
949    /// Inline text to extract from (use heredoc for large content).
950    #[arg(long)]
951    text: Option<String>,
952
953    /// Number of bullet points to extract (default: 10).
954    #[arg(long, default_value = "10")]
955    bullets: usize,
956
957    /// Focus extraction on specific topic.
958    #[arg(long)]
959    focus: Option<String>,
960
961    /// Output file path (JSON).
962    #[arg(long)]
963    out: Option<PathBuf>,
964}
965
966#[derive(clap::Args, Debug)]
967pub struct FinanceScheduleArgs {
968    /// Schedule kind: earnings | macro | all.
969    #[arg(long, default_value = "all")]
970    pub kind: String,
971    /// Single date (YYYY-MM-DD). If set, overrides --from/--to.
972    #[arg(long)]
973    pub date: Option<String>,
974    /// Start date (YYYY-MM-DD).
975    #[arg(long = "from")]
976    pub from: Option<String>,
977    /// End date (YYYY-MM-DD).
978    #[arg(long = "to")]
979    pub to: Option<String>,
980    /// Optional ticker filter for earnings rows (repeatable or comma-separated).
981    #[arg(long, visible_alias = "tickers", value_delimiter = ',')]
982    pub ticker: Vec<String>,
983    /// Macro-only: keep only major US releases (CPI, PCE, GDP, jobs, FOMC, claims).
984    #[arg(long, default_value_t = false)]
985    pub major: bool,
986    /// Minimum market cap for earnings (e.g. 10B, 500M, 1T).
987    #[arg(long = "min-cap")]
988    pub min_cap: Option<String>,
989    /// Filter earnings by report time: pre-market | after-hours.
990    #[arg(long)]
991    pub time: Option<String>,
992    /// Macro filtering profile: broad | market | major.
993    #[arg(long = "macro-profile", default_value = "market")]
994    pub macro_profile: String,
995    /// Output format (json only).
996    #[arg(long, default_value = "json")]
997    pub format: String,
998    /// Write full JSON output to a file instead of stdout.
999    #[arg(long)]
1000    pub out: Option<PathBuf>,
1001}
1002
1003#[derive(clap::Args, Debug)]
1004pub struct FinanceRatePathArgs {
1005    /// Optional cache directory for prediction-market CSVs.
1006    #[arg(long)]
1007    pub cache_dir: Option<PathBuf>,
1008    /// DEPRECATED: accepted for backwards compatibility but ignored. The live
1009    /// API path always dominates; the CSV cache is only used when the live
1010    /// fetch fails. The auto/meeting/fallback distinction was a no-op.
1011    #[arg(long, default_value = "auto", hide = true)]
1012    pub source_mode: String,
1013    /// Output format (json only).
1014    #[arg(long, default_value = "json")]
1015    pub format: String,
1016    /// Output file path.
1017    #[arg(long)]
1018    pub out: Option<PathBuf>,
1019}
1020
1021#[derive(clap::Args, Debug)]
1022pub struct FinanceAuctionsArgs {
1023    /// Filter by security type: bill, note, bond, tips, frn, or all.
1024    #[arg(long, default_value = "all")]
1025    pub security_type: String,
1026    /// Number of recent auctions to return.
1027    #[arg(long, default_value_t = 50)]
1028    pub limit: usize,
1029    /// Output format (json only).
1030    #[arg(long, default_value = "json")]
1031    pub format: String,
1032    /// Output file path.
1033    #[arg(long)]
1034    pub out: Option<PathBuf>,
1035}
1036
1037#[derive(clap::Args, Debug)]
1038pub struct FinanceCotArgs {
1039    /// Search query to filter by contract name (e.g. "gold", "crude oil", "10y note").
1040    #[arg(long)]
1041    pub query: Option<String>,
1042    /// Number of weeks of data to fetch. Default 12.
1043    #[arg(long, default_value_t = 12)]
1044    pub weeks: usize,
1045    /// Report type: auto (detect from query), disaggregated (commodities), or financial (rates/FX/equity).
1046    #[arg(long, default_value = "auto")]
1047    pub report: String,
1048    /// Max number of distinct contracts to return (default 15).
1049    #[arg(long)]
1050    pub limit: Option<usize>,
1051    /// Output format (json only).
1052    #[arg(long, default_value = "json")]
1053    pub format: String,
1054    /// Output file path.
1055    #[arg(long)]
1056    pub out: Option<PathBuf>,
1057}
1058
1059#[derive(clap::Args, Debug)]
1060pub struct FinanceCurveArgs {
1061    /// Commodity to chart (e.g. oil, gold, natgas, silver, copper). Use --list to see all.
1062    #[arg(long)]
1063    pub commodity: Option<String>,
1064    /// Number of forward months to include (default 12, max 24).
1065    #[arg(long, default_value_t = 12)]
1066    pub months: usize,
1067    /// List supported commodities.
1068    #[arg(long, default_value_t = false)]
1069    pub list: bool,
1070    /// Output file path.
1071    #[arg(long)]
1072    pub out: Option<PathBuf>,
1073}
1074
1075#[derive(clap::Args, Debug)]
1076pub struct FinanceNyfedArgs {
1077    /// Endpoint: rates | rrp | soma | dealers
1078    #[arg(long, default_value = "rates")]
1079    pub kind: String,
1080    #[arg(long, default_value = "json")]
1081    pub format: String,
1082    #[arg(long)]
1083    pub out: Option<PathBuf>,
1084}
1085
1086#[derive(clap::Args, Debug)]
1087pub struct FinanceVolsurfaceArgs {
1088    /// Comma-separated CBOE index symbols (default: all 9). Options: VIX,VIX9D,VIX3M,VIX6M,VIX1Y,VVIX,OVX,GVZ,SKEW
1089    #[arg(long)]
1090    pub symbols: Option<String>,
1091    /// Number of historical trading days (default: latest only)
1092    #[arg(long)]
1093    pub history: Option<usize>,
1094    #[arg(long, default_value = "json")]
1095    pub format: String,
1096    #[arg(long)]
1097    pub out: Option<PathBuf>,
1098}
1099
1100#[derive(clap::Args, Debug)]
1101pub struct FinanceStressArgs {
1102    /// Days of history (default: 30)
1103    #[arg(long, default_value_t = 30)]
1104    pub range: usize,
1105    #[arg(long, default_value = "json")]
1106    pub format: String,
1107    #[arg(long)]
1108    pub out: Option<PathBuf>,
1109}
1110
1111#[derive(clap::Args, Debug)]
1112pub struct FinanceFiscalArgs {
1113    /// Endpoint: debt | statement | interest
1114    #[arg(long, default_value = "debt")]
1115    pub kind: String,
1116    #[arg(long, default_value = "json")]
1117    pub format: String,
1118    #[arg(long)]
1119    pub out: Option<PathBuf>,
1120}
1121
1122#[derive(clap::Args, Debug)]
1123pub struct FinanceEcbArgs {
1124    /// Preset: eurusd | fx_majors | estr | m3 | euribor | yield_curve | balance_sheet
1125    #[arg(long)]
1126    pub preset: Option<String>,
1127    /// SDMX dataset (e.g. EXR, BSI, FM, EST, YC). Use with --key.
1128    #[arg(long)]
1129    pub dataset: Option<String>,
1130    /// SDMX dimension key (e.g. D.USD.EUR.SP00.A). Use with --dataset.
1131    #[arg(long)]
1132    pub key: Option<String>,
1133    /// Start period (YYYY-MM-DD or YYYY-MM or YYYY).
1134    #[arg(long, default_value = "2025-01-01")]
1135    pub start: String,
1136    /// End period.
1137    #[arg(long)]
1138    pub end: Option<String>,
1139    #[arg(long, default_value = "json")]
1140    pub format: String,
1141    #[arg(long)]
1142    pub out: Option<PathBuf>,
1143}
1144
1145#[derive(clap::Args, Debug)]
1146pub struct FinanceEiaArgs {
1147    /// Preset: crude | gasoline | distillate | all | nat_gas
1148    #[arg(long)]
1149    pub preset: Option<String>,
1150    /// Custom API route (e.g. petroleum/stoc/wstk/data/).
1151    #[arg(long)]
1152    pub route: Option<String>,
1153    /// Start date (YYYY-MM-DD).
1154    #[arg(long)]
1155    pub start: Option<String>,
1156    /// Max observations to return (default 52 = ~1 year weekly).
1157    #[arg(long, default_value = "52")]
1158    pub length: usize,
1159    #[arg(long, default_value = "json")]
1160    pub format: String,
1161    #[arg(long)]
1162    pub out: Option<PathBuf>,
1163}
1164
1165#[derive(clap::Args, Debug)]
1166pub struct FinanceBisArgs {
1167    /// Preset: policy_rates | assets | credit_gap | property | eer
1168    #[arg(long)]
1169    pub preset: Option<String>,
1170    /// SDMX dataset (e.g. WS_CBPOL). Use with --key.
1171    #[arg(long)]
1172    pub dataset: Option<String>,
1173    /// SDMX key (e.g. M.US+XM+JP+GB). Use with --dataset.
1174    #[arg(long)]
1175    pub key: Option<String>,
1176    /// Country codes (comma-separated, e.g. US,XM,JP,GB).
1177    #[arg(long)]
1178    pub countries: Option<String>,
1179    /// Start period (YYYY-MM).
1180    #[arg(long, default_value = "2020-01")]
1181    pub start: String,
1182    #[arg(long, default_value = "json")]
1183    pub format: String,
1184    #[arg(long)]
1185    pub out: Option<PathBuf>,
1186}
1187
1188#[derive(clap::Args, Debug)]
1189pub struct FinanceBojArgs {
1190    /// Preset: policy_rate | call_rate | monetary_base | balance_sheet | money_stock | tankan | fx
1191    #[arg(long)]
1192    pub preset: Option<String>,
1193    /// BOJ database name (e.g. IR01, FM01, BS01, CO). Use with --codes.
1194    #[arg(long)]
1195    pub db: Option<String>,
1196    /// BOJ series codes (comma-separated).
1197    #[arg(long)]
1198    pub codes: Option<String>,
1199    /// Start date (YYYYMM format for BOJ).
1200    #[arg(long, default_value = "202401")]
1201    pub start: String,
1202    #[arg(long, default_value = "json")]
1203    pub format: String,
1204    #[arg(long)]
1205    pub out: Option<PathBuf>,
1206}
1207
1208#[derive(clap::Args, Debug)]
1209pub struct FinanceBoeArgs {
1210    /// Preset: bank_rate | sonia | gilts | m4 | fx | all
1211    #[arg(long)]
1212    pub preset: Option<String>,
1213    /// Series codes (comma-separated, e.g. IUDBEDR,IUDSOIA).
1214    #[arg(long)]
1215    pub codes: Option<String>,
1216    /// Start date (DD/Mon/YYYY format, e.g. 01/Jan/2025).
1217    #[arg(long, default_value = "01/Jan/2025")]
1218    pub start: String,
1219    /// End date (DD/Mon/YYYY or "now").
1220    #[arg(long, default_value = "now")]
1221    pub end: String,
1222    #[arg(long, default_value = "json")]
1223    pub format: String,
1224    #[arg(long)]
1225    pub out: Option<PathBuf>,
1226}
1227
1228#[derive(clap::Args, Debug)]
1229struct FinanceFundamentalsArgs {
1230    /// Tickers to fetch (repeatable or comma-separated).
1231    #[arg(long, visible_alias = "ticker", value_delimiter = ',')]
1232    tickers: Vec<String>,
1233
1234    /// Output format (currently: json).
1235    #[arg(long, default_value = "json")]
1236    format: String,
1237
1238    /// Write full JSON output to a file instead of stdout.
1239    #[arg(long)]
1240    out: Option<PathBuf>,
1241}
1242
1243#[derive(clap::Args, Debug)]
1244struct FinanceMoversArgs {
1245    /// Candidate universe: day_movers | day_gainers | day_losers | most_actives |
1246    /// small_cap_gainers | aggressive_small_caps | top_etfs | most_shorted | tickers.
1247    #[arg(long, default_value = "day_movers")]
1248    universe: String,
1249
1250    /// Explicit tickers for universe=tickers, or to override screener discovery.
1251    #[arg(long, visible_alias = "ticker", value_delimiter = ',')]
1252    tickers: Vec<String>,
1253
1254    /// Direction filter: gainers | losers | both.
1255    #[arg(long, default_value = "both")]
1256    direction: String,
1257
1258    /// Sort by: percent | abs_percent | market_cap | value_change | dollar_volume | volume.
1259    #[arg(long, default_value = "value_change")]
1260    sort_by: String,
1261
1262    /// Data provider for price/change: auto | yahoo | ibkr. Auto uses IBKR when configured, Yahoo otherwise.
1263    #[arg(long, default_value = "auto")]
1264    provider: String,
1265
1266    /// Minimum market cap filter, e.g. 500M, 2B, 1.5T.
1267    #[arg(long)]
1268    min_market_cap: Option<String>,
1269
1270    /// Maximum market cap filter, e.g. 2B for small/mid-cap screens.
1271    #[arg(long)]
1272    max_market_cap: Option<String>,
1273
1274    /// Minimum absolute percent move.
1275    #[arg(long, default_value_t = 0.0)]
1276    min_change_pct: f64,
1277
1278    /// Minimum last price.
1279    #[arg(long, default_value_t = 5.0)]
1280    min_price: f64,
1281
1282    /// Minimum reported day volume.
1283    #[arg(long)]
1284    min_volume: Option<u64>,
1285
1286    /// Optional sector filter (case-insensitive substring match against Yahoo screener `sector`).
1287    #[arg(long)]
1288    sector: Option<String>,
1289
1290    /// Optional industry filter (case-insensitive substring match against Yahoo screener `industry`).
1291    #[arg(long)]
1292    industry: Option<String>,
1293
1294    /// Number of movers to return.
1295    #[arg(long, default_value_t = 25)]
1296    limit: usize,
1297
1298    /// Candidate count per Yahoo screener leg before local filtering/sorting.
1299    #[arg(long, default_value_t = 100)]
1300    scan_limit: usize,
1301
1302    /// Optional IBKR account code. Used when --provider ibkr or auto detects IBKR setup.
1303    #[arg(long)]
1304    ibkr_account: Option<String>,
1305
1306    /// Optional IBKR host override.
1307    #[arg(long)]
1308    ibkr_host: Option<String>,
1309
1310    /// Optional IBKR port override.
1311    #[arg(long)]
1312    ibkr_port: Option<u16>,
1313
1314    /// Optional IBKR client id override.
1315    #[arg(long)]
1316    ibkr_client_id: Option<i32>,
1317
1318    /// Optional IBKR market data type: 1 live, 2 frozen, 3 delayed, 4 delayed-frozen.
1319    #[arg(long)]
1320    ibkr_market_data_type: Option<i32>,
1321
1322    /// Optional IBKR timeout in seconds.
1323    #[arg(long)]
1324    ibkr_timeout_secs: Option<u64>,
1325
1326    /// Output format (currently: json).
1327    #[arg(long, default_value = "json")]
1328    format: String,
1329
1330    /// Write full JSON output to a file instead of stdout.
1331    #[arg(long)]
1332    out: Option<PathBuf>,
1333
1334    /// Also fetch and surface pre-market / after-hours move alongside regular-session change.
1335    #[arg(long, default_value_t = false)]
1336    include_extended_hours: bool,
1337}
1338
1339#[derive(clap::Args, Debug)]
1340struct FinanceSearchArgs {
1341    /// Search query (e.g. "Apple" or "Inflation").
1342    #[arg(long, required = false)]
1343    query: Option<String>,
1344
1345    /// Search query (positional alternative to --query).
1346    #[arg(index = 1, required = false)]
1347    query_positional: Option<String>,
1348
1349    /// Data provider (yahoo | ibkr).
1350    #[arg(long, default_value = "yahoo")]
1351    provider: String,
1352
1353    /// Optional IBKR account code (e.g. U1234567). Used when --provider ibkr.
1354    #[arg(long)]
1355    ibkr_account: Option<String>,
1356
1357    /// Optional IBKR host override.
1358    #[arg(long)]
1359    ibkr_host: Option<String>,
1360
1361    /// Optional IBKR port override.
1362    #[arg(long)]
1363    ibkr_port: Option<u16>,
1364
1365    /// Optional IBKR client id override.
1366    #[arg(long)]
1367    ibkr_client_id: Option<i32>,
1368
1369    /// Optional IBKR market data type: 1 live, 2 frozen, 3 delayed, 4 delayed-frozen.
1370    #[arg(long)]
1371    ibkr_market_data_type: Option<i32>,
1372
1373    /// Output format (currently: json).
1374    #[arg(long, default_value = "json")]
1375    format: String,
1376
1377    /// Optional policy file override.
1378    #[arg(long = "policy-file")]
1379    policy_file: Option<PathBuf>,
1380
1381    /// Policy mode: observe | assist | enforce.
1382    #[arg(long = "policy-mode", default_value = "observe")]
1383    policy_mode: String,
1384
1385    /// Write full JSON output to a file instead of stdout.
1386    #[arg(long)]
1387    out: Option<PathBuf>,
1388}
1389
1390#[derive(clap::Args, Debug)]
1391struct FinanceOddsArgs {
1392    #[command(subcommand)]
1393    action: Option<FinanceOddsAction>,
1394
1395    /// Data source: kalshi (default), polymarket, or auto (kalshi then polymarket).
1396    #[arg(long)]
1397    provider: Option<String>,
1398    /// Kalshi series ticker.
1399    #[arg(long)]
1400    series: Option<String>,
1401
1402    /// Event ticker.
1403    #[arg(long)]
1404    event: Option<String>,
1405
1406    /// Market ticker.
1407    #[arg(long)]
1408    market: Option<String>,
1409
1410    /// Filter by status (e.g. open).
1411    #[arg(long)]
1412    status: Option<String>,
1413
1414    /// Page size limit.
1415    #[arg(long)]
1416    limit: Option<usize>,
1417
1418    /// Pagination cursor.
1419    #[arg(long)]
1420    cursor: Option<String>,
1421
1422    /// Max pages to fetch (Kalshi list endpoints).
1423    #[arg(long)]
1424    max_pages: Option<usize>,
1425
1426    /// List series (Kalshi only).
1427    #[arg(long)]
1428    list_series: bool,
1429
1430    /// List events.
1431    #[arg(long)]
1432    list_events: bool,
1433
1434    /// List markets.
1435    #[arg(long)]
1436    list_markets: bool,
1437
1438    /// List tags (Polymarket only).
1439    #[arg(long)]
1440    list_tags: bool,
1441
1442    /// Category filter (Kalshi list endpoints, and local CSV search when --search is used).
1443    #[arg(long)]
1444    category: Option<String>,
1445
1446    /// Case-insensitive literal substring match (titles/tickers/slugs).
1447    #[arg(long, alias = "query")]
1448    search: Option<String>,
1449
1450    /// Optional country filter for local CSV search (v1: US only).
1451    #[arg(long)]
1452    country: Option<String>,
1453
1454    /// Minimum market volume in USD (local CSV search).
1455    #[arg(long = "min-volume")]
1456    min_volume: Option<f64>,
1457
1458    /// Return top N markets after ranking (local CSV search).
1459    #[arg(long)]
1460    top: Option<usize>,
1461
1462    /// Ranking for local CSV search output.
1463    /// Options: relevance, volume, delta_prob, delta_yes_price, delta_volume.
1464    #[arg(long = "sort-by", default_value = "relevance")]
1465    sort_by: String,
1466    /// Query profile: auto | macro | broad.
1467    #[arg(long, default_value = "auto")]
1468    profile: String,
1469
1470    /// Optional policy file override.
1471    #[arg(long = "policy-file")]
1472    policy_file: Option<PathBuf>,
1473
1474    /// Policy mode: observe | assist | enforce.
1475    #[arg(long = "policy-mode", default_value = "observe")]
1476    policy_mode: String,
1477
1478    /// Only include markets that changed since the last sync (requires sync delta index).
1479    #[arg(long, default_value_t = false)]
1480    deltas_only: bool,
1481
1482    /// Minimum absolute probability move (percentage points) since last sync.
1483    /// Requires sync delta index.
1484    #[arg(long = "min-delta-pp")]
1485    min_delta_pp: Option<f64>,
1486
1487    /// Include compact ranking explanations in local CSV search output.
1488    #[arg(long, default_value_t = false)]
1489    explain: bool,
1490
1491    /// Upgrade CSV search results to live API prices (fresh bid/ask/volume).
1492    #[arg(long, default_value_t = false)]
1493    live: bool,
1494
1495    /// Include mention/speech-prediction markets (filtered by default).
1496    #[arg(long, default_value_t = false)]
1497    include_mentions: bool,
1498
1499    /// Include orderbook depth (heavier call; Polymarket orderbook supported).
1500    #[arg(long)]
1501    orderbook: bool,
1502
1503    /// Orderbook depth (levels).
1504    #[arg(long)]
1505    depth: Option<usize>,
1506
1507    /// Output format (currently: json).
1508    #[arg(long, default_value = "json")]
1509    format: String,
1510
1511    /// Write full JSON output to a file instead of stdout.
1512    #[arg(long)]
1513    out: Option<PathBuf>,
1514}
1515
1516#[derive(Subcommand, Debug)]
1517enum FinanceOddsAction {
1518    /// Sync prediction markets (Kalshi + Polymarket) to a local CSV cache.
1519    Sync(FinanceSyncArgs),
1520
1521    /// Print local cache paths for odds CSVs.
1522    Where(FinanceOddsWhereArgs),
1523}
1524
1525#[derive(clap::Args, Debug)]
1526struct FinanceOddsWhereArgs {
1527    /// Override cache directory (defaults to the same cache used by `eli finance sync`).
1528    #[arg(long)]
1529    cache_dir: Option<PathBuf>,
1530}
1531
1532#[derive(clap::Args, Debug)]
1533struct FinanceOptionsArgs {
1534    /// Underlying ticker (e.g. INTC).
1535    #[arg(long, visible_alias = "tickers")]
1536    ticker: String,
1537
1538    /// Expiration date (YYYY-MM-DD). If omitted, summary mode uses the first usable future expiry.
1539    #[arg(long)]
1540    expiry: Option<String>,
1541
1542    /// Target days to expiry. If set and --expiry is omitted, picks the closest listed expiry.
1543    #[arg(long = "target-dte")]
1544    target_dte: Option<i64>,
1545
1546    /// Filter: calls | puts | both (default: both).
1547    #[arg(long = "type", value_name = "calls|puts|both")]
1548    option_type: Option<String>,
1549
1550    /// Only return strikes within this percentage of the underlying (e.g. 10 = +/-10%).
1551    #[arg(long = "near-money")]
1552    near_money: Option<f64>,
1553
1554    /// Return summary metrics only (no full chain).
1555    #[arg(long)]
1556    summary: bool,
1557
1558    /// List available expirations only.
1559    #[arg(long)]
1560    expirations: bool,
1561
1562    /// Fetch ALL expirations and compute cross-expiry analytics.
1563    /// Dumps full chain to --out file, prints term structure summary to stdout.
1564    #[arg(long)]
1565    all: bool,
1566
1567    /// Data provider (yahoo | ibkr).
1568    #[arg(long, default_value = "yahoo")]
1569    provider: String,
1570
1571    /// Optional IBKR account code (e.g. U1234567). Used when --provider ibkr.
1572    #[arg(long)]
1573    ibkr_account: Option<String>,
1574
1575    /// Optional IBKR host override.
1576    #[arg(long)]
1577    ibkr_host: Option<String>,
1578
1579    /// Optional IBKR port override.
1580    #[arg(long)]
1581    ibkr_port: Option<u16>,
1582
1583    /// Optional IBKR client id override.
1584    #[arg(long)]
1585    ibkr_client_id: Option<i32>,
1586
1587    /// Optional IBKR market data type: 1 live, 2 frozen, 3 delayed, 4 delayed-frozen.
1588    #[arg(long)]
1589    ibkr_market_data_type: Option<i32>,
1590
1591    /// Output format (currently: json).
1592    #[arg(long, default_value = "json")]
1593    format: String,
1594
1595    /// Write full JSON output to a file instead of stdout.
1596    #[arg(long)]
1597    out: Option<PathBuf>,
1598}
1599
1600#[derive(clap::Args, Debug)]
1601struct FinanceSyncArgs {
1602    /// Sources to sync: kalshi, polymarket (comma-separated). Default: both.
1603    #[arg(long, value_delimiter = ',')]
1604    sources: Vec<String>,
1605
1606    /// Debug only: frontier-sample page cap per source. Hides coverage and is not a normal sync control.
1607    #[arg(long)]
1608    max_pages: Option<usize>,
1609
1610    /// Fail if pagination/coverage checks indicate incomplete source exhaustion.
1611    #[arg(long)]
1612    strict: bool,
1613
1614    /// Include sports markets/events in sync output (default: false).
1615    #[arg(long)]
1616    include_sports: bool,
1617
1618    /// Include Kalshi historical markets (archived/settled tier). Default: false.
1619    #[arg(long, hide = true)]
1620    include_historical: bool,
1621
1622    /// Fast refresh from Kalshi websocket ticker stream using cached baseline (no full re-pagination).
1623    #[arg(long)]
1624    stream_refresh: bool,
1625
1626    /// Breadth heartbeat in hours for stream refresh mode. If cached baseline is older, force strict REST anchor sync (default: 6).
1627    #[arg(long, hide = true)]
1628    refresh_heartbeat_hours: Option<u64>,
1629
1630    /// WebSocket listen window in seconds for stream refresh mode (default: 300).
1631    #[arg(long, hide = true)]
1632    stream_refresh_timeout_secs: Option<u64>,
1633
1634    /// Cache directory for CSV files (defaults to platform cache dir).
1635    #[arg(long)]
1636    cache_dir: Option<PathBuf>,
1637
1638    /// Output format (currently: json).
1639    #[arg(long, default_value = "json", hide = true)]
1640    format: String,
1641
1642    /// Emit full verbose payload on stdout (default is compact/token-efficient).
1643    #[arg(long, hide = true)]
1644    full: bool,
1645
1646    /// Optional policy file override.
1647    #[arg(long = "policy-file", hide = true)]
1648    policy_file: Option<PathBuf>,
1649
1650    /// Policy mode: observe | assist | enforce.
1651    #[arg(long = "policy-mode", default_value = "observe", hide = true)]
1652    policy_mode: String,
1653
1654    /// Write full JSON output to a file instead of stdout.
1655    #[arg(long)]
1656    out: Option<PathBuf>,
1657}
1658
1659#[derive(clap::Args, Debug)]
1660struct FinancePaperArgs {
1661    /// Command: trade | positions | trades | mark | reset
1662    #[arg(long, value_enum, default_value = "trade")]
1663    command: FinancePaperCommandArg,
1664
1665    /// Execution mode (v1: simulated local fills)
1666    #[arg(long, value_enum, default_value = "simulated")]
1667    mode: FinancePaperModeArg,
1668
1669    /// Paper account name.
1670    #[arg(long, default_value = "default")]
1671    account: String,
1672
1673    /// Provider for trade/mark pricing (kalshi|polymarket).
1674    #[arg(long)]
1675    provider: Option<String>,
1676
1677    /// Market ticker or market id (required for --command trade).
1678    #[arg(long)]
1679    market: Option<String>,
1680
1681    /// Side (yes|no) for --command trade.
1682    #[arg(long, value_enum)]
1683    side: Option<FinancePaperSideArg>,
1684
1685    /// Order action (buy|sell) for --command trade.
1686    #[arg(long, value_enum)]
1687    action: Option<FinancePaperOrderActionArg>,
1688
1689    /// Quantity/contracts for --command trade.
1690    #[arg(long)]
1691    qty: Option<f64>,
1692
1693    /// Optional manual fill price in probability units [0,1]. If omitted, uses live midpoint.
1694    #[arg(long)]
1695    price: Option<f64>,
1696
1697    /// Starting paper cash for account init/reset (default: 10000).
1698    #[arg(long)]
1699    starting_cash: Option<f64>,
1700
1701    /// Trade history limit for --command trades (default: 50).
1702    #[arg(long)]
1703    limit: Option<usize>,
1704
1705    /// Optional custom cache dir or full state file path.
1706    #[arg(long)]
1707    cache_dir: Option<PathBuf>,
1708
1709    /// Output format (json only).
1710    #[arg(long, default_value = "json")]
1711    format: String,
1712
1713    /// Write full JSON output to a file instead of stdout.
1714    #[arg(long)]
1715    out: Option<PathBuf>,
1716}
1717
1718#[derive(clap::Args, Debug)]
1719struct FinanceFilingsArgs {
1720    /// Ticker to fetch filings for.
1721    #[arg(long, visible_alias = "tickers")]
1722    ticker: String,
1723
1724    /// Form types to include (comma-separated), e.g. 8-K,10-K,10-Q. Defaults to 8-K,10-K,10-Q.
1725    #[arg(long, value_delimiter = ',')]
1726    forms: Vec<String>,
1727
1728    /// Max number of filings to return.
1729    #[arg(long, default_value_t = 5)]
1730    limit: usize,
1731
1732    /// Do not download filing files; return SEC metadata and URLs only.
1733    #[arg(long)]
1734    no_download: bool,
1735
1736    /// Download every document listed in each filing index, not just the primary document.
1737    #[arg(long)]
1738    download_all: bool,
1739
1740    /// Deprecated alias for the old text mode. Now downloads raw filing files without parsing.
1741    #[arg(long)]
1742    include_text: bool,
1743
1744    /// Deprecated. Filings are downloaded raw; no inline excerpt is generated.
1745    #[arg(long)]
1746    max_chars: Option<usize>,
1747
1748    /// SEC User-Agent override with contact email, e.g. "eli-cli (mailto:me@example.com)".
1749    #[arg(long)]
1750    user_agent: Option<String>,
1751
1752    /// Override cache directory (defaults to Eli's cache dir).
1753    #[arg(long)]
1754    cache_dir: Option<PathBuf>,
1755
1756    /// Output format (currently: json).
1757    #[arg(long, default_value = "json")]
1758    format: String,
1759
1760    /// Write full JSON output to a file instead of stdout.
1761    #[arg(long)]
1762    out: Option<PathBuf>,
1763}
1764
1765#[derive(clap::Args, Debug)]
1766struct FinanceTimeseriesArgs {
1767    /// Preset ticker group (macro, forex_majors, yield_curve, liquidity, crypto).
1768    /// Expands to predefined tickers with default range/granularity. User flags override defaults.
1769    #[arg(long)]
1770    preset: Option<String>,
1771
1772    /// Tickers to fetch (repeatable or comma-separated).
1773    #[arg(long, visible_alias = "ticker", value_delimiter = ',')]
1774    tickers: Vec<String>,
1775
1776    /// Optional file with tickers (one per line).
1777    #[arg(long)]
1778    tickers_file: Option<PathBuf>,
1779
1780    /// Lookback range (e.g. 1d, 12mo, 5y).
1781    #[arg(long, default_value = "1y")]
1782    range: String,
1783
1784    /// Candle size / sampling granularity (e.g. 10m, 1h, 1d, 1w, 1mo).
1785    #[arg(long, default_value = "1d")]
1786    granularity: String,
1787
1788    /// Explicit window start (RFC3339 or YYYY-MM-DD). Must be used with --end.
1789    #[arg(long)]
1790    start: Option<String>,
1791
1792    /// Explicit window end (RFC3339 or YYYY-MM-DD). Must be used with --start.
1793    #[arg(long)]
1794    end: Option<String>,
1795
1796    /// End timestamp for the window (RFC3339). If you pass YYYY-MM-DD, it's treated as end-of-day UTC. Defaults to now (UTC).
1797    #[arg(long)]
1798    as_of: Option<String>,
1799
1800    /// Data provider (auto | yahoo | fred | ibkr | pyth | binance). "auto" routes by ticker prefix: PYTH:/CLEV:/IBKR:/BN:/FRED: → matching provider; numeric (Polymarket) and KX*-prefix (Kalshi) auto-detected; bare names → Yahoo, with FRED fallback for macro-style IDs.
1801    #[arg(long, default_value = "auto")]
1802    provider: String,
1803
1804    /// Optional IBKR account code (e.g. U1234567). Used when --provider ibkr.
1805    #[arg(long)]
1806    ibkr_account: Option<String>,
1807
1808    /// Optional IBKR host override.
1809    #[arg(long)]
1810    ibkr_host: Option<String>,
1811
1812    /// Optional IBKR port override.
1813    #[arg(long)]
1814    ibkr_port: Option<u16>,
1815
1816    /// Optional IBKR client id override.
1817    #[arg(long)]
1818    ibkr_client_id: Option<i32>,
1819
1820    /// Optional IBKR market data type: 1 live, 2 frozen, 3 delayed, 4 delayed-frozen.
1821    #[arg(long)]
1822    ibkr_market_data_type: Option<i32>,
1823
1824    /// Optional explicit prediction market provider to include as a timeseries series (kalshi | polymarket).
1825    #[arg(long)]
1826    odds_provider: Option<String>,
1827
1828    /// Optional prediction market identifier. Kalshi: market ticker. Polymarket: market ID or slug.
1829    #[arg(long)]
1830    odds_market: Option<String>,
1831
1832    /// Prediction market side to include for --odds-market (yes | no). Defaults to yes.
1833    #[arg(long, default_value = "yes")]
1834    odds_side: String,
1835
1836    /// Safety cap for points per ticker.
1837    #[arg(long)]
1838    max_points_per_ticker: Option<usize>,
1839
1840    /// Override cache directory (defaults to Eli's cache dir).
1841    #[arg(long)]
1842    cache_dir: Option<PathBuf>,
1843
1844    /// Output format (currently: json).
1845    #[arg(long, default_value = "json")]
1846    format: String,
1847
1848    /// Write full JSON output to a file instead of stdout.
1849    #[arg(long)]
1850    out: Option<PathBuf>,
1851}
1852
1853#[derive(clap::Args, Debug)]
1854struct FinanceIbkrArgs {
1855    /// IBKR command surface.
1856    #[arg(long, value_enum)]
1857    command: FinanceIbkrCommandArg,
1858
1859    /// Optional IBKR account code (e.g. U1234567).
1860    #[arg(long)]
1861    account: Option<String>,
1862
1863    /// Optional IBKR host override.
1864    #[arg(long)]
1865    host: Option<String>,
1866
1867    /// Optional IBKR port override.
1868    #[arg(long)]
1869    port: Option<u16>,
1870
1871    /// Optional IBKR client id override.
1872    #[arg(long)]
1873    client_id: Option<i32>,
1874
1875    /// Optional IBKR market data type: 1 live, 2 frozen, 3 delayed, 4 delayed-frozen.
1876    #[arg(long)]
1877    market_data_type: Option<i32>,
1878
1879    /// Optional timeout in seconds for the bridge request.
1880    #[arg(long)]
1881    timeout_secs: Option<u64>,
1882
1883    /// Tickers for snapshot / timeseries commands (repeatable or comma-separated).
1884    #[arg(long, value_delimiter = ',')]
1885    tickers: Vec<String>,
1886
1887    /// Range for timeseries requests (e.g. 1d, 1mo, 1y).
1888    #[arg(long, default_value = "1mo")]
1889    range: String,
1890
1891    /// Granularity for timeseries requests (e.g. 1min, 5min, 1h, 1d).
1892    #[arg(long, default_value = "1day")]
1893    granularity: String,
1894
1895    /// Contract symbol for order placement.
1896    #[arg(long)]
1897    symbol: Option<String>,
1898
1899    /// Contract security type for orders (default: STK).
1900    #[arg(long)]
1901    sec_type: Option<String>,
1902
1903    /// Contract exchange (default: SMART).
1904    #[arg(long)]
1905    exchange: Option<String>,
1906
1907    /// Contract primary exchange.
1908    #[arg(long)]
1909    primary_exchange: Option<String>,
1910
1911    /// Contract currency (default: USD).
1912    #[arg(long)]
1913    currency: Option<String>,
1914
1915    /// Contract expiry / contract month (e.g. 20260320).
1916    #[arg(long)]
1917    expiry: Option<String>,
1918
1919    /// Contract strike price.
1920    #[arg(long)]
1921    strike: Option<f64>,
1922
1923    /// Contract right (C/P).
1924    #[arg(long)]
1925    right: Option<String>,
1926
1927    /// Contract multiplier.
1928    #[arg(long)]
1929    multiplier: Option<String>,
1930
1931    /// Trading class.
1932    #[arg(long)]
1933    trading_class: Option<String>,
1934
1935    /// Order side for place-order (BUY or SELL).
1936    #[arg(long)]
1937    side: Option<String>,
1938
1939    /// Order type for place-order (MKT, LMT, STP, STP LMT).
1940    #[arg(long)]
1941    order_type: Option<String>,
1942
1943    /// Quantity for place-order.
1944    #[arg(long)]
1945    quantity: Option<f64>,
1946
1947    /// Limit price for limit orders.
1948    #[arg(long)]
1949    limit_price: Option<f64>,
1950
1951    /// Stop price for stop orders.
1952    #[arg(long)]
1953    stop_price: Option<f64>,
1954
1955    /// Time in force (default: DAY).
1956    #[arg(long)]
1957    tif: Option<String>,
1958
1959    /// Order id for cancel-order.
1960    #[arg(long)]
1961    order_id: Option<i32>,
1962
1963    /// Optional account summary tag filter.
1964    #[arg(long)]
1965    tags: Option<String>,
1966
1967    /// Output format (json only).
1968    #[arg(long, default_value = "json")]
1969    format: String,
1970
1971    /// Write full JSON output to a file instead of stdout.
1972    #[arg(long)]
1973    out: Option<PathBuf>,
1974}