Skip to main content

apr_cli/
commands_enum.rs

1
2/// Output format for `apr code` non-interactive mode (PMAT-CODE-OUTPUT-FORMAT-001).
3/// Mirrors Claude Code's `claude -p --output-format <fmt>` parity row.
4#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum, Default)]
5pub enum CodeOutputFormat {
6    /// Plain assistant text on stdout (default; existing behavior).
7    #[default]
8    Text,
9    /// Structured JSON envelope: `{type:"result", subtype:"success", result, session_id, duration_ms}`.
10    Json,
11}
12
13/// Input format for `apr code` non-interactive mode (PMAT-CODE-INPUT-FORMAT-001).
14/// `--input-format json` reads `{"role":"user","content":"..."}` from stdin instead
15/// of treating stdin as raw prompt text.
16#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum, Default)]
17pub enum CodeInputFormat {
18    /// Raw prompt text from positional args or stdin (default; existing behavior).
19    #[default]
20    Text,
21    /// JSON message envelope on stdin: `{"role":"user","content":"..."}`.
22    Json,
23}
24
25#[derive(Subcommand, Debug)]
26pub enum Commands {
27    /// Run model directly (auto-download, cache, execute)
28    Run {
29        /// Model source: local path, hf://org/repo, or URL
30        #[arg(value_name = "SOURCE")]
31        source: String,
32        /// Text prompt (positional): `apr run model.gguf "What is 2+2?"`
33        #[arg(value_name = "PROMPT")]
34        positional_prompt: Option<String>,
35        /// Input file (audio, text, etc.)
36        #[arg(short, long)]
37        input: Option<PathBuf>,
38        /// Text prompt for generation (for LLM models)
39        #[arg(short, long)]
40        prompt: Option<String>,
41        /// Maximum tokens to generate (default: 32)
42        #[arg(short = 'n', long, default_value = "32")]
43        max_tokens: usize,
44        /// Enable streaming output
45        #[arg(long)]
46        stream: bool,
47        /// Language code (for ASR models)
48        #[arg(short, long)]
49        language: Option<String>,
50        /// Task (transcribe, translate)
51        #[arg(short, long)]
52        task: Option<String>,
53        /// Output format (text, json, srt, vtt)
54        #[arg(short = 'f', long, default_value = "text")]
55        format: String,
56        /// Disable GPU acceleration (force CPU-only inference)
57        #[arg(long, alias = "cpu", conflicts_with = "gpu")]
58        no_gpu: bool,
59        /// Force GPU acceleration
60        #[arg(long, conflicts_with = "no_gpu")]
61        gpu: bool,
62        /// Offline mode: block all network access (Sovereign AI compliance)
63        #[arg(long)]
64        offline: bool,
65        /// Benchmark mode: output performance metrics (tok/s, latency)
66        #[arg(long)]
67        benchmark: bool,
68        /// Enable inference tracing (APR-TRACE-001)
69        #[arg(long)]
70        trace: bool,
71        /// Trace specific steps only (comma-separated)
72        #[arg(long, value_delimiter = ',')]
73        trace_steps: Option<Vec<String>>,
74        /// Verbose tracing (show tensor values)
75        #[arg(long)]
76        trace_verbose: bool,
77        /// Save trace output to JSON file
78        #[arg(long, value_name = "FILE")]
79        trace_output: Option<PathBuf>,
80        /// Trace detail level (none, basic, layer, payload, chrome)
81        /// "chrome" outputs chrome://tracing JSON integrating layer trace + brick profile.
82        /// F-CLIPARITY-01 / PMAT-386 / paiml/aprender#574
83        #[arg(long, value_name = "LEVEL", default_value = "basic")]
84        trace_level: String,
85        /// Shorthand for --trace --trace-level payload (tensor value inspection)
86        #[arg(long)]
87        trace_payload: bool,
88        /// Enable inline Roofline profiling (PMAT-SHOWCASE-METHODOLOGY-001)
89        #[arg(long)]
90        profile: bool,
91        /// Apply chat template for Instruct models (GAP-UX-001)
92        ///
93        /// Wraps prompt in ChatML format for Qwen2, LLaMA, Mistral Instruct models.
94        /// Format: <|im_start|>user\n{prompt}<|im_end|>\n<|im_start|>assistant\n
95        #[arg(long)]
96        chat: bool,
97        /// Sampling temperature (0.0 = greedy, default: 0.0)
98        #[arg(long, default_value = "0.0")]
99        temperature: f32,
100        /// Top-k sampling (default: 1 = greedy)
101        #[arg(long, default_value = "1")]
102        top_k: usize,
103        /// Top-p nucleus sampling (0.0 = disabled). When set with --top-k, applies top-k first then top-p.
104        /// F-CLIPARITY-01 / PMAT-381 / paiml/aprender#569
105        #[arg(long)]
106        top_p: Option<f32>,
107        /// RNG seed for deterministic sampling (default: 299792458, matching Candle)
108        /// F-CLIPARITY-01 / PMAT-382 / paiml/aprender#570
109        #[arg(long, default_value = "299792458")]
110        seed: u64,
111        /// Repetition penalty (1.0 = no penalty, >1.0 penalizes repeats)
112        /// F-CLIPARITY-01 / PMAT-383 / paiml/aprender#571
113        #[arg(long, default_value = "1.0")]
114        repeat_penalty: f32,
115        /// Context window for repetition penalty (number of recent tokens to check)
116        /// F-CLIPARITY-01 / PMAT-384 / paiml/aprender#571
117        #[arg(long, default_value = "64")]
118        repeat_last_n: usize,
119        /// Process prompt tokens one-by-one instead of batched prefill.
120        /// Useful for debugging prefill correctness (comparing per-token attention).
121        /// F-CLIPARITY-01 / PMAT-385 / paiml/aprender#572
122        #[arg(long)]
123        split_prompt: bool,
124        /// Batch mode: read prompts from JSONL, output results as JSONL.
125        /// Model loads once, processes all prompts sequentially.
126        /// Each input line: {"prompt": "...", "task_id": "..."}
127        /// Chat template is applied automatically.
128        #[arg(long, value_name = "FILE")]
129        batch_jsonl: Option<PathBuf>,
130        /// Show verbose output (model loading, backend info)
131        #[arg(short, long)]
132        verbose: bool,
133        /// PMAT-488: Compute backend override (cuda, cpu, wgpu)
134        #[arg(long, value_name = "BACKEND")]
135        backend: Option<String>,
136    },
137    /// Inference server (plan/run)
138    Serve {
139        #[command(subcommand)]
140        command: ServeCommands,
141    },
142    /// Inspect model metadata, vocab, and structure
143    Inspect {
144        /// Path to .apr model file
145        #[arg(value_name = "FILE")]
146        file: PathBuf,
147        /// Show vocabulary details
148        #[arg(long)]
149        vocab: bool,
150        /// Show filter/security details
151        #[arg(long)]
152        filters: bool,
153        /// Show weight statistics
154        #[arg(long)]
155        weights: bool,
156        /// Output as JSON
157        #[arg(long)]
158        json: bool,
159    },
160    /// Simple debugging output ("drama" mode available)
161    Debug {
162        /// Path to .apr model file
163        #[arg(value_name = "FILE")]
164        file: PathBuf,
165        /// Theatrical "drama" mode output
166        #[arg(long)]
167        drama: bool,
168        /// Show hex dump
169        #[arg(long)]
170        hex: bool,
171        /// Extract ASCII strings
172        #[arg(long)]
173        strings: bool,
174        /// Limit output lines
175        #[arg(long, default_value = "256")]
176        limit: usize,
177    },
178    /// Validate model integrity and quality
179    Validate {
180        /// Path to .apr model file
181        #[arg(value_name = "FILE")]
182        file: PathBuf,
183        /// Show 100-point quality assessment
184        #[arg(long)]
185        quality: bool,
186        /// Strict validation (fail on warnings)
187        #[arg(long)]
188        strict: bool,
189        /// Minimum score to pass (0-100)
190        #[arg(long)]
191        min_score: Option<u8>,
192    },
193    /// Validate a publish manifest (FALSIFY-PM-001..006).
194    ///
195    /// Contract: `contracts/publish-manifest-v1.yaml`
196    /// Spec:     SPEC-SHIP-TWO-001 §12.3 AC-EX-004
197    ValidateManifest {
198        /// Path to manifest YAML
199        #[arg(value_name = "MANIFEST")]
200        file: PathBuf,
201        /// Optional local .apr artifact to discharge FALSIFY-PM-002 (sha256 match)
202        #[arg(long, value_name = "APR_FILE")]
203        artifact: Option<PathBuf>,
204        /// Discharge FALSIFY-PM-003 via network: HTTP HEAD + streaming sha256.
205        /// Default is DEFERRED (offline-safe). Ignored when --offline is set.
206        /// Closes F-PUBLISH-EXTRA-001::dogfood_ex05 (no Python in ex-05).
207        #[arg(long)]
208        live: bool,
209    },
210    /// Compare two models
211    Diff {
212        /// First model file
213        #[arg(value_name = "FILE1")]
214        file1: PathBuf,
215        /// Second model file
216        #[arg(value_name = "FILE2")]
217        file2: PathBuf,
218        /// Show weight-level differences
219        #[arg(long)]
220        weights: bool,
221        /// Compare actual tensor values with statistical analysis
222        #[arg(long)]
223        values: bool,
224        /// Filter tensors by name pattern (for --values)
225        #[arg(long)]
226        filter: Option<String>,
227        /// Maximum number of tensors to compare (for --values)
228        #[arg(long, default_value = "10")]
229        limit: usize,
230        /// Account for transpose when comparing (GGUF col-major vs APR row-major)
231        #[arg(long)]
232        transpose_aware: bool,
233        /// Output as JSON
234        #[arg(long)]
235        json: bool,
236    },
237    /// List tensor names and shapes
238    Tensors {
239        /// Path to .apr model file
240        #[arg(value_name = "FILE")]
241        file: PathBuf,
242        /// Show tensor statistics (mean, std, min, max)
243        #[arg(long)]
244        stats: bool,
245        /// Filter tensors by name pattern
246        #[arg(long)]
247        filter: Option<String>,
248        /// Limit number of tensors shown (0 = unlimited)
249        #[arg(long, default_value = "0")]
250        limit: usize,
251        /// Output as JSON
252        #[arg(long)]
253        json: bool,
254    },
255    /// Layer-by-layer trace analysis
256    Trace {
257        /// Path to .apr model file
258        #[arg(value_name = "FILE")]
259        file: PathBuf,
260        /// Filter layers by name pattern
261        #[arg(long)]
262        layer: Option<String>,
263        /// Compare with reference model
264        #[arg(long)]
265        reference: Option<PathBuf>,
266        /// Output as JSON
267        #[arg(long)]
268        json: bool,
269        /// Verbose output with per-layer stats
270        #[arg(short, long)]
271        verbose: bool,
272        /// Trace payload through model
273        #[arg(long)]
274        payload: bool,
275        /// Diff mode
276        #[arg(long)]
277        diff: bool,
278        /// Interactive mode
279        #[arg(long)]
280        interactive: bool,
281        /// Save per-stage F32 tensors during trace for SHIP-007 layer-0
282        /// element-wise diff. Comma-separated stage names from
283        /// `apr-cli-trace-save-tensor-v1.yaml` (e.g.
284        /// `embedding,qkv_matmul,attention`). Pass `all` to save every
285        /// stage. Output goes to `--save-tensor-dir` if provided,
286        /// else `<file_dir>/trace-tensors/<run_id>/`.
287        #[arg(long, value_name = "STAGES")]
288        save_tensor: Option<String>,
289        /// Output directory for `--save-tensor` (default: sibling
290        /// `trace-tensors/<run_id>/`).
291        #[arg(long, value_name = "DIR")]
292        save_tensor_dir: Option<PathBuf>,
293        /// Layer-id range for `--save-tensor` (default: 0..1, i.e.
294        /// layer 0 only). Format: `START..END` (Rust range syntax,
295        /// END exclusive).
296        #[arg(long, value_name = "RANGE", default_value = "0..1")]
297        save_tensor_layers: String,
298    },
299    /// Check for best practices and conventions
300    Lint {
301        /// Path to .apr model file
302        #[arg(value_name = "FILE")]
303        file: PathBuf,
304    },
305    /// Explain errors, architecture, tensors, and kernel dispatch
306    Explain {
307        /// Error code, model file path, or family name (auto-detected)
308        #[arg(value_name = "CODE_OR_FILE")]
309        code_or_file: Option<String>,
310        /// Path to .apr model file (optional context for --tensor)
311        #[arg(short, long)]
312        file: Option<PathBuf>,
313        /// Explain a specific tensor
314        #[arg(long)]
315        tensor: Option<String>,
316        /// Explain kernel dispatch pipeline for architecture
317        #[arg(long)]
318        kernel: bool,
319        /// Output as JSON
320        #[arg(long)]
321        json: bool,
322        /// Show kernel contract details and proof obligations
323        #[arg(short, long)]
324        verbose: bool,
325        /// Show per-kernel proof status from contract tests
326        #[arg(long)]
327        proof_status: bool,
328    },
329    /// Manage canary tests for regression
330    Canary {
331        #[command(subcommand)]
332        command: CanaryCommands,
333    },
334    /// Export model to other formats
335    Export {
336        /// Path to .apr model file
337        #[arg(value_name = "FILE", required_unless_present = "list_formats")]
338        file: Option<PathBuf>,
339        /// Output format (safetensors, gguf, mlx, onnx, openvino, coreml)
340        #[arg(long, default_value = "safetensors")]
341        format: String,
342        /// Output file/directory path
343        #[arg(short, long)]
344        output: Option<PathBuf>,
345        /// Apply quantization during export (int8, int4, fp16)
346        #[arg(long)]
347        quantize: Option<String>,
348        /// List all supported export formats
349        #[arg(long)]
350        list_formats: bool,
351        /// Batch export to multiple formats (comma-separated: gguf,mlx,safetensors)
352        #[arg(long)]
353        batch: Option<String>,
354        /// Output in JSON format
355        #[arg(long)]
356        json: bool,
357        /// Plan mode (validate inputs, show export plan, no execution)
358        #[arg(long)]
359        plan: bool,
360    },
361    /// Import from external formats (hf://org/repo, local files, URLs)
362    Import {
363        /// Source: hf://org/repo, local file, or URL
364        #[arg(value_name = "SOURCE")]
365        source: String,
366        /// Output .apr file path (default: derived from source name)
367        #[arg(short, long)]
368        output: Option<PathBuf>,
369        /// Model architecture (whisper, llama, bert, qwen2, qwen3, gpt2, starcoder, gpt-neox, opt, phi, gemma, falcon, mamba, t5, auto)
370        #[arg(long, default_value = "auto")]
371        arch: String,
372        /// Quantization (int8, int4, fp16)
373        #[arg(long)]
374        quantize: Option<String>,
375        /// Strict mode: reject unverified architectures and fail on validation errors
376        #[arg(long)]
377        strict: bool,
378        /// Preserve Q4K quantization for fused kernel inference (GGUF only)
379        /// Uses realizar's Q4K converter instead of dequantizing to F32
380        #[arg(long)]
381        preserve_q4k: bool,
382        /// PMAT-232: External tokenizer.json for weights-only GGUF files.
383        /// Required if the GGUF has no embedded tokenizer vocabulary.
384        #[arg(long)]
385        tokenizer: Option<PathBuf>,
386        /// F-GT-001: Enforce provenance chain. Rejects pre-baked GGUF imports
387        /// (only SafeTensors sources allowed). Ensures single-provenance testing.
388        #[arg(long)]
389        enforce_provenance: bool,
390        /// GH-223: Allow import without config.json (default: error).
391        /// Without config.json, hyperparameters like rope_theta are inferred from
392        /// tensor shapes and may be wrong, producing garbage output.
393        #[arg(long)]
394        allow_no_config: bool,
395    },
396    /// Download and cache model OR HuggingFace dataset (Ollama-like UX)
397    Pull {
398        /// Model reference (alias, hf:// URI, or org/repo) OR "dataset"
399        /// asset-type discriminator. When this value is the literal
400        /// string "dataset", the next positional `repo` is the
401        /// HuggingFace dataset repo and dataset-pull semantics apply.
402        #[arg(value_name = "MODEL_OR_ASSET_TYPE")]
403        model_ref: String,
404        /// Dataset repository (used only when model_ref == "dataset").
405        /// Per `apr-cli-pull-dataset-v1.yaml`.
406        #[arg(value_name = "REPO")]
407        repo: Option<String>,
408        /// Force re-download even if cached
409        #[arg(long)]
410        force: bool,
411        /// CRUX-A-01: resolve short name to canonical URL and exit without
412        /// performing any network I/O.
413        #[arg(long)]
414        dry_run: bool,
415        /// CRUX-A-03: pin to a specific branch, tag, or git SHA on the remote
416        /// (HuggingFace Hub). Defaults to "main" when omitted.
417        #[arg(long, value_name = "REV")]
418        revision: Option<String>,
419        /// CRUX-A-20: offline mode — forbid any outbound network I/O.
420        /// Equivalent to APR_OFFLINE=1 or HF_HUB_OFFLINE=1 in the environment.
421        #[arg(long)]
422        offline: bool,
423        /// (dataset mode) Glob pattern for shard selection. May be passed
424        /// multiple times; matches are unioned. fnmatch-compatible
425        /// (`*`, `?`, `[a-z]`). No-match is fail-fast.
426        #[arg(long, value_name = "GLOB")]
427        include: Vec<String>,
428        /// (dataset mode) Output directory. Default:
429        /// `~/.cache/aprender/datasets/<repo>/`.
430        #[arg(short = 'o', long)]
431        output: Option<PathBuf>,
432    },
433    /// Registry operations (CRUX-A-01): inspect alias map, etc.
434    Registry {
435        #[command(subcommand)]
436        command: crate::commands::registry::RegistryCommands,
437    },
438    /// List cached models
439    #[command(name = "list", alias = "ls")]
440    List,
441    /// Remove model from cache
442    #[command(name = "rm", alias = "remove")]
443    Rm {
444        /// Model reference to remove
445        #[arg(value_name = "MODEL")]
446        model_ref: String,
447    },
448    /// Convert/optimize model
449    Convert {
450        /// Path to .apr model file
451        #[arg(value_name = "FILE")]
452        file: PathBuf,
453        /// Quantize to format (int8, int4, fp16, q4k)
454        #[arg(long)]
455        quantize: Option<String>,
456        /// Compress output (none, zstd, zstd-max, lz4)
457        #[arg(long)]
458        compress: Option<String>,
459        /// Output file path
460        #[arg(short, long)]
461        output: PathBuf,
462        /// Force overwrite existing files
463        #[arg(short, long)]
464        force: bool,
465    },
466    /// Stamp provenance fields (license, data_source, data_license) onto an existing .apr file
467    ///
468    /// SHIP-009 full-discharge enabler — patches the three provenance fields on
469    /// a pre-built APR v2 artifact (e.g., the shipped MODEL-1 teacher whose
470    /// fields are all (missing) because it was built before GATE-APR-PROV-001..003
471    /// shipped). Tensor bytes and header flags are preserved verbatim.
472    Stamp {
473        /// Path to input .apr model file
474        #[arg(value_name = "FILE")]
475        file: PathBuf,
476        /// SPDX license identifier (e.g., Apache-2.0)
477        #[arg(long)]
478        license: Option<String>,
479        /// Training-data source (e.g., huggingface.co/Qwen/Qwen2.5-Coder-7B-Instruct)
480        #[arg(long = "data-source")]
481        data_source: Option<String>,
482        /// SPDX license for data_source (e.g., Apache-2.0)
483        #[arg(long = "data-license")]
484        data_license: Option<String>,
485        /// Output file path
486        #[arg(short, long)]
487        output: PathBuf,
488        /// Force overwrite existing files
489        #[arg(short, long)]
490        force: bool,
491    },
492    /// Compile model into standalone executable (APR-SPEC §4.16)
493    Compile {
494        /// Input .apr model file
495        #[arg(value_name = "FILE", required_unless_present = "list_targets")]
496        file: Option<PathBuf>,
497        /// Output binary path (default: derived from model name)
498        #[arg(short, long)]
499        output: Option<PathBuf>,
500        /// Target triple (e.g., x86_64-unknown-linux-musl)
501        #[arg(long)]
502        target: Option<String>,
503        /// Quantize weights before embedding (int8, int4, fp16)
504        #[arg(long)]
505        quantize: Option<String>,
506        /// Release mode (optimized)
507        #[arg(long)]
508        release: bool,
509        /// Strip debug symbols
510        #[arg(long)]
511        strip: bool,
512        /// Enable LTO (Link-Time Optimization)
513        #[arg(long)]
514        lto: bool,
515        /// List available compilation targets
516        #[arg(long)]
517        list_targets: bool,
518    },
519    /// Merge multiple models
520    Merge {
521        /// Model files to merge
522        #[arg(value_name = "FILES", num_args = 2..)]
523        files: Vec<PathBuf>,
524        /// Merge strategy (average, weighted, slerp, ties, dare)
525        #[arg(long, default_value = "average")]
526        strategy: String,
527        /// Output file path (optional in --plan mode)
528        #[arg(short, long, required_unless_present = "plan")]
529        output: Option<PathBuf>,
530        /// Weights for weighted merge (comma-separated, e.g., "0.7,0.3")
531        #[arg(long, value_delimiter = ',')]
532        weights: Option<Vec<f32>>,
533        /// Base model for TIES/DARE (task vectors computed as delta from base)
534        #[arg(long)]
535        base_model: Option<PathBuf>,
536        /// DARE drop probability (default: 0.9)
537        #[arg(long, default_value = "0.9")]
538        drop_rate: f32,
539        /// TIES trim density threshold (default: 0.2)
540        #[arg(long, default_value = "0.2")]
541        density: f32,
542        /// RNG seed for DARE (default: 42)
543        #[arg(long, default_value = "42")]
544        seed: u64,
545        /// Plan mode (validate inputs, show merge plan, no execution)
546        #[arg(long)]
547        plan: bool,
548    },
549    /// Quantize model weights (GH-243)
550    Quantize {
551        /// Input model file
552        #[arg(value_name = "FILE")]
553        file: PathBuf,
554        /// Quantization scheme: int8, int4, fp16, q4k
555        #[arg(long, short = 's', default_value = "int4")]
556        scheme: String,
557        /// Output file path (required unless --plan)
558        #[arg(short, long)]
559        output: Option<PathBuf>,
560        /// Output format override (apr, gguf, safetensors)
561        #[arg(long)]
562        format: Option<String>,
563        /// Batch quantization (comma-separated schemes)
564        #[arg(long)]
565        batch: Option<String>,
566        /// Plan mode (estimate only, no execution)
567        #[arg(long)]
568        plan: bool,
569        /// Force overwrite existing files
570        #[arg(short, long)]
571        force: bool,
572    },
573    /// Model optimization commands (fine-tune, prune, distill)
574    #[command(flatten)]
575    ModelOps(ModelOpsCommands),
576    /// Start the MCP (Model Context Protocol) server over stdio
577    ///
578    /// Exposes `apr` as MCP tools for Claude Code, Cursor, Cline, and other
579    /// MCP clients. Configure via `.mcp.json` with `{"command":"apr","args":["mcp"]}`.
580    Mcp {},
581    /// Interactive terminal UI
582    Tui {
583        /// Path to .apr model file
584        #[arg(value_name = "FILE")]
585        file: Option<PathBuf>,
586    },
587    /// Model self-test: 10-stage pipeline integrity check (APR-TRACE-001)
588    Check {
589        /// Path to model file
590        #[arg(value_name = "FILE")]
591        file: PathBuf,
592        /// Disable GPU acceleration
593        #[arg(long)]
594        no_gpu: bool,
595        /// Output as JSON
596        #[arg(long)]
597        json: bool,
598    },
599    /// GPU status and VRAM reservation management (GPU-SHARE-001)
600    #[cfg(feature = "training")]
601    Gpu {
602        /// Show reservations as JSON
603        #[arg(long)]
604        json: bool,
605    },
606    /// Sovereign AI coding assistant — all inference local via realizar (PMAT-182)
607    
608    Code {
609        /// Path to local GGUF/APR model file (prefers .apr format)
610        #[arg(long)]
611        model: Option<PathBuf>,
612
613        /// Project directory (loads APR.md/CLAUDE.md from this path)
614        #[arg(long, default_value = ".")]
615        project: PathBuf,
616
617        /// Resume previous session (optionally by ID)
618        #[arg(long)]
619        resume: Option<Option<String>>,
620
621        /// Agent manifest (advanced — overrides defaults)
622        #[arg(long)]
623        manifest: Option<PathBuf>,
624
625        /// Initial prompt (non-interactive: print response and exit)
626        #[arg(short, long)]
627        print: bool,
628
629        /// Prompt text (positional, for -p mode)
630        #[arg(trailing_var_arg = true)]
631        prompt: Vec<String>,
632
633        /// Max turns before stopping
634        #[arg(long, default_value = "50")]
635        max_turns: u32,
636
637        /// Emit a `ccpa-trace.jsonl` describing the run to this path.
638        /// Format mirrors the schema at
639        /// <https://github.com/paiml/claude-code-parity-apr/blob/main/contracts/claude-code-parity-apr-v1.yaml>
640        /// (`§ trace_schema`). Used by `ccpa measure` to score apr-code
641        /// against canonical Claude Code reference fixtures.
642        #[arg(long)]
643        emit_trace: Option<PathBuf>,
644
645        /// Output format for non-interactive (`-p`) mode (PMAT-CODE-OUTPUT-FORMAT-001).
646        /// `text` (default): plain assistant text.
647        /// `json`: structured `{type:"result", subtype:"success", result, session_id, duration_ms}`
648        /// envelope matching Claude Code's `claude -p --output-format json` shape.
649        #[arg(long, value_enum, default_value_t = CodeOutputFormat::Text)]
650        output_format: CodeOutputFormat,
651
652        /// Input format for non-interactive stdin (PMAT-CODE-INPUT-FORMAT-001).
653        /// `text` (default): treat stdin as raw prompt text.
654        /// `json`: parse `{"role":"user","content":"..."}` from stdin and use `content`
655        /// as the prompt. Matches Claude Code's `claude -p --input-format json` shape.
656        #[arg(long, value_enum, default_value_t = CodeInputFormat::Text)]
657        input_format: CodeInputFormat,
658    },
659    /// Extended analysis, profiling, QA, and visualization commands
660    #[command(flatten)]
661    Extended(ExtendedCommands),
662
663    /// Monorepo management (publish, shims, audit, archive) [dev-only]
664    #[cfg(feature = "dev")]
665    #[command(subcommand)]
666    Mono(crate::commands::mono::MonoCommands),
667}