#ci-cd #cli-framework #framework #ci

build mici

Lightweight CLI framework based on filesystem hierarchy

6 releases

Uses new Rust 2024

new 0.1.5 Feb 25, 2026
0.1.4 Feb 23, 2026
0.1.2 Jan 30, 2026
0.1.1 Oct 15, 2025

#109 in Build Utils

Apache-2.0

135KB
3.5K SLoC

mici

mici is a lightweight CLI framework that automatically discovers and executes your commands based on filesystem hierarchy.

Define your commands as YAML files and mici handles the CLI and its execution for you.

Quick Start

Make sure Rust is installed. See #install for more details.

# Install mici using Cargo
# This will install `mici` as executable.
cargo install mici

Run mici --help to see what's available.

# Initialize mici
mici init

# Create your first command and edit if needed
# at `~/.mici/jobs/commands/hello.yml`
# or run `mici edit hello` to quickly open in an editor.
mici new hello

# See what it is with --help
# Pager can be disabled with `disable_pager: true` in the `config.yml`.
mici hello --help

# Run it
mici hello

Why mici?

Traditional CLI development:

  • Write command parsers and argument handling
  • Manage command registration and routing
  • Rebuild and redeploy for every new command
  • Maintain complex CLI application code

With mici:

  • Drop YAML files in a directory structure
  • Commands appear in your CLI automatically
  • No rebuilds, no deployments, no CLI code
  • Perfect for CI/CD replacement workflows

How it works

Create your commands as YAML files in a directory hierarchy.

~/.mici
├── config.yml                          # Configuration file
└── jobs
    ├── commands
    │   ├── deploy
    │   │   ├── terraform.yml           # mici deploy terraform
    │   │   └── frontend
    │   │       ├── staging.yml         # mici deploy frontend staging
    │   │       └── production.yml      # mici deploy frontend production
    │   ├── database
    │   │   ├── backup.yml              # mici database backup
    │   │   └── migrate.yml             # mici database migrate
    │   └── hello.yml                   # mici hello
    │
    └── scripts                         # Usable as:
        ├── hello.py                    #   hello.py
        └── run.sh                      #   run.sh

Each YAML file has CI-like attributes - environment variables, confirmation prompts, parallel execution, and more; allowing mici to customize your run of that command and generate help documentation based on the available information.

For a full reference of how a mici command is structured, see examples/.../hello.yml.

version: "1.0"
name: "hello"
description: "A new mici command"
usage: "mici hello"
configuration:
  confirm: false
  environment:
    VAR_ONE: "SOME_VALUE_123"
    VAR_TWO: "SOME_VALUE_123"
    IS_FORCED: "@{inputs.force}"
    TOKEN: "${MY_PRIVATE_TOKEN}"
  working_directory: null
inputs:
  name:
    type: string
    description: "A name to say hello to!"
    required: true
    secret: false
    short: -n
    long: --name
    default: "World"
  force:
    type: boolean
    description: "Run this with force, maybe?"
    short: -f
    long: --force
steps:
  - id: "say_hello"
    name: "Say hello on terminal"
    run:
      shell: "bash"
      working_directory: null
      environment:
        VAR_TWO: "ANOTHER_VALUE_456"
      command: |
        echo "Hello, @{inputs.name}!"

That's it. Your filesystem is your CLI structure, and YAML is your command.

Install

Cargo is a package manager for Rust. Make sure to have Rust toolset available on your computer first. See rustup installation guide for easy introduction.

Once you have Rust available, you can run any of the following commands to install mici.

From crates.io

cargo install mici

From source

git clone git@github.com:rwxdash/mici.git
cd ./mici

cargo install --path .

Uninstall

Simply run:

cargo uninstall mici

What's to come

There are some major stories to complete before I call this project version 1.0. Here's what I have in my mind so far:

Done

  • Implement tests and CI checks
  • Implement the basic runner
    • Handle step confirmation
    • Basic execution of a simple command
    • Implement environment variable substitution
    • Make basic execution run on Windows
  • The default schema in new command should have proper default shell for linux/windows
  • Basic validation for commands
  • Handle errors with miette
  • Implement tracing
  • Runtime input validation
    • Reject invalid values for choice inputs
    • Enforce required inputs — error when not provided and no default
  • Secret masking for secret: true inputs in logs/output
  • Config validation — reject unknown/misspelled keys in config.yml
  • Better fetch UX — confirmation prompt and/or backup before nuking local commands
  • Logging improvements
    • Log level configurable through config.yml
    • Silent mode
    • Timestamps
  • Exit code forwarding — propagate step exit codes to the caller (currently always exits 1)
  • Implement script: "scripts/..." usage for steps
    • Pass inputs as env vars (e.g., MICI_INPUT_<INPUT_NAME>=<INPUT_VALUE>).

Up next

  • Parallel step execution
  • Step output capture (stdout/stderr per step)
    • Prerequisite for @{steps.<STEP_ID>.output} in expressions
  • Implement expression evaluator for when: in steps
    • on_failure() # any previous step failed
    • on_success() # all previous steps passed
    • on_platform("linux") # linux/win/darwin
    • depends_on("step_id") # or depends_on(["step1", "step2"])
    • ${ENV_VAR} == "production"
    • @{inputs.cleanup}
    • @{inputs.branch} == "main"
    • @{steps.<STEP_ID>.output} == "success"
    • Accept operators and chains

Later

  • Runner/step-execution isolation
    • with chroot/containers/microvms
  • OpenTelemetry Support
    • OpenTelemetry export through config.yml
    • OpenTelemetry export through command's yml

Contributions and Code of Conduct

Code of conduct is simple. Be nice and thoughtful. That's all.

The project is not open to contributions at this time. It's still early and I'm actively shaping what this tool should be.

In the meantime, feel free to open an issue if you find a bug or have a suggestion.

License

Distributed under the Apache License 2.0.

See the LICENSE file for more information.


mici: Your filesystem is the best argument parser.

Dependencies

~31–50MB
~772K SLoC