ssh_cli/lib.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2//! # ssh-cli
3//!
4//! Full-stack Rust CLI that gives an LLM (Claude Code, Cursor, Windsurf) the ability
5//! to operate remote servers over SSH in a subprocess flow via stdin/stdout.
6//!
7//! ## Modules
8//!
9//! | Module | Responsibility |
10//! |-----------------|---------------------------------------------------------------|
11//! | `cli` | Clap derive argument definitions and dispatcher |
12//! | `vps` | CRUD and persistence of VPS records (XDG + TOML + 0o600) |
13//! | `secrets` | Primary key and default at-rest encryption (ChaCha20-Poly1305)|
14//! | `ssh` | Real one-shot SSH client via `russh` (password/key, TOFU) |
15//! | `i18n` | Internationalization with bilingual `Message` enum |
16//! | `locale` | OS locale detection and resolution |
17//! | `platform` | Platform adjustments (Windows UTF-8, TTY detection) |
18//! | `masking` | Unicode-safe masking of sensitive values |
19//! | `errors` | Structured error types via `thiserror` |
20//! | `output` | Sole module authorized for `println!` (CRUD formatting) |
21//! | `paths` | Path validation and normalization (anti-traversal, NFC) |
22//! | `signals` | Ctrl+C handler with cancellation flag via `AtomicBool` |
23//! | `terminal` | TTY detection and color choice via `termcolor` |
24//!
25//! ## Entry point
26//!
27//! The public [`run`] function is the entry point called by `main.rs`.
28
29#![cfg_attr(docsrs, feature(doc_cfg))]
30#![warn(missing_docs)]
31#![warn(rust_2018_idioms)]
32#![warn(clippy::undocumented_unsafe_blocks)]
33#![warn(clippy::multiple_unsafe_ops_per_block)]
34#![warn(unsafe_op_in_unsafe_fn)]
35
36pub mod cli;
37pub mod errors;
38pub mod erros;
39pub mod i18n;
40pub mod locale;
41pub mod masking;
42pub mod output;
43pub mod paths;
44pub mod platform;
45pub mod scp;
46pub mod secrets;
47pub mod signals;
48pub mod ssh;
49pub mod terminal;
50pub mod tunnel;
51pub mod vps;
52
53use anyhow::Result;
54
55/// Runs ssh-cli from the command-line arguments.
56///
57/// Entry point called by `main.rs`. It:
58/// 1. Registers the Ctrl+C handler for graceful cancellation.
59/// 2. Initializes the platform (Windows UTF-8 code page, TTY detection).
60/// 3. Parses arguments via clap.
61/// 4. Initializes logging via `tracing-subscriber`.
62/// 5. Initializes terminal color configuration.
63/// 6. Initializes i18n with the detected language.
64/// 7. Dispatches to the appropriate subcommand (`vps`, `connect`, `exec`, `sudo-exec`, `scp`, `tunnel`).
65pub async fn run() -> Result<()> {
66 signals::register_handler()?;
67
68 platform::initialize_platform()?;
69
70 let argumentos = cli::parse_args();
71
72 cli::initialize_logs(&argumentos);
73
74 terminal::initialize(argumentos.no_color)?;
75
76 i18n::initialize_language(argumentos.lang.as_deref())?;
77
78 cli::dispatch(argumentos).await
79}