Skip to main content

talon_cli/cli/
mod.rs

1//! CLI argument parsing via `clap` derive.
2
3mod ask_args;
4mod changes_args;
5mod init_args;
6mod inspect_args;
7mod meta_args;
8mod read_args;
9mod recall_args;
10mod related_args;
11pub mod scope;
12mod search_args;
13mod status_args;
14mod sync_args;
15mod where_clause;
16
17pub use where_clause::parse_where_clause;
18
19pub use ask_args::AskArgs;
20pub use changes_args::ChangesArgs;
21use clap::{Parser, Subcommand};
22pub use init_args::InitArgs;
23pub use inspect_args::InspectArgs;
24pub use inspect_args::InspectCheck;
25pub use meta_args::MetaArgs;
26pub use read_args::ReadArgs;
27pub use recall_args::RecallArgs;
28pub use related_args::RelatedArgs;
29pub use scope::SharedScopeArgs;
30pub use search_args::{CliSearchMode, SearchArgs, SharedSearchArgs};
31pub use status_args::StatusArgs;
32pub use sync_args::SyncArgs;
33
34#[derive(Debug, Clone, clap::Args)]
35pub struct SecretsArgs {
36    #[command(subcommand)]
37    pub subcommand: crate::command::secrets::SecretsSubcommand,
38}
39
40/// Talon — Obsidian vault search, indexing, and MCP server.
41#[allow(clippy::struct_excessive_bools)]
42#[derive(Debug, Clone, Parser)]
43#[command(
44    name = "talon",
45    version = env!("CARGO_PKG_VERSION"),
46    subcommand_required = false,
47    about = "Obsidian vault search, indexing, and MCP server.",
48    before_help = crate::banner::help_banner_colored(),
49    after_help = r#"Examples:
50  talon search "project setup" --mode hybrid
51  talon read src/main.rs --from-line 10 --max-lines 20
52  talon related src/lib.rs --depth 2 --direction both
53  talon sync --force
54  talon sync --rebuild --fast
55
56Use 'talon <command> --help' for per-command help."#
57)]
58pub struct Cli {
59    /// Print embedded SKILL.md.
60    #[arg(long, global = true)]
61    pub skill: bool,
62
63    /// Token-efficient JSON for agents. Disables human banner and spinner.
64    #[arg(long, global = true, conflicts_with = "verbose")]
65    pub agent: bool,
66
67    /// Emit JSON output.
68    #[arg(long, global = true)]
69    pub json: bool,
70
71    /// Use fast mode for search or sync.
72    #[arg(long, global = true)]
73    pub fast: bool,
74
75    /// Include diagnostic details in output.
76    #[arg(short, long, global = true)]
77    pub verbose: bool,
78
79    /// Read config from PATH.
80    #[arg(short = 'c', long = "config", global = true, value_hint = clap::ValueHint::FilePath)]
81    pub config_file: Option<std::path::PathBuf>,
82
83    #[command(subcommand)]
84    pub command: Option<Commands>,
85}
86
87#[derive(Debug, Clone, Subcommand)]
88pub enum Commands {
89    #[command(about = "Initialize a new talon configuration file.")]
90    Init(InitArgs),
91
92    #[command(about = "Sync your vault with the search index.")]
93    Sync(SyncArgs),
94
95    #[command(about = "Show vault index status.")]
96    Status(StatusArgs),
97
98    #[command(about = "Search your Obsidian vault using hybrid ranking.")]
99    Search(SearchArgs),
100
101    #[command(about = "Ask a vault-grounded question.")]
102    Ask(AskArgs),
103
104    #[command(about = "Read a note from your vault.")]
105    Read(ReadArgs),
106
107    #[command(about = "Find related notes via wikilink traversal.")]
108    Related(RelatedArgs),
109
110    #[command(about = "Query frontmatter metadata from your vault.")]
111    Meta(MetaArgs),
112
113    #[command(about = "Show vault changes since a timestamp.")]
114    Changes(ChangesArgs),
115
116    #[command(about = "Inspect your vault for structural signals and patterns.")]
117    Inspect(InspectArgs),
118
119    #[command(about = "Recall relevant vault context for a message.")]
120    Recall(RecallArgs),
121
122    #[command(about = "Manage API keys stored in the OS keychain.")]
123    Secrets(SecretsArgs),
124
125    #[command(about = "Run MCP-over-stdio mode.")]
126    Mcp,
127}
128
129/// Parses CLI args or exits on error.
130#[must_use]
131pub fn parse_or_exit() -> Cli {
132    Cli::parse()
133}