1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
pub mod batch;
pub mod bench;
pub mod bench_ndcg;
pub mod context;
pub mod diff;
pub mod edit;
pub mod exists;
pub mod explain;
pub mod find;
pub mod impact;
pub mod index;
pub mod init;
#[cfg(feature = "mcp")]
pub mod mcp;
pub mod outline;
pub mod read;
pub mod rename;
pub mod run;
pub mod search;
pub mod stats;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(name = "prx", version, about = "Praxis — agent-native Unix tools")]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
/// Human-readable output instead of JSON
#[arg(long, global = true)]
pub plain: bool,
/// Suppress non-essential output
#[arg(short, long, global = true)]
pub quiet: bool,
/// Fail with an error instead of falling back to grep/cat/find
#[arg(long, global = true)]
pub no_fallback: bool,
}
#[derive(Subcommand)]
pub enum Commands {
/// Search the codebase by query
Search(search::SearchArgs),
/// Read file content with structural awareness
Read(read::ReadArgs),
/// List and filter files in the workspace
Find(find::FindArgs),
/// Find and replace content in a file
Edit(edit::EditArgs),
/// Show git diffs with semantic summaries
Diff(diff::DiffArgs),
/// Build or update the search index
Index(index::IndexArgs),
/// Print the symbol table for a file or directory
Outline(outline::OutlineArgs),
/// Probabilistic existence check for a pattern
Exists(exists::ExistsArgs),
/// Execute multiple commands in parallel from stdin
Batch(batch::BatchArgs),
/// Print token savings dashboard
Stats(stats::StatsArgs),
/// Generate integration files for agent frameworks
Init(init::InitArgs),
/// Run a command and return structured output
Run(run::RunArgs),
/// Run synthetic benchmarks comparing prx vs grep+cat
Bench(bench::BenchArgs),
/// Run NDCG benchmark against a labeled dataset
BenchNdcg(bench_ndcg::BenchNdcgArgs),
/// Assemble context package for a module
Context(context::ContextArgs),
/// Analyze reverse dependencies for a file or symbol
Impact(impact::ImpactArgs),
/// Explain a symbol: definition, references, and tests in one call
Explain(explain::ExplainArgs),
/// Rename a symbol across the codebase (dry-run by default)
Rename(rename::RenameArgs),
/// Start MCP server on stdio
#[cfg(feature = "mcp")]
Mcp(mcp::McpArgs),
}
impl Commands {
pub fn name(&self) -> String {
match self {
Self::Search(_) => "search",
Self::Read(_) => "read",
Self::Find(_) => "find",
Self::Edit(_) => "edit",
Self::Diff(_) => "diff",
Self::Index(_) => "index",
Self::Outline(_) => "outline",
Self::Exists(_) => "exists",
Self::Batch(_) => "batch",
Self::Stats(_) => "stats",
Self::Init(_) => "init",
Self::Run(_) => "run",
Self::Bench(_) => "bench",
Self::BenchNdcg(_) => "bench-ndcg",
Self::Context(_) => "context",
Self::Impact(_) => "impact",
Self::Explain(_) => "explain",
Self::Rename(_) => "rename",
#[cfg(feature = "mcp")]
Self::Mcp(_) => "mcp",
}
.to_string()
}
}