{"id":27226127,"url":"https://github.com/jamesgober/mod-cli","last_synced_at":"2025-10-30T11:49:26.109Z","repository":{"id":287139699,"uuid":"959838033","full_name":"jamesgober/mod-cli","owner":"jamesgober","description":"A modular, high-performance CLI framework for Rust — built for customization, speed, and control.","archived":false,"fork":false,"pushed_at":"2025-05-01T02:57:14.000Z","size":246,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-30T14:07:09.423Z","etag":null,"topics":["cli","cli-framework","rust","terminal"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jamesgober.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-03T12:40:22.000Z","updated_at":"2025-05-01T02:53:08.000Z","dependencies_parsed_at":"2025-04-10T11:47:26.246Z","dependency_job_id":"19a3964a-4647-4e63-84bd-bc062352a55d","html_url":"https://github.com/jamesgober/mod-cli","commit_stats":null,"previous_names":["jamesgober/mod-cli"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/jamesgober/mod-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesgober%2Fmod-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesgober%2Fmod-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesgober%2Fmod-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesgober%2Fmod-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jamesgober","download_url":"https://codeload.github.com/jamesgober/mod-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesgober%2Fmod-cli/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267312886,"owners_count":24067792,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-27T02:00:11.917Z","response_time":82,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","cli-framework","rust","terminal"],"created_at":"2025-04-10T11:47:16.408Z","updated_at":"2025-10-17T01:44:48.052Z","avatar_url":"https://github.com/jamesgober.png","language":"Rust","readme":"\u003ch1 align=\"center\"\u003e\n    \u003cimg width=\"120px\" height=\"auto\" src=\"https://raw.githubusercontent.com/jamesgober/jamesgober/main/media/icons/hexagon-3.svg\" alt=\"Triple Hexagon\"\u003e\n    \u003cbr\u003e\u003cstrong\u003eMOD-CLI\u003c/strong\u003e\u003cbr\u003e\n    \u003csub\u003e\u003csup\u003e\u003csup\u003eCLI FRAMEWORK\u003c/sup\u003e\u003c/sup\u003e\u003c/sub\u003e\n\u003c/h1\u003e\n\u003cdiv align=\"center\"\u003e\n    \u003cdiv\u003e\n        \u003ca href=\"https://crates.io/crates/mod-cli\" alt=\"ModCLI on Crates.io\"\u003e\u003cimg alt=\"Crates.io\" src=\"https://img.shields.io/crates/v/mod-cli\"\u003e\u003c/a\u003e\n        \u003cspan\u003e\u0026nbsp;\u003c/span\u003e\n        \u003ca href=\"https://crates.io/crates/mod-cli\" alt=\"Download ModCLI\"\u003e\u003cimg alt=\"Crates.io Downloads\" src=\"https://img.shields.io/crates/d/mod-cli?color=%230099ff\"\u003e\u003c/a\u003e\n        \u003cspan\u003e\u0026nbsp;\u003c/span\u003e\n        \u003ca href=\"https://docs.rs/mod-cli\" title=\"ModCLI Documentation\"\u003e\u003cimg alt=\"docs.rs\" src=\"https://img.shields.io/docsrs/mod-cli\"\u003e\u003c/a\u003e\n        \u003cspan\u003e\u0026nbsp;\u003c/span\u003e\n        \u003ca href=\"https://github.com/jamesgober/mod-cli/actions/workflows/ci.yml\" title=\"CI Status\"\u003e\u003cimg alt=\"CI\" src=\"https://github.com/jamesgober/mod-cli/actions/workflows/ci.yml/badge.svg\"\u003e\u003c/a\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\u003cp\u003e\n  \u003cstrong\u003eMOD-CLI\u003c/strong\u003e is a lightweight, modular CLI framework for Rust.\n  Register commands, style output, and build interactive flows with a clean, zero-bloat core.\n  Focus on your app, not boilerplate.\n  \n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003csup\u003e\n    \u003ca href=\"#installation\"\u003e\u003cb\u003eInstall\u003c/b\u003e\u003c/a\u003e\n    \u003cspan\u003e\u0026nbsp;│\u0026nbsp;\u003c/span\u003e\n    \u003ca href=\"#usage\"\u003e\u003cb\u003eUsage\u003c/b\u003e\u003c/a\u003e\n    \u003cspan\u003e\u0026nbsp;│\u0026nbsp;\u003c/span\u003e\n    \u003ca href=\"#error-handling\"\u003e\u003cb\u003eError Handling\u003c/b\u003e\u003c/a\u003e\n  \u003c/sup\u003e\n  \u003cbr\u003e\n\u003c/div\u003e\n\n\u003cbr\u003e\n\u003cbr\u003e\n\n\u003ch2\u003eDocumentation\u003c/h2\u003e\n\u003cp\u003e\n  Full API docs are on \u003ca href=\"https://docs.rs/mod-cli\" title=\"Docs.rs: mod-cli\"\u003edocs.rs\u003c/a\u003e.\n  Docs are built with a minimal, stable feature set (\u003ccode\u003einternal-commands\u003c/code\u003e, \u003ccode\u003ecustom-commands\u003c/code\u003e) to ensure MSRV compatibility.\n\u003c/p\u003e\n\n\u003cbr\u003e\n\u003ch2\u003eKey Features\u003c/h2\u003e\n\u003cli\u003e\n    \u003cstrong\u003eCustom Commands\u003c/strong\u003e - Define your own commands with execution logic.\n\u003c/li\u003e\n\u003cbr\u003e\n\u003cli\u003e\n    \u003cstrong\u003eColors and Gradients\u003c/strong\u003e – Full-spectrum foreground and background colors with multi-color gradient support.\n\u003c/li\u003e\n\u003cbr\u003e\n\u003cli\u003e\n    \u003cstrong\u003eStyled Output\u003c/strong\u003e – Compose bold, italic, underlined, and colorized output using a chainable builder. Includes table rendering and ANSI-safe formatting.\n\u003c/li\u003e\n\u003cbr\u003e\n\u003cli\u003e\n    \u003cstrong\u003eAnimated Loaders\u003c/strong\u003e – Built-in progress bars, spinners, and percent indicators with customizable characters, labels, and themes.\n\u003c/li\u003e\n\u003cbr\u003e\n\u003cli\u003e\n    \u003cstrong\u003eInteractive Console\u003c/strong\u003e – Launch an interactive shell with command routing, custom input handlers, prompt styling, and exit messages.\n\u003c/li\u003e\n\u003cbr\u003e\n\u003cli\u003e\n    \u003cstrong\u003eModular Architecture\u003c/strong\u003e – Drop-in components for printing, styling, theming, command sources, and shell extensions. Easily replace or extend any layer.\n\u003c/li\u003e\n\u003cbr\u003e\n\u003cli\u003e\n    \u003cstrong\u003eZero-Bloat Core\u003c/strong\u003e – Minimal dependencies, clean structure, and fully optional features through Cargo flags.\n\u003c/li\u003e\n\n\u003chr\u003e\u003cbr\u003e\n\n\u003ch2\u003eInstallation\u003c/h2\u003e\n\nAdd the library to your `Cargo.toml`:\n```toml\n[dependencies]\nmod-cli = \"0.6.4\"\n```\n\n\u003chr\u003e\u003cbr\u003e\n\n\u003ch2\u003eError Handling\u003c/h2\u003e\n\nCommands and selected APIs return structured errors via `ModCliError`.\n\nKey updates:\n- `Command::validate(\u0026self, args) -\u003e Result\u003c(), modcli::error::ModCliError\u003e`\n- `set_startup_banner_from_file(path) -\u003e Result\u003c(), ModCliError\u003e`\n- `output::messages::load_messages_from_json(path) -\u003e Result\u003c(), ModCliError\u003e` (feature: `theme-config`)\n\nMinimal example:\n\n```rust\nuse modcli::command::Command;\nuse modcli::error::ModCliError;\n\nstruct Hello;\n\nimpl Command for Hello {\n    fn name(\u0026self) -\u003e \u0026str { \"hello\" }\n    fn help(\u0026self) -\u003e Option\u003c\u0026str\u003e { Some(\"Greets the user\") }\n\n    fn validate(\u0026self, args: \u0026[String]) -\u003e Result\u003c(), ModCliError\u003e {\n        if args.len() \u003e 1 {\n            return Err(ModCliError::InvalidUsage(\"hello takes at most one argument\".into()));\n        }\n        Ok(())\n    }\n\n    fn execute(\u0026self, args: \u0026[String]) {\n        if let Some(name) = args.first() { println!(\"Hello, {name}!\"); } else { println!(\"Hello!\"); }\n    }\n}\n```\n\nProgrammatic dispatch:\n\n```rust\nuse modcli::{loader::CommandRegistry, error::ModCliError};\nlet reg = CommandRegistry::new();\nmatch reg.try_execute(\"unknown\", \u0026[]) {\n    Err(ModCliError::UnknownCommand(name)) =\u003e eprintln!(\"unknown: {name}\"),\n    Err(other) =\u003e eprintln!(\"error: {other}\"),\n    Ok(()) =\u003e {}\n}\n```\n\u003cbr\u003e\n\nAdd the library with features:\n```toml\n[dependencies]\nmod-cli = { version = \"0.6.4\", features = [\"gradients\", \"table-presets\"] }\n```\n\u003cbr\u003e\n\n\u003cbr\u003e\n\u003ch3\u003eFeature Flags\u003c/h3\u003e\n\n| Feature               | Description |\n|----------------------|-------------|\n| `internal-commands`  | Built-in helper commands like `help`, `ping`, etc. |\n| `custom-commands`    | Ergonomic helpers for user-defined commands. |\n| `tracing-logs`       | Emit `tracing` events via `output::hook` alongside console output. |\n| `dispatch-cache`     | Single-entry dispatch cache to speed repeated invocations. |\n| `gradients`          | Named gradient helpers (24‑bit RGB) with zero extra deps. |\n| `layouts`            | Lightweight layout engine for terminal rows/columns. |\n| `table-presets`      | Convenience presets for `TableStyle` (ASCII, Rounded, Heavy). |\n| `progress-presets`   | Convenience constructors for `ProgressStyle` (compact, heavy). |\n| `theme-config`       | Enable theme config serialization (serde/serde_json). |\n| `images`             | Optional image support (png/jpeg) via the `image` crate. |\n\n\n\u003c!-- Removed experimental sections for plugins/json-loader to align with current feature set. --\u003e\n\n\n\u003chr\u003e\u003cbr\u003e\n\n\u003ch2\u003eUsage\u003c/h2\u003e\n\n\n### Basic Usage\n```rust\nuse modcli::ModCli;\n\nfn main() {\n    let args: Vec\u003cString\u003e = std::env::args().skip(1).collect();\n    let mut cli = ModCli::new();\n    cli.run(args);\n}\n```\n\n### Set a custom prefix\n```rust\nuse modcli::ModCli;\n\nfn main() {\n    let args: Vec\u003cString\u003e = std::env::args().skip(1).collect();\n    let mut cli = ModCli::new();\n\n    // Set a custom prefix\n    cli.set_prefix(\"myCLI\");\n\n    cli.run(args);\n}\n```\n\n\n#### Using named colors\n```rust\nuse modcli::output::{build, colors, print};\n\nlet teal = colors::get(\"teal\"); // returns a Color (or fallback)\nlet demo = build()\n    .part(\"Color Demo:\").space()\n    .part(\"Teal\").color(teal).bold().get();\nprint::line(\u0026demo);\n\n```\n\n\n---\n\n### Using Gradients\n\n#### Two-color gradient:\n```rust\nuse modcli::output::{\n    gradient,\n    print,\n    RED, ORANGE\n};\n\nlet gradient_text = gradient::two_color(\"Two color gradient\", RED, ORANGE);\nprint::line(\u0026gradient_text);\n\n```\n\n#### Three-color gradient:\n```rust\nuse modcli::output::{\n    gradient,\n    print,\n    BLUE, GREEN, YELLOW\n};\n\nlet gradient_text = gradient::three_color(\"Three color gradient\", BLUE, GREEN, YELLOW);\nprint::line(\u0026gradient_text);\n\n```\n\n#### Multi-color gradient:\n```rust\nuse modcli::output::{\n    gradient,\n    print,\n    RED, ORANGE, YELLOW, GREEN, BLUE\n};\n\nlet gradient_text = gradient::multi_color(\"Multi-color gradient\", vec![RED, ORANGE, YELLOW, GREEN, BLUE]);\nprint::line(\u0026gradient_text);\n\n```\n\n#### Using RGB with gradients:\n```rust\nuse modcli::output::{\n    gradient,\n    print\n};\n\nlet gradient_text = gradient::two_color(\n    \"Gradient Output\", \n    Color::Rgb { r: 255, g: 0, b: 0 },\n    Color::Rgb { r: 0, g: 0, b: 255 },\n);\nprint::line(\u0026gradient_text);\n\n```\n\n### Themes\n\n\u003c!-- Optional screenshot/GIF. Replace the src with your asset path. --\u003e\n\u003c!-- \u003cimg src=\"docs/media/themes-demo.gif\" alt=\"Themes demo\" width=\"600\" /\u003e --\u003e\n\n```rust\nuse modcli::output::{print, themes};\n\n// Apply a theme (changes terminal fg/bg until reset)\nthemes::apply_theme(\"blue\");\nprint::line(\"Applied theme: blue\");\n\n// Read colors for log categories from current theme\nlet t = themes::current_theme();\nlet categories = [\"error\",\"warn\",\"success\",\"info\",\"debug\",\"trace\",\"notice\",\"status\"]; \nfor key in categories {\n    let color = t.get_log_color(key);\n    println!(\"{key}: {:?}\", color);\n}\n\n// Reset at the end\nthemes::Theme::reset();\n```\n\n---\n\n### Output Styles\n```rust\nuse modcli::output::{\n    print,\n    build,\n    BLUE\n};\n\n // 📦 Progress Bar Demo\n let testing = build()\n        .part(\"Testing\")\n        .color(BLUE)\n        .bold()\n        .get();\n\nprint::line(\u0026testing);\n\n// Outputs \"Testing\" in bold/blue.\n```\n\n#### Multiple Styles:\n```rust\nuse modcli::output::{\n    gradient,\n    print,\n    build,\n    BLUE, LIGHT_BLUE\n};\n\n // 📦 Progress Bar Demo\n let testing = build()\n        .part(\"Label:\").color(BLUE).bold().space()\n        .part(\"This content has\").space()\n        .part(\"multiple\").color(LIGHT_BLUE).bold().space()\n        .part(\"styles\").underline().space()\n        .part(\"and\").italic().space()\n        .part(\"colors\").underline().space()\n        .part(\"!\")\n        .get();\n\nprint::line(\u0026testing);\n```\n\n#### Style + Gradients:\n```rust\nuse modcli::output::{\n    print,\n    build,\n    BLUE, GREEN\n};\n\nlet gradient_text = gradient::two_color(\"Gradient Output\", BLUE, GREEN);\nlet testing = build()\n        .part(\u0026gradient_text).bold().space()\n        .part(\"+ Styled!\")\n        .get();\n\nprint::line(\u0026testing);\n\n```\n\n---\n\n### Progress Bar \u0026amp; Animated Loaders\n\n#### Auto Progress:\n```rust\nuse modcli::output::{\n    progress::{\n        show_progress_bar, \n    }\n};\n\nshow_progress_bar(\"Testing\", 45, 1500);\n```\n\n\u003e Displays\n```bash\nLabel [#############################################] 100% Done!\n```\n\n#### Manual control:\n```rust\nuse modcli::output::{\n    build,\n    progress::{\n        ProgressBar, \n        ProgressStyle,\n    },\n    LIGHT_BLUE\n};\n\n // Progress Bar Demo\n let label = build()\n    .part(\"Loading\")\n    .color(LIGHT_BLUE)\n    .bold()\n    .get();\n\nlet mut bar = ProgressBar::new(30, ProgressStyle {\n    fill: '■',\n    done_label: \"Complete!\",\n    color: Some(LIGHT_BLUE),\n    ..Default::default()\n});\n\nbar.set_label(\u0026label);\nbar.start_auto(2000); // auto-fill in 2 seconds\n\n```\n\n#### Manual .tick() control (like during a loop):\n```rust\nuse std::time::Duration;\nuse modcli::output::{\n    progress::{\n        ProgressBar, \n        ProgressStyle\n    },\n    ORANGE\n};\nuse modcli::console::run_shell;\n\n\n let mut bar = ProgressBar::new(10, ProgressStyle {\n    fill: '■',\n    done_label: \"Done!\",\n    color: Some(ORANGE),\n    ..Default::default()\n});\n bar.set_label(\"Syncing\");\n \n for _ in 0..10 {\n     bar.tick();\n     std::thread::sleep(Duration::from_millis(200));\n }\n println!(\" {}\", bar.style.done_label);\n\n```\n\n#### Animated Spinner (Loading/Waiting):\n```rust\nuse modcli::output::{\n    progress::{\n        show_spinner\n    }\n};\nshow_spinner(\"Loading\", 20, 100);\n```\n\n#### Animated Percentage Loader:\n```rust\nuse std::thread::sleep;\nuse std::time::Duration;\nuse modcli::output::{\n    progress::{\n        show_percent_progress\n    }\n};\n\nfor i in (0..=100).step_by(10) {\n    show_percent_progress(\"Loading\", i);\n    sleep(Duration::from_millis(100));\n}\nprintln!();\n```\n---\n\n### Tables\n\n#### Table Example: Flex Width, Heavy Borders\n```rust\nuse modcli::output::table::{render_table, TableMode, TableStyle};\n\nlet headers = [\"Name\", \"Age\", \"Role\"];\nlet rows = vec![\n    vec![\"Alice\", \"29\", \"Engineer\"],\n    vec![\"Bob\", \"35\", \"Manager\"],\n    vec![\"Charlie\", \"41\", \"CTO\"],\n];\n\nrender_table(\u0026headers, \u0026rows, TableMode::Flex, TableStyle::Heavy);\n```\n\n\u003e Outputs\n```bash\n┏━━━━━━━━┳━━━━━━━━┳━━━━━━━━┓\n┃Name    ┃Age     ┃Role    ┃\n┣━━━━━━━━╋━━━━━━━━╋━━━━━━━━┫\n┃Alice   ┃29      ┃Engineer┃\n┃Bob     ┃35      ┃Manager ┃\n┃Charlie ┃41      ┃CTO     ┃\n┗━━━━━━━━┻━━━━━━━━┻━━━━━━━━┛\n\n```\n\n#### Table Example: Fixed Width, Rounded Borders\n```rust\nuse crate::output::table::{render_table, TableMode, TableStyle};\n\nlet headers = [\"Name\", \"Age\", \"Role\"];\nlet rows = vec![\n    vec![\"Alice\", \"29\", \"Engineer\"],\n    vec![\"Bob\", \"35\", \"Manager\"],\n    vec![\"Charlie\", \"41\", \"CTO\"],\n];\n\nrender_table(\u0026headers, \u0026rows, TableMode::Fixed(15), TableStyle::Rounded);\n```\n\u003e Outputs\n```bash\n╭───────────────┬───────────────┬───────────────╮\n│Name           │Age            │Role           │\n├───────────────┼───────────────┼───────────────┤\n│Alice          │29             │Engineer       │\n│Bob            │35             │Manager        │\n│Charlie        │41             │CTO            │\n╰───────────────┴───────────────┴───────────────╯\n```\n\n#### Table Example: Fixed Width, Ascii Borders\n```rust\nuse crate::output::table::{render_table, TableMode, TableStyle};\n\nlet headers = [\"Name\", \"Age\", \"Role\"];\nlet rows = vec![\n    vec![\"Alice\", \"29\", \"Engineer\"],\n    vec![\"Bob\", \"35\", \"Manager\"],\n    vec![\"Charlie\", \"41\", \"CTO\"],\n];\n\nrender_table(\u0026headers, \u0026rows, TableMode::Fixed(15), TableStyle::Ascii);\n```\n\u003e Outputs\n```bash\n+---------------+---------------+---------------+\n|Name           |Age            |Role           |\n+---------------+---------------+---------------+\n|Alice          |29             |Engineer       |\n|Bob            |35             |Manager        |\n|Charlie        |41             |CTO            |\n+---------------+---------------+---------------+\n```\n\n\u003cbr\u003e\u003cbr\u003e\n\n\n\u003ch2\u003eCreating Custom Commands\u003c/h2\u003e\n\n### File Structure\n```\nmy_project/\n├── src/\n│   ├── commands/\n│   │   └── greet.rs      ← define `GreetCommand` here\n```\n\u003e Create a commands folder in src/, then put the command in its own file:\n\n\n### Custom Command File\n```rust\nuse modcli::command::Command;\n\npub struct GreetCommand;\n\nimpl Command for GreetCommand {\n    fn name(\u0026self) -\u003e \u0026str {\n        \"greet\"\n    }\n\n    fn aliases(\u0026self) -\u003e \u0026[\u0026str] {\n        \u0026[\"hi\"]\n    }\n\n    fn help(\u0026self) -\u003e Option\u003c\u0026str\u003e {\n        Some(\"Greets the user.\")\n    }\n\n    fn validate(\u0026self, _args: \u0026[String]) -\u003e Result\u003c(), String\u003e {\n        Ok(())\n    }\n\n    fn execute(\u0026self, _args: \u0026[String]) {\n        println!(\"Greetings!\");\n    }\n}\n```\n\u003e greet.rs\n\n\n### Register your command in `main.rs`, `tool.rs`, etc.\n```rust\nmod commands;\nuse modcli::ModCli;\nuse commands::greet::GreetCommand;\n\nfn main() {\n    let args: Vec\u003cString\u003e = std::env::args().skip(1).collect();\n    let mut cli = ModCli::new();\n\n    // Register function\n    cli.registry.register(Box::new(GreetCommand));\n\n\n    cli.run(args);\n}\n```\n\n\n#### Test Command\n```sh\n$ myCLI greet\nGreetings!\n\n$ myCLI help\nList of available commands...\n```\n\n\u003cbr\u003e\u003cbr\u003e\n\n\u003ch2\u003eInteractive Shell\u003c/h3\u003e\n\n### ModCLI supports an interactive console mode (like a REPL):\n```rust\nuse modcli::config::CliConfig;\nuse modcli::console::run_shell;\n\nfn main() {\n    let config = CliConfig::load(None);\n    run_shell(\u0026config);\n}\n```\n\n\n### Adding a custom console command for `shell`: \n```rust\nuse modcli::ModCli;\nuse modcli::shell_commands::{register, ShellCommand};\n\nfn greet_handler(_input: \u0026str) -\u003e bool {\n    println!(\"👋 Hello from shell command!\");\n    true\n}\n\nfn main() {\n    register(ShellCommand {\n        name: \"greet\",\n        aliases: \u0026[\"hi\", \"wave\"],\n        help: \"Greets the user with a friendly hello\",\n        handler: greet_handler,\n    });\n}\n```\n\n#### Config File Example (config.json)\n```json\n{\n  \"modcli\": {\n        \"name\"  : \"mod-cli\",\n        \"prefix\": \"mod\",\n        \"banner\": \"Welcome to ModCLI\",\n        \"delay\" : 0,\n        \"theme\" : \"default\",\n        \"strict\": false,\n        \"force_shell\": false,\n        \"shell\": {\n            \"prompt\": \"Tool \u003e\",\n            \"welcome\": [\"Welcome to the console.\"],\n            \"goodbye\": [\"Bye!\"]\n        },\n        \"messages\": {\n            \"no_command\": \"No command provided.\",\n            \"not_found\": \"Command not found.\"\n        }\n  }\n}\n```\n\u003e Default location: `project_root/config.json` \n\n#### Manually set the config path (if not project root)\n```rust\nuse modcli::config;\n\nfn main() {\n    config::set_path((\"my/custom/config.json\");\n\n```\n\n\n\u003cbr\u003e\u003chr\u003e\u003cbr\u003e\n\n\u003e [!WARNING]\n\u003e **Pre-release**: This project is in active development.\n\u003e The core is stable but features are evolving. Production use is possible, \n\u003e but interfaces may still evolve until 1.0.\n\n\n\u003cbr\u003e\n\u003c!--\n:: LICENSE\n============================================================================ --\u003e\n\u003cdiv id=\"license\"\u003e\n    \u003chr\u003e\n    \u003ch2\u003e📌 License\u003c/h2\u003e\n    \u003cp\u003eLicensed under the \u003cb\u003eApache License\u003c/b\u003e, version 2.0 (the \u003cb\u003e\"License\"\u003c/b\u003e); you may not use this software, including, but not limited to the source code, media files, ideas, techniques, or any other associated property or concept belonging to, associated with, or otherwise packaged with this software except in compliance with the \u003cb\u003eLicense\u003c/b\u003e.\u003c/p\u003e\n    \u003cp\u003eYou may obtain a copy of the \u003cb\u003eLicense\u003c/b\u003e at: \u003ca href=\"http://www.apache.org/licenses/LICENSE-2.0\" title=\"Apache-2.0 License\" target=\"_blank\"\u003ehttp://www.apache.org/licenses/LICENSE-2.0\u003c/a\u003e.\u003c/p\u003e\n    \u003cp\u003eUnless required by applicable law or agreed to in writing, software distributed under the \u003cb\u003eLicense\u003c/b\u003e is distributed on an \"\u003cb\u003eAS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND\u003c/b\u003e, either express or implied.\u003c/p\u003e\n    \u003cp\u003eSee the \u003ca href=\"./LICENSE\" title=\"Software License file\"\u003eLICENSE\u003c/a\u003e file included with this project for the specific language governing permissions and limitations under the \u003cb\u003eLicense\u003c/b\u003e.\u003c/p\u003e\n    \u003cbr\u003e\n\u003c/div\u003e\n\n\n\n\n\n\u003c!--\n:: COPYRIGHT\n============================================================================ --\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003cbr\u003e\n  \u003ch2\u003e\u003c/h2\u003e\n  \u003csup\u003eCOPYRIGHT \u003csmall\u003e\u0026copy;\u003c/small\u003e 2025 \u003cstrong\u003eJAMES GOBER.\u003c/strong\u003e\u003c/sup\u003e\n\u003c/div\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesgober%2Fmod-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjamesgober%2Fmod-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesgober%2Fmod-cli/lists"}