ipfrs_cli/
lib.rs

1//! IPFRS CLI Library
2//!
3//! This library provides the core functionality for the IPFRS command-line interface.
4//! While primarily used by the binary, it also exposes utilities for output formatting,
5//! configuration management, and interactive shell support.
6//!
7//! # Modules
8//!
9//! - [`commands`] - Command handler implementations (modular refactoring)
10//! - [`config`] - Configuration file management and settings (with caching)
11//! - [`output`] - Output formatting with colors and tables
12//! - [`plugin`] - Plugin system for extending CLI with custom commands
13//! - [`progress`] - Progress indicators for long-running operations
14//! - [`shell`] - Interactive REPL shell implementation
15//! - [`tui`] - Terminal User Interface dashboard
16//! - [`utils`] - Utility functions for maintenance and updates
17//!
18//! # Performance Optimizations
19//!
20//! The CLI has been optimized for fast startup and low latency:
21//!
22//! - **Config Caching**: Configuration files are loaded once and cached globally
23//!   using [`std::sync::OnceLock`] to avoid repeated disk I/O.
24//! - **Lazy Initialization**: Heavy modules are only loaded when needed.
25//! - **Minimal Dependencies**: Core functionality uses lightweight dependencies.
26//!
27//! # Examples
28//!
29//! ```rust
30//! use ipfrs_cli::output::{format_bytes, OutputStyle};
31//!
32//! // Format file sizes
33//! let size = format_bytes(1048576);
34//! assert_eq!(size, "1.00 MB");
35//!
36//! // Create output style
37//! let style = OutputStyle::new(true, "text");
38//! assert_eq!(style.format, "text");
39//! ```
40//!
41//! ## Configuration Management
42//!
43//! ```rust
44//! use ipfrs_cli::config::Config;
45//!
46//! // Load config with caching (fast on subsequent calls)
47//! let config = Config::load().unwrap();
48//! assert_eq!(config.general.log_level, "info");
49//!
50//! // Force fresh load without cache
51//! let fresh_config = Config::load_uncached().unwrap();
52//! ```
53
54pub mod commands;
55pub mod config;
56pub mod output;
57pub mod plugin;
58pub mod progress;
59pub mod shell;
60pub mod tui;
61pub mod utils;
62
63/// Build the CLI command structure
64///
65/// This function creates the complete clap command structure for IPFRS CLI.
66/// It's used by both the main binary and utilities like man page generation.
67///
68/// # Returns
69///
70/// Returns a fully configured `clap::Command` with all subcommands and options.
71///
72/// # Examples
73///
74/// ```
75/// use ipfrs_cli::build_cli;
76///
77/// let cli = build_cli();
78/// assert_eq!(cli.get_name(), "ipfrs");
79/// ```
80pub fn build_cli() -> clap::Command {
81    use clap::{Arg, Command};
82
83    Command::new("ipfrs")
84        .version(env!("CARGO_PKG_VERSION"))
85        .about("IPFRS - Inter-Planet File RUST System")
86        .long_about(
87            "IPFRS - Inter-Planet File RUST System\n\n\
88            A next-generation content-addressed storage system with built-in support for\n\
89            tensors, logic programming, and semantic search. IPFRS extends IPFS concepts\n\
90            with advanced features for AI/ML workloads and distributed data management.\n\n\
91            Examples:\n  \
92            ipfrs init                    Initialize a new repository\n  \
93            ipfrs add file.txt            Add a file to IPFRS\n  \
94            ipfrs get <cid>               Retrieve content by CID\n  \
95            ipfrs daemon                  Start the IPFRS daemon\n  \
96            ipfrs shell                   Start interactive shell",
97        )
98        .arg(
99            Arg::new("verbose")
100                .short('v')
101                .long("verbose")
102                .help("Enable verbose logging (shows debug information)")
103                .action(clap::ArgAction::SetTrue),
104        )
105        .arg(
106            Arg::new("no-color")
107                .long("no-color")
108                .help("Disable colored output (useful for scripts and non-TTY environments)")
109                .action(clap::ArgAction::SetTrue),
110        )
111        .arg(
112            Arg::new("quiet")
113                .short('q')
114                .long("quiet")
115                .help(
116                    "Quiet mode - suppress non-essential output (useful for scripts and pipelines)",
117                )
118                .action(clap::ArgAction::SetTrue),
119        )
120        .arg(
121            Arg::new("config")
122                .short('c')
123                .long("config")
124                .value_name("FILE")
125                .help("Path to configuration file (overrides default config location)")
126                .action(clap::ArgAction::Set),
127        )
128        // Add basic subcommands for man page generation
129        // (The main binary has the full implementation)
130        .subcommand(Command::new("init").about("Initialize an IPFRS repository"))
131        .subcommand(Command::new("add").about("Add file to IPFRS"))
132        .subcommand(Command::new("cat").about("Output file contents by CID"))
133        .subcommand(Command::new("get").about("Download file to filesystem"))
134        .subcommand(Command::new("ls").about("List directory contents"))
135        .subcommand(
136            Command::new("block")
137                .about("Manage raw blocks")
138                .subcommand(Command::new("get").about("Get raw block"))
139                .subcommand(Command::new("put").about("Put raw block"))
140                .subcommand(Command::new("stat").about("Block statistics"))
141                .subcommand(Command::new("rm").about("Remove block")),
142        )
143        .subcommand(
144            Command::new("daemon")
145                .about("Manage IPFRS daemon")
146                .subcommand(Command::new("start").about("Start daemon in background"))
147                .subcommand(Command::new("stop").about("Stop background daemon"))
148                .subcommand(Command::new("status").about("Check daemon status"))
149                .subcommand(Command::new("restart").about("Restart daemon")),
150        )
151        .subcommand(
152            Command::new("dag")
153                .about("Manage DAG nodes")
154                .subcommand(Command::new("get").about("Get DAG node"))
155                .subcommand(Command::new("put").about("Put DAG node"))
156                .subcommand(Command::new("resolve").about("Resolve IPLD path"))
157                .subcommand(Command::new("export").about("Export DAG to CAR"))
158                .subcommand(Command::new("import").about("Import DAG from CAR")),
159        )
160        .subcommand(
161            Command::new("swarm")
162                .about("Manage swarm connections")
163                .subcommand(Command::new("peers").about("List connected peers"))
164                .subcommand(Command::new("connect").about("Connect to peer"))
165                .subcommand(Command::new("disconnect").about("Disconnect from peer"))
166                .subcommand(Command::new("addrs").about("List listening addresses")),
167        )
168        .subcommand(
169            Command::new("dht")
170                .about("DHT operations")
171                .subcommand(Command::new("findprovs").about("Find providers"))
172                .subcommand(Command::new("findpeer").about("Find peer address"))
173                .subcommand(Command::new("provide").about("Announce provider")),
174        )
175        .subcommand(Command::new("id").about("Show node identity"))
176        .subcommand(Command::new("version").about("Show version info"))
177        .subcommand(
178            Command::new("stats")
179                .about("Show statistics")
180                .subcommand(Command::new("repo").about("Repository statistics"))
181                .subcommand(Command::new("bw").about("Bandwidth statistics"))
182                .subcommand(Command::new("bitswap").about("Bitswap statistics")),
183        )
184        .subcommand(
185            Command::new("pin")
186                .about("Manage pinned content")
187                .subcommand(Command::new("add").about("Pin content"))
188                .subcommand(Command::new("rm").about("Unpin content"))
189                .subcommand(Command::new("ls").about("List pins"))
190                .subcommand(Command::new("verify").about("Verify pin integrity")),
191        )
192        .subcommand(
193            Command::new("repo")
194                .about("Manage repository")
195                .subcommand(Command::new("gc").about("Run garbage collection"))
196                .subcommand(Command::new("stat").about("Repository statistics"))
197                .subcommand(Command::new("fsck").about("Verify repository"))
198                .subcommand(Command::new("version").about("Repository version")),
199        )
200        .subcommand(
201            Command::new("tensor")
202                .about("Manage tensors")
203                .subcommand(Command::new("add").about("Add tensor"))
204                .subcommand(Command::new("get").about("Get tensor"))
205                .subcommand(Command::new("info").about("Tensor metadata"))
206                .subcommand(Command::new("export").about("Export tensor format")),
207        )
208        .subcommand(
209            Command::new("logic")
210                .about("Logic programming")
211                .subcommand(Command::new("infer").about("Run inference query"))
212                .subcommand(Command::new("prove").about("Show proof tree"))
213                .subcommand(Command::new("kb-stats").about("Knowledge base statistics"))
214                .subcommand(Command::new("kb-save").about("Save knowledge base"))
215                .subcommand(Command::new("kb-load").about("Load knowledge base")),
216        )
217        .subcommand(
218            Command::new("semantic")
219                .about("Semantic search")
220                .subcommand(Command::new("search").about("Vector search"))
221                .subcommand(Command::new("index").about("Manual indexing"))
222                .subcommand(Command::new("similar").about("Find similar"))
223                .subcommand(Command::new("stats").about("Index statistics"))
224                .subcommand(Command::new("save").about("Save semantic index"))
225                .subcommand(Command::new("load").about("Load semantic index")),
226        )
227        .subcommand(
228            Command::new("model")
229                .about("Model management")
230                .subcommand(Command::new("add").about("Add model directory"))
231                .subcommand(Command::new("checkpoint").about("Create snapshot"))
232                .subcommand(Command::new("diff").about("Compare models"))
233                .subcommand(Command::new("rollback").about("Restore version")),
234        )
235        .subcommand(
236            Command::new("gradient")
237                .about("Gradient operations")
238                .subcommand(Command::new("push").about("Publish gradient"))
239                .subcommand(Command::new("pull").about("Fetch gradient"))
240                .subcommand(Command::new("aggregate").about("Federated learning"))
241                .subcommand(Command::new("history").about("View updates")),
242        )
243        .subcommand(
244            Command::new("bootstrap")
245                .about("Manage bootstrap peers")
246                .subcommand(Command::new("list").about("List bootstrap peers"))
247                .subcommand(Command::new("add").about("Add bootstrap peer"))
248                .subcommand(Command::new("rm").about("Remove bootstrap peer")),
249        )
250        .subcommand(Command::new("ping").about("Ping peer"))
251        .subcommand(Command::new("shell").about("Start interactive shell"))
252        .subcommand(Command::new("tui").about("Start Terminal User Interface dashboard"))
253        .subcommand(
254            Command::new("plugin")
255                .about("Plugin management")
256                .long_about(
257                    "Manage and execute IPFRS CLI plugins.\n\n\
258                    Plugins are executables that extend the CLI with custom commands.\n\
259                    Place plugins in ~/.ipfrs/plugins/ with the naming convention:\n  \
260                    ipfrs-plugin-<name>\n\n\
261                    Examples:\n  \
262                    ipfrs plugin list              List all available plugins\n  \
263                    ipfrs plugin info <name>       Show plugin information\n  \
264                    ipfrs plugin run <name> ...    Execute a plugin",
265                )
266                .subcommand(Command::new("list").about("List available plugins"))
267                .subcommand(
268                    Command::new("info")
269                        .about("Show plugin information")
270                        .arg(Arg::new("name").required(true).help("Plugin name")),
271                )
272                .subcommand(
273                    Command::new("run")
274                        .about("Execute a plugin")
275                        .arg(Arg::new("name").required(true).help("Plugin name"))
276                        .arg(
277                            Arg::new("args")
278                                .num_args(0..)
279                                .help("Plugin arguments")
280                                .trailing_var_arg(true),
281                        ),
282                ),
283        )
284}