Skip to main content

torvyn_cli/
cli.rs

1//! clap derive definitions for the Torvyn CLI.
2//!
3//! This module defines the complete argument schema for the `torvyn` binary.
4//! Every subcommand, flag, and argument is defined here with embedded help text.
5
6use clap::{Parser, Subcommand, ValueEnum};
7use std::path::PathBuf;
8
9// ---------------------------------------------------------------------------
10// Top-level CLI
11// ---------------------------------------------------------------------------
12
13/// Torvyn — Ownership-aware reactive streaming runtime
14///
15/// Build, validate, run, trace, benchmark, and package streaming components.
16///
17/// Getting started? Try: torvyn init my-first-pipeline --template full-pipeline
18#[derive(Parser, Debug)]
19#[command(name = "torvyn", version, about, long_about = None)]
20#[command(propagate_version = true)]
21#[command(
22    after_help = "Getting started? Try: torvyn init my-first-pipeline --template full-pipeline"
23)]
24pub struct Cli {
25    /// Global options available to all subcommands.
26    #[command(flatten)]
27    pub global: GlobalOpts,
28
29    /// The subcommand to execute.
30    #[command(subcommand)]
31    pub command: Command,
32}
33
34// ---------------------------------------------------------------------------
35// Global options
36// ---------------------------------------------------------------------------
37
38/// Global options applied to every subcommand.
39///
40/// ## Invariants
41/// - `verbose` and `quiet` are mutually exclusive (enforced by clap `conflicts_with`).
42/// - `format` defaults to `OutputFormat::Human`.
43/// - `color` defaults to `ColorChoice::Auto`.
44#[derive(Parser, Debug, Clone)]
45pub struct GlobalOpts {
46    /// Increase output verbosity (show debug-level messages).
47    #[arg(long, short = 'v', global = true, conflicts_with = "quiet")]
48    pub verbose: bool,
49
50    /// Suppress non-essential output (errors only).
51    #[arg(long, short = 'q', global = true, conflicts_with = "verbose")]
52    pub quiet: bool,
53
54    /// Output format for command results.
55    #[arg(long, global = true, value_enum, default_value_t = OutputFormat::Human)]
56    pub format: OutputFormat,
57
58    /// Color output control.
59    #[arg(long, global = true, value_enum, default_value_t = ColorChoice::Auto)]
60    pub color: ColorChoice,
61}
62
63// ---------------------------------------------------------------------------
64// Enums
65// ---------------------------------------------------------------------------
66
67/// Output format for CLI results.
68#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
69#[serde(rename_all = "lowercase")]
70pub enum OutputFormat {
71    /// Styled terminal output with colors, tables, and progress indicators.
72    Human,
73    /// Machine-readable JSON output to stdout.
74    Json,
75}
76
77/// Color output control.
78#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq)]
79pub enum ColorChoice {
80    /// Auto-detect terminal color support.
81    Auto,
82    /// Always use color output.
83    Always,
84    /// Never use color output.
85    Never,
86}
87
88/// Project template type for `torvyn init`.
89#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
90#[serde(rename_all = "lowercase")]
91pub enum TemplateKind {
92    /// Data producer (no input, one output).
93    Source,
94    /// Data consumer (one input, no output).
95    Sink,
96    /// Stateless data transformer.
97    Transform,
98    /// Content filter/guard.
99    Filter,
100    /// Multi-output router.
101    Router,
102    /// Stateful windowed aggregator.
103    Aggregator,
104    /// Complete multi-component pipeline with source + transform + sink.
105    FullPipeline,
106    /// Minimal skeleton for experienced users.
107    Empty,
108}
109
110impl TemplateKind {
111    /// Returns a human-readable description of this template.
112    #[allow(dead_code)]
113    pub fn description(&self) -> &'static str {
114        match self {
115            Self::Source => "Data producer (no input, one output)",
116            Self::Sink => "Data consumer (one input, no output)",
117            Self::Transform => "Stateless data transformer",
118            Self::Filter => "Content filter/guard",
119            Self::Router => "Multi-output router",
120            Self::Aggregator => "Stateful windowed aggregator",
121            Self::FullPipeline => "Complete pipeline with source + transform + sink",
122            Self::Empty => "Minimal skeleton for experienced users",
123        }
124    }
125}
126
127/// Implementation language for `torvyn init`.
128#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
129#[serde(rename_all = "lowercase")]
130pub enum Language {
131    /// Rust (primary, fully supported).
132    Rust,
133    /// Go (via TinyGo, limited support).
134    Go,
135    /// Python (via componentize-py, limited support).
136    Python,
137    /// Zig (experimental).
138    Zig,
139}
140
141/// Shell type for shell completion generation.
142#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq)]
143pub enum ShellKind {
144    /// Bash shell completions.
145    Bash,
146    /// Zsh shell completions.
147    Zsh,
148    /// Fish shell completions.
149    Fish,
150    /// PowerShell completions.
151    #[value(name = "powershell")]
152    PowerShell,
153}
154
155/// Sections to show in `torvyn inspect`.
156#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
157#[serde(rename_all = "lowercase")]
158pub enum InspectSection {
159    /// Show all available information.
160    All,
161    /// Show exported and imported interfaces.
162    Interfaces,
163    /// Show required capabilities.
164    Capabilities,
165    /// Show component metadata (version, authors, etc.).
166    Metadata,
167    /// Show binary size breakdown.
168    Size,
169    /// Show WIT contract definitions.
170    Contracts,
171    /// Show embedded benchmark results.
172    Benchmarks,
173}
174
175/// Report format for `torvyn bench`.
176#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
177#[serde(rename_all = "lowercase")]
178pub enum ReportFormat {
179    /// Styled terminal table.
180    Pretty,
181    /// JSON report.
182    Json,
183    /// CSV report.
184    Csv,
185    /// Markdown report.
186    Markdown,
187}
188
189/// Trace output format for `torvyn trace`.
190#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
191#[serde(rename_all = "lowercase")]
192pub enum TraceFormat {
193    /// Pretty-printed tree trace.
194    Pretty,
195    /// JSON trace spans.
196    Json,
197    /// OpenTelemetry Protocol export.
198    Otlp,
199}
200
201// ---------------------------------------------------------------------------
202// Subcommands
203// ---------------------------------------------------------------------------
204
205/// All available subcommands for the `torvyn` binary.
206#[derive(Subcommand, Debug)]
207pub enum Command {
208    /// Create a new Torvyn project.
209    ///
210    /// Scaffolds a complete project with WIT contracts, implementation stubs,
211    /// a Torvyn.toml manifest, and build configuration. The generated project
212    /// compiles and runs out of the box.
213    Init(InitArgs),
214
215    /// Validate contracts, manifest, and project structure.
216    ///
217    /// Performs static analysis: parses WIT contracts, validates the manifest
218    /// schema, resolves references, and checks capability declarations.
219    Check(CheckArgs),
220
221    /// Verify component composition compatibility.
222    ///
223    /// Given a pipeline configuration, verifies that all component interfaces
224    /// are compatible and the topology is valid (DAG, connected, role-consistent).
225    Link(LinkArgs),
226
227    /// Execute a pipeline locally.
228    ///
229    /// Instantiates the Torvyn host runtime, loads components, and runs
230    /// the pipeline. Displays element count, errors, and completion status.
231    Run(RunArgs),
232
233    /// Run with full diagnostic tracing.
234    ///
235    /// Like `run` but with full tracing enabled. Outputs flow timeline
236    /// showing per-stage latency, resource transfers, backpressure events.
237    Trace(TraceArgs),
238
239    /// Benchmark a pipeline.
240    ///
241    /// Runs the pipeline under sustained load with warmup, then produces
242    /// a report with p50/p95/p99/p99.9 latency, throughput, copy count,
243    /// memory, and resource utilization.
244    Bench(BenchArgs),
245
246    /// Package as OCI artifact.
247    ///
248    /// Assembles compiled components, contracts, and metadata into a
249    /// distributable artifact.
250    Pack(PackArgs),
251
252    /// Publish to a registry.
253    ///
254    /// Pushes a packaged artifact to a registry. For Phase 0: local
255    /// directory registry only.
256    Publish(PublishArgs),
257
258    /// Inspect a component or artifact.
259    ///
260    /// Displays metadata, interfaces, capabilities, and size information
261    /// for a compiled .wasm file or packaged artifact.
262    Inspect(InspectArgs),
263
264    /// Check development environment.
265    ///
266    /// Verifies required tools, correct versions, and common misconfigurations.
267    /// Run `torvyn doctor --fix` to attempt automatic repair.
268    Doctor(DoctorArgs),
269
270    /// Generate shell completions.
271    ///
272    /// Prints a completion script to stdout for the specified shell.
273    /// Example: `torvyn completions bash > ~/.bash_completion.d/torvyn`
274    Completions(CompletionsArgs),
275}
276
277// ---------------------------------------------------------------------------
278// Per-command argument structs
279// ---------------------------------------------------------------------------
280
281/// Arguments for `torvyn init`.
282#[derive(Parser, Debug)]
283pub struct InitArgs {
284    /// Directory name and project name.
285    /// If omitted, uses the current directory name.
286    pub project_name: Option<String>,
287
288    /// Project template to use.
289    #[arg(long, short = 't', value_enum, default_value_t = TemplateKind::Transform)]
290    pub template: TemplateKind,
291
292    /// Implementation language.
293    #[arg(long, short = 'l', value_enum, default_value_t = Language::Rust)]
294    pub language: Language,
295
296    /// Skip git repository initialization.
297    #[arg(long)]
298    pub no_git: bool,
299
300    /// Skip example implementation, generate contract stubs only.
301    #[arg(long)]
302    pub no_example: bool,
303
304    /// Torvyn contract version to target.
305    #[arg(long, default_value = "0.1.0")]
306    pub contract_version: String,
307
308    /// Overwrite existing directory contents.
309    #[arg(long)]
310    pub force: bool,
311}
312
313/// Arguments for `torvyn check`.
314#[derive(Parser, Debug)]
315pub struct CheckArgs {
316    /// Path to Torvyn.toml.
317    #[arg(long, default_value = "./Torvyn.toml")]
318    pub manifest: PathBuf,
319
320    /// Treat warnings as errors.
321    #[arg(long)]
322    pub strict: bool,
323}
324
325/// Arguments for `torvyn link`.
326#[derive(Parser, Debug)]
327pub struct LinkArgs {
328    /// Path to Torvyn.toml with flow definition.
329    #[arg(long, default_value = "./Torvyn.toml")]
330    pub manifest: PathBuf,
331
332    /// Specific flow to check (default: all flows).
333    #[arg(long)]
334    pub flow: Option<String>,
335
336    /// Directory containing compiled .wasm components.
337    #[arg(long)]
338    pub components: Option<PathBuf>,
339
340    /// Show full interface compatibility details.
341    #[arg(long)]
342    pub detail: bool,
343}
344
345/// Arguments for `torvyn run`.
346#[derive(Parser, Debug)]
347pub struct RunArgs {
348    /// Path to Torvyn.toml.
349    #[arg(long, default_value = "./Torvyn.toml")]
350    pub manifest: PathBuf,
351
352    /// Flow to execute (default: first defined flow).
353    #[arg(long)]
354    pub flow: Option<String>,
355
356    /// Override source input (file path, stdin, or generator).
357    #[arg(long)]
358    pub input: Option<String>,
359
360    /// Override sink output (file path, stdout).
361    #[arg(long)]
362    pub output: Option<String>,
363
364    /// Process at most N elements then exit.
365    #[arg(long)]
366    pub limit: Option<u64>,
367
368    /// Maximum execution time (e.g., 30s, 5m).
369    #[arg(long)]
370    pub timeout: Option<String>,
371
372    /// Override component configuration values.
373    #[arg(long, value_name = "KEY=VALUE")]
374    pub config: Vec<String>,
375
376    /// Log verbosity.
377    #[arg(long, default_value = "info")]
378    pub log_level: String,
379}
380
381/// Arguments for `torvyn trace`.
382#[derive(Parser, Debug)]
383pub struct TraceArgs {
384    /// Path to Torvyn.toml.
385    #[arg(long, default_value = "./Torvyn.toml")]
386    pub manifest: PathBuf,
387
388    /// Flow to trace (default: first defined flow).
389    #[arg(long)]
390    pub flow: Option<String>,
391
392    /// Override source input.
393    #[arg(long)]
394    pub input: Option<String>,
395
396    /// Trace at most N elements.
397    #[arg(long)]
398    pub limit: Option<u64>,
399
400    /// Write trace data to file (default: stdout).
401    #[arg(long)]
402    pub output_trace: Option<PathBuf>,
403
404    /// Trace output format.
405    #[arg(long, value_enum, default_value_t = TraceFormat::Pretty)]
406    pub trace_format: TraceFormat,
407
408    /// Include buffer content snapshots in trace.
409    #[arg(long)]
410    pub show_buffers: bool,
411
412    /// Highlight backpressure events.
413    #[arg(long)]
414    pub show_backpressure: bool,
415}
416
417/// Arguments for `torvyn bench`.
418#[derive(Parser, Debug)]
419pub struct BenchArgs {
420    /// Path to Torvyn.toml.
421    #[arg(long, default_value = "./Torvyn.toml")]
422    pub manifest: PathBuf,
423
424    /// Flow to benchmark (default: first defined flow).
425    #[arg(long)]
426    pub flow: Option<String>,
427
428    /// Benchmark duration (default: 10s).
429    #[arg(long, default_value = "10s")]
430    pub duration: String,
431
432    /// Warmup period excluded from results (default: 2s).
433    #[arg(long, default_value = "2s")]
434    pub warmup: String,
435
436    /// Override source input (for reproducible benchmarks).
437    #[arg(long)]
438    pub input: Option<String>,
439
440    /// Write report to file (default: stdout).
441    #[arg(long)]
442    pub report: Option<PathBuf>,
443
444    /// Report format.
445    #[arg(long, value_enum, default_value_t = ReportFormat::Pretty)]
446    pub report_format: ReportFormat,
447
448    /// Compare against a previous benchmark result.
449    #[arg(long)]
450    pub compare: Option<PathBuf>,
451
452    /// Save result as a named baseline for future comparison.
453    #[arg(long)]
454    pub baseline: Option<String>,
455}
456
457/// Arguments for `torvyn pack`.
458#[derive(Parser, Debug)]
459pub struct PackArgs {
460    /// Path to Torvyn.toml.
461    #[arg(long, default_value = "./Torvyn.toml")]
462    pub manifest: PathBuf,
463
464    /// Specific component to pack (default: all in project).
465    #[arg(long)]
466    pub component: Option<String>,
467
468    /// Output artifact path (default: .torvyn/artifacts/).
469    #[arg(long)]
470    pub output: Option<PathBuf>,
471
472    /// OCI tag (default: derived from manifest version).
473    #[arg(long)]
474    pub tag: Option<String>,
475
476    /// Include source WIT contracts in artifact metadata.
477    #[arg(long)]
478    pub include_source: bool,
479
480    /// Sign artifact (requires signing key configuration).
481    #[arg(long)]
482    pub sign: bool,
483}
484
485/// Arguments for `torvyn publish`.
486#[derive(Parser, Debug)]
487pub struct PublishArgs {
488    /// Path to packed artifact (default: latest in .torvyn/artifacts/).
489    #[arg(long)]
490    pub artifact: Option<PathBuf>,
491
492    /// Target registry URL (default: from config).
493    #[arg(long)]
494    pub registry: Option<String>,
495
496    /// Override tag.
497    #[arg(long)]
498    pub tag: Option<String>,
499
500    /// Validate publish without actually pushing.
501    #[arg(long)]
502    pub dry_run: bool,
503
504    /// Overwrite existing tag.
505    #[arg(long)]
506    pub force: bool,
507}
508
509/// Arguments for `torvyn inspect`.
510#[derive(Parser, Debug)]
511pub struct InspectArgs {
512    /// Path to .wasm file, OCI artifact, or registry reference.
513    pub target: String,
514
515    /// What section to show.
516    #[arg(long, value_enum, default_value_t = InspectSection::All)]
517    pub show: InspectSection,
518}
519
520/// Arguments for `torvyn doctor`.
521#[derive(Parser, Debug)]
522pub struct DoctorArgs {
523    /// Attempt to fix common issues automatically.
524    #[arg(long)]
525    pub fix: bool,
526}
527
528/// Arguments for `torvyn completions`.
529#[derive(Parser, Debug)]
530pub struct CompletionsArgs {
531    /// Shell to generate completions for.
532    pub shell: ShellKind,
533}