clish
The most elegant CLI framework. Successor of vecli, my first ever Rust crate.
Inspired by Typer
[!WARNING] clish is a work in progress. it's not published yet to crates-io, so you'll have to use git to experiment for now.
[] = { = "https://codeberg.org/razkar/clish" }or
How it works
Annotate a function with #[command]. The argument types tell clish how to parse the command line.
use *;
/// Deploy to an environment
myapp deploy production --env prod --force
[!IMPORTANT] Do not import
clish::*directly as it exposes the framework's internals. Only use when you know what you're doing. Always prefer usingclish::prelude::*
Argument types
The type of each parameter determines how clish parses it.
| Type | Behavior | Example |
|---|---|---|
Pos<T> |
Positional, required | myapp cmd foo |
Pos<Option<T>> |
Positional, optional | myapp cmd or myapp cmd foo |
Pos<Vec<T>> |
Positional, variadic | myapp cmd a b c |
Named<T> |
--name val, required |
myapp cmd --env prod |
Named<Option<T>> |
--name val, optional |
|
Named<Vec<T>> |
--name val, repeatable |
myapp cmd --tag a --tag b |
bool |
--flag presence |
myapp cmd --force |
Any T that implements FromStr works: String, i64, u32, f64, and so on. Type mismatches produce a clear error at runtime:
error: invalid value for <port>: expected u16
Option<Vec<T>> and Option<bool> are rejected at compile time with a clear error.
Command metadata
The #[command] attribute accepts metadata at the top level:
| Key | Type | Description |
|---|---|---|
help |
string | Short description (shown everywhere) |
details |
string | Long description (shown only in --help) |
name |
string | Override the CLI command name |
aliases |
array | Alternative names for command lookup |
hidden |
bool | Omit from app-level help listing (still invocable) |
deprecated |
bool | Print a warning when invoked |
deprecation_note |
string | Extra message for deprecation |
Deprecated commands appear dimmed in the command listing and show a warning on use. Aliased commands can be invoked by any alias.
Parameter metadata
Individual parameters are documented via param(ident, ...) (or parameter(ident, ...) if you're feeling fancy) blocks inside #[command]:
Display
| Key | Type | Description |
|---|---|---|
help |
string | Short description |
details |
string | Long description (shown only in --help) |
name |
string | Override the CLI flag name (e.g. name = "dry-run") |
short |
char | Single-character alias (short = 'd' becomes -d) |
placeholder |
string | Custom help token (placeholder = "HOST" shows <HOST>) |
hide |
bool | Omit this parameter from help listings |
Value resolution
| Key | Type | Description |
|---|---|---|
env |
string | Environment variable to fall back to |
default |
string | Default value when nothing is provided |
Resolution order: CLI arg > $ENV_VAR > default > error (if required).
Validation
| Key | Type | Description |
|---|---|---|
choices |
array | Allowed values (choices = ["debug", "info"]) |
conflicts_with |
array | Mutual exclusion (conflicts_with = ["quiet"]) |
requires |
array | Prerequisites (requires = ["output"]) |
Completion
| Key | Type | Description |
|---|---|---|
value_hint |
string | Hint for shell completion engines |
value_hint is reserved for future use, shell completion generation is not yet implemented.
Help text
clish generates --help automatically from all metadata, showing short aliases, placeholders, choices, env vars, and defaults:
myapp deploy --help
myapp --help deploy
Example output:
myapp deploy
Deploy the application
Usage: myapp deploy <HOST> [--port <PORT>] [-l <LEVEL>] [-v]
Arguments:
<HOST> Target host [env: DEPLOY_HOST]
Options:
-p, --port <PORT> Port number [default: 8080]
-l, --level <LEVEL> Log level [choices: debug, info, error]
-v, --verbose Verbose output
-q, --quiet Suppress output
App metadata
app!() reads CARGO_PKG_NAME, CARGO_PKG_VERSION, and CARGO_PKG_DESCRIPTION automatically from your crate. Override any of them with the builder:
app!
.name
.version
.description
.run;
Styling
Help output uses farben markup by default. Override the styles:
use *;
use ;
app!
.styles
.run;
Or pass an anstyle::Style directly if you're already in the anstyle ecosystem:
use ;
app!
.styles
.run;
Crate structure
| Crate | Purpose |
|---|---|
clish |
Public API, the one you add |
clish-core |
Runtime: App, CommandEntry, parse helpers |
clish-macros |
Proc macro: #[command] |
You never need to depend on clish-core or clish-macros directly.
Status
Beta :tada:
Early development. The API is not stable.
- Positional arguments
- Named arguments
- Boolean flags
- Optional arguments
- Typed arguments via
FromStr - Short flag/option aliases (
-v,-o) - Environment variable fallback (
env) - Default values (
default) - Enum-like value constraints (
choices) - Mutual exclusion / prerequisites (
conflicts_with,requires) - Command aliases
- Hidden commands / deprecated commands
- Custom help placeholders
- Hide individual params from help
- Auto-generated help
-
farben+anstylestyling - Variadic
Vec<T>in macro - Subcommand groups
- Shell completions
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Cheers, RazkarStudio
Copyright © 2026 RazkarStudio. All rights reserved.