greppy/cli/
mod.rs

1//! CLI command definitions and handlers
2
3pub mod daemon;
4pub mod index;
5pub mod login;
6pub mod model;
7pub mod search;
8pub mod trace;
9pub mod web;
10
11use clap::{Parser, Subcommand};
12use std::path::PathBuf;
13
14const LONG_ABOUT: &str = r#"
15 ██████╗ ██████╗ ███████╗██████╗ ██████╗ ██╗   ██╗
16██╔════╝ ██╔══██╗██╔════╝██╔══██╗██╔══██╗╚██╗ ██╔╝
17██║  ███╗██████╔╝█████╗  ██████╔╝██████╔╝ ╚████╔╝ 
18██║   ██║██╔══██╗██╔══╝  ██╔═══╝ ██╔═══╝   ╚██╔╝  
19╚██████╔╝██║  ██║███████╗██║     ██║        ██║   
20 ╚═════╝ ╚═╝  ╚═╝╚══════╝╚═╝     ╚═╝        ╚═╝   
21
22Sub-millisecond semantic code search powered by BM25 + AI reranking.
23
24QUICK START:
25    1. greppy index           Index your codebase (one-time setup)
26    2. greppy login           Setup AI reranking (Ollama local or cloud)
27    3. greppy search <query>  Search your code!
28
29SEARCH MODES:
30    greppy search "query"     Semantic search - AI reranks BM25 results
31    greppy search -d "query"  Direct search - BM25 only (no AI, faster)
32
33DAEMON (optional, for faster searches):
34    greppy start              Start background daemon with file watcher
35    greppy stop               Stop the daemon
36    greppy status             Check if daemon is running
37
38AI PROVIDERS:
39    greppy login              Configure AI provider for semantic search
40    greppy logout             Remove stored credentials
41
42    Supports Ollama (local, free), Claude, or Gemini. Without login,
43    searches fall back to direct BM25 mode automatically.
44
45TRACE (symbol analysis):
46    greppy trace <symbol>             Find all invocation paths
47    greppy trace --refs <symbol>      Find all references  
48    greppy trace --impact <symbol>    Analyze change impact
49    greppy trace --dead               Find unused code
50    greppy trace --stats              Codebase statistics
51
52EXAMPLES:
53    greppy index                      Index current directory
54    greppy search "error handling"    Find error handling code
55    greppy search -d "TODO" -n 50     Find all TODOs (direct mode)
56    greppy search "auth" --json       JSON output for scripting
57    greppy trace --refs createUser    Find all references to createUser
58    greppy trace --impact auth        Analyze impact of changing auth
59"#;
60
61/// Sub-millisecond semantic code search
62#[derive(Parser, Debug)]
63#[command(name = "greppy")]
64#[command(author, version)]
65#[command(about = "Sub-millisecond semantic code search")]
66#[command(long_about = LONG_ABOUT)]
67#[command(propagate_version = true)]
68pub struct Cli {
69    #[command(subcommand)]
70    pub command: Commands,
71}
72
73#[derive(Subcommand, Debug)]
74pub enum Commands {
75    /// Search for code (semantic by default, -d for direct BM25)
76    #[command(visible_alias = "s")]
77    Search(SearchArgs),
78
79    /// Index a project for searching
80    #[command(visible_alias = "i")]
81    Index(IndexArgs),
82
83    /// Start the background daemon
84    Start,
85
86    /// Stop the background daemon
87    Stop,
88
89    /// Check if the daemon is running
90    Status,
91
92    /// Configure AI provider for semantic search (Ollama, Claude, or Gemini)
93    #[command(after_help = "AI PROVIDERS:
94    1. Run 'greppy login'
95    2. Select your provider using arrow keys
96    3. Complete setup (OAuth for cloud, auto-detect for Ollama)
97    4. You're ready to use semantic search!
98
99PROVIDERS:
100    Ollama (Local)     - Free, private, runs on your machine
101    Claude (Anthropic) - Uses your Claude.ai account via OAuth
102    Gemini (Google)    - Uses your Google account via OAuth
103
104NOTES:
105    - Ollama: Install from ollama.com, run 'ollama pull <model>'
106    - Cloud providers use OAuth (no API keys needed)
107    - Credentials stored in ~/.config/greppy/config.toml
108    - Run 'greppy logout' to remove stored credentials")]
109    Login,
110
111    /// Remove stored credentials and log out from all providers
112    #[command(
113        after_help = "This removes all stored credentials from your config file.
114After logging out, semantic search will fall back to direct BM25 search.
115Run 'greppy login' to authenticate again."
116    )]
117    Logout,
118
119    /// Switch AI model/provider interactively
120    #[command(visible_alias = "m")]
121    #[command(after_help = "USAGE:
122    greppy model              Interactive model switcher
123    
124Shows current AI configuration and lets you:
125    - Switch between saved profiles (Claude, Gemini, Ollama models)
126    - Add new Ollama models from your local installation
127    - Set the active model for semantic search
128
129EXAMPLES:
130    greppy model              Open interactive switcher
131    
132Profiles are saved in ~/.config/greppy/config.toml")]
133    Model,
134
135    /// Trace symbol invocations across codebase
136    #[command(visible_alias = "t")]
137    Trace(trace::TraceArgs),
138
139    /// Launch web UI for visual codebase exploration
140    #[command(visible_alias = "w")]
141    Web(web::WebArgs),
142}
143
144/// Arguments for the search command
145#[derive(Parser, Debug)]
146#[command(after_help = "EXAMPLES:
147    greppy search \"authentication\"       Semantic search (AI)
148    greppy search -d \"authentication\"    Direct BM25 search
149    greppy search \"error\" -n 10          Limit results
150    greppy search \"query\" --json         JSON output")]
151pub struct SearchArgs {
152    /// Search query
153    pub query: String,
154
155    /// Direct mode (BM25 only, no AI)
156    #[arg(short = 'd', long)]
157    pub direct: bool,
158
159    /// Max results
160    #[arg(short = 'n', long, default_value = "20")]
161    pub limit: usize,
162
163    /// JSON output
164    #[arg(long)]
165    pub json: bool,
166
167    /// Project path (default: current directory)
168    #[arg(short, long)]
169    pub project: Option<PathBuf>,
170}
171
172/// Arguments for the index command
173#[derive(Parser, Debug)]
174#[command(after_help = "EXAMPLES:
175    greppy index              Index current directory
176    greppy index -p ~/code    Index specific directory
177    greppy index --force      Force full re-index")]
178pub struct IndexArgs {
179    /// Project path (default: current directory)
180    #[arg(short, long)]
181    pub project: Option<PathBuf>,
182
183    /// Force full re-index
184    #[arg(short, long)]
185    pub force: bool,
186}
187
188/// Output format options
189#[derive(Debug, Clone, Copy, PartialEq, Eq)]
190pub enum OutputFormat {
191    Human,
192    Json,
193}