Skip to main content

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