Skip to content

Commit 0e4e20d

Browse files
committed
add shell completions
1 parent 8e92a47 commit 0e4e20d

File tree

8 files changed

+487
-13
lines changed

8 files changed

+487
-13
lines changed

Cargo.lock

Lines changed: 101 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ sqlite-vec = "0.1"
2828

2929
# CLI
3030
clap = { version = "4", features = ["derive"] }
31+
clap_complete = "4"
32+
33+
# Interactive CLI (optional, on by default)
34+
dialoguer = { version = "0.11", features = ["fuzzy-select"], optional = true }
35+
indicatif = { version = "0.17", optional = true }
36+
console = { version = "0.15", optional = true }
3137

3238
# Knowledge graph
3339
petgraph = "0.6"
@@ -60,6 +66,10 @@ hostname = "0.4"
6066
# Vector byte casting
6167
zerocopy = "0.8"
6268

69+
[features]
70+
default = ["interactive"]
71+
interactive = ["dep:dialoguer", "dep:indicatif", "dep:console"]
72+
6373
[dev-dependencies]
6474
tokio-test = "0.4"
6575
tempfile = "3"

src/cli/commands.rs

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
use clap::{Parser, Subcommand};
2+
use clap_complete::Shell;
23

34
#[derive(Parser)]
45
#[command(
56
name = "smriti",
67
version,
7-
about = "SmritiA lightning-fast knowledge store and memory layer for AI agents",
8+
about = "smriti — memory layer for your AI agents",
89
long_about = "Smriti (Sanskrit: memory) — Self-hosted knowledge store built in Rust for agentic AI.\n\
9-
Features: MCP server, agent memory, knowledge graph, wiki-links, full-text search, sync."
10+
Features: MCP server, agent memory, knowledge graph, wiki-links, full-text search, sync.",
11+
after_help = "\x1b[1mExamples:\x1b[0m\n \
12+
smriti create \"Meeting Notes\" -c \"Discussed Q2 roadmap\" -t client,project\n \
13+
smriti new # interactive guided note creation\n \
14+
smriti search \"roadmap\" --limit 5\n \
15+
smriti graph --format dot | dot -Tsvg -o graph.svg\n \
16+
smriti serve --port 8080\n \
17+
smriti completions zsh > ~/.zsh/completions/_smriti",
18+
styles = styles(),
1019
)]
1120
pub struct Cli {
1221
/// Path to the database file
@@ -19,7 +28,10 @@ pub struct Cli {
1928

2029
#[derive(Subcommand)]
2130
pub enum Commands {
31+
// ── CAPTURE ──────────────────────────────────────────
32+
2233
/// Create a new note
34+
#[command(display_order = 1)]
2335
Create {
2436
/// Note title
2537
title: String,
@@ -37,7 +49,15 @@ pub enum Commands {
3749
tags: Option<Vec<String>>,
3850
},
3951

52+
/// Interactive guided note creation
53+
#[cfg(feature = "interactive")]
54+
#[command(display_order = 2, alias = "n")]
55+
New,
56+
57+
// ── SEARCH ───────────────────────────────────────────
58+
4059
/// Read a note by ID or title
60+
#[command(display_order = 10)]
4161
Read {
4262
/// Note ID or title
4363
id: String,
@@ -48,6 +68,7 @@ pub enum Commands {
4868
},
4969

5070
/// List all notes
71+
#[command(display_order = 11)]
5172
List {
5273
/// Maximum number of notes to show
5374
#[arg(long, short, default_value = "20")]
@@ -63,6 +84,7 @@ pub enum Commands {
6384
},
6485

6586
/// Search notes using full-text search
87+
#[command(display_order = 12)]
6688
Search {
6789
/// Search query
6890
query: String,
@@ -76,7 +98,10 @@ pub enum Commands {
7698
json: bool,
7799
},
78100

101+
// ── GRAPH ────────────────────────────────────────────
102+
79103
/// Show the knowledge graph
104+
#[command(display_order = 20)]
80105
Graph {
81106
/// Output format: json, dot, or text
82107
#[arg(long, short, default_value = "text")]
@@ -92,9 +117,13 @@ pub enum Commands {
92117
},
93118

94119
/// Show database statistics
120+
#[command(display_order = 21)]
95121
Stats,
96122

123+
// ── SERVER ───────────────────────────────────────────
124+
97125
/// Start the REST API server
126+
#[command(display_order = 30)]
98127
Serve {
99128
/// Host to bind to
100129
#[arg(long, default_value = "0.0.0.0")]
@@ -106,9 +135,28 @@ pub enum Commands {
106135
},
107136

108137
/// Start the MCP server (JSON-RPC over stdio)
138+
#[command(display_order = 31)]
109139
Mcp,
110140

141+
/// Generate shell completion scripts
142+
#[command(
143+
display_order = 32,
144+
after_help = "Install completions:\n \
145+
bash: smriti completions bash > ~/.bash_completion.d/smriti\n \
146+
zsh: smriti completions zsh > ~/.zsh/completions/_smriti\n \
147+
fish: smriti completions fish > ~/.config/fish/completions/smriti.fish\n \
148+
powershell: smriti completions powershell >> $PROFILE\n \
149+
elvish: smriti completions elvish > ~/.elvish/lib/smriti.elv"
150+
)]
151+
Completions {
152+
/// Target shell
153+
shell: Shell,
154+
},
155+
156+
// ── DATA ─────────────────────────────────────────────
157+
111158
/// Sync notes with a remote server (Synology WebDAV or custom)
159+
#[command(display_order = 40)]
112160
Sync {
113161
/// Remote URL (e.g., https://nas.local:5006/notes)
114162
#[arg(long)]
@@ -120,6 +168,7 @@ pub enum Commands {
120168
},
121169

122170
/// Import notes from a directory of markdown files
171+
#[command(display_order = 41)]
123172
Import {
124173
/// Directory containing .md files
125174
path: String,
@@ -130,6 +179,7 @@ pub enum Commands {
130179
},
131180

132181
/// Export notes to a directory of markdown files
182+
#[command(display_order = 42)]
133183
Export {
134184
/// Output directory
135185
path: String,
@@ -139,3 +189,35 @@ pub enum Commands {
139189
frontmatter: bool,
140190
},
141191
}
192+
193+
/// Custom styles for colorized --help output.
194+
fn styles() -> clap::builder::Styles {
195+
use clap::builder::styling::{AnsiColor, Color, Style};
196+
197+
clap::builder::Styles::styled()
198+
.usage(
199+
Style::new()
200+
.bold()
201+
.underline()
202+
.fg_color(Some(Color::Ansi(AnsiColor::Yellow))),
203+
)
204+
.header(
205+
Style::new()
206+
.bold()
207+
.underline()
208+
.fg_color(Some(Color::Ansi(AnsiColor::Yellow))),
209+
)
210+
.literal(
211+
Style::new()
212+
.fg_color(Some(Color::Ansi(AnsiColor::Cyan))),
213+
)
214+
.placeholder(
215+
Style::new()
216+
.fg_color(Some(Color::Ansi(AnsiColor::Green))),
217+
)
218+
.valid(
219+
Style::new()
220+
.fg_color(Some(Color::Ansi(AnsiColor::Cyan)))
221+
.bold(),
222+
)
223+
}

0 commit comments

Comments
 (0)