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