A TUI command assembler β snap together tools, fill params, and launch.
Vibecoding workflow: If you frequently ask an agent to run local scripts
or tools for you, use cmdsnap instead β define the tools once in
config.json, then launch them yourself from the TUI. No need to
summon an agent or wait for a response.
Pure keyboard operation. No mouse, no memorizing flags. Browse files, pick from enums, type free text β all inside the TUI. Run multiple scripts side by side, watch their logs, kill or restart.
Any executable works: Python, Node, Rust, Bash, .NET, whatever.
This README is written for both humans and AI. The config reference below is structured so an agent can read it and help you add any tool β just tell it what command you want to run, and it can write the config entry.
Vibecoding workflow: If you frequently ask an agent to run local scripts
or tools for you, use cmdsnap instead β define the tools once in
config.json, then launch them yourself from the TUI. No need to
summon an agent or wait for a response.
# From source
git clone https://github.com/your-username/cmdsnap.git
cd cmdsnap
cargo install --path .# Initialize in any project
cd ~/my-project
cmdsnap init
# Let AI agents read the docs
cmdsnap readme # prints the full README for AI consumption
# Launch
cmdsnapThis creates a .cmdsnap/ directory in your project:
.cmdsnap/
βββ config.json β your tool definitions
βββ theme.json β color theme
βββ cmdsnap.db β log history
βββ habit.db β parameter memory
| Feature | How |
|---|---|
| Assemble commands | Pick a tool, fill params via form, all in TUI |
| File browser | Press [Right] on a file param β browse, select, path is filled |
| Enum picker | [Right] cycles options; [Right]/Type lets you choose or type freely |
| Template preview | Select a recent run to pre-fill all param values |
| Toolkits | Group tools into folders, navigate with Left/Right |
| Multi-process | Run any number of tools concurrently, each in its own log panel |
| Inline actions | Stop, delete, or inspect each running process |
| Clipboard copy | [Ctrl+L] copies the entire log + command |
| AI-readable docs | cmdsnap readme prints full docs for agents |
| History browser | [Ctrl+H] browses all past runs from the database |
| Non-interactive guard | Interactive commands (nano, vim) are rejected with a clear error |
| ANSI colors | Colored terminal output renders in the log panel |
| Multi-language | Any executable: bash, python3, node, dotnet, uv, etc. |
| Theme system | 4 built-in themes, customizable via theme.json |
| Habit learning | Remembers last browsed directories and param history per tool |
Edit .cmdsnap/config.json. Each tool or toolkit is an entry in service:
{
"name": "hello",
"description": "A simple test",
"command": "echo",
"args": ["hello world"]
}Launch cmdsnap, select the tool, and press Enter.
Tools can have interactive parameters that you fill in before launching:
{
"name": "search",
"description": "Search for files",
"command": "find",
"args": ["."],
"params": [
{
"name": "-name",
"label": "Pattern",
"type": "text",
"required": true,
"description": "File pattern, e.g. '*.rs'"
}
]
}Three parameter types:
| Type | Description | Interaction |
|---|---|---|
text |
Free text input | Type your value |
file |
File path selection | [Right] opens file browser |
enum |
Predefined options | [Right] cycles options, or type your own |
{
"name": "--format",
"label": "Format",
"type": "enum",
"options": ["json", "csv"],
"option_descriptions": {
"json": "JSON output with full metadata",
"csv": "Comma-separated values"
}
}For boolean flags, use an enum with an empty option:
{
"name": "--verbose",
"label": "Verbose",
"type": "enum",
"options": ["", "--verbose"]
}When --verbose is selected, it's passed as a flag. When empty, nothing is passed.
Group related tools under a toolkit:
{
"type": "toolkit",
"name": "git_tools",
"description": "Git operations",
"service": [
{
"name": "status",
"description": "Show git status",
"command": "git",
"args": ["status"]
},
{
"name": "commit",
"description": "Stage all and commit",
"command": "bash",
"args": ["-c", "git add . && git commit -m \"${1:-update}\"", "bash"],
"params": [
{
"name": "MSG",
"label": "Message",
"type": "text",
"required": false,
"description": "Commit message (empty = 'update')"
}
]
}
]
}Enter a toolkit with Right, leave with Left.
- Name starts with
--or-β passed as--name value - Name is plain β value passed as positional argument
- For positional usage, add a placeholder arg in
argsto serve as$0:
{
"command": "bash",
"args": ["-c", "script using $1 for the message", "bash"],
"params": [
{
"name": "MSG",
"label": "Message",
"type": "text"
}
]
}{
"work_dir": "..",
"service": [
{
"name": "docs-preview",
"description": "Build and preview docs",
"command": "mdbook",
"args": ["serve", "--open"],
"params": [
{
"name": "--port",
"label": "Port",
"type": "text",
"required": false,
"description": "Port number (default: 3000)"
}
]
},
{
"type": "toolkit",
"name": "git",
"service": [
{
"name": "status",
"command": "git",
"args": ["status"]
},
{
"name": "log",
"command": "git",
"args": ["log", "--oneline", "-10"]
}
]
}
]
}work_dir is relative to .cmdsnap/. This lets you run tools from your
project root:
my-project/
βββ .cmdsnap/
β βββ config.json β work_dir: ".." means project root
βββ src/
βββ ...
| Key | Context | Action |
|---|---|---|
Up/Down |
Service list | Select service |
Right |
Service list | Enter toolkit |
Left |
Service list | Leave toolkit |
Enter |
Service list | Run / configure / enter toolkit |
Ctrl+S |
Any | Settings menu |
Ctrl+F |
Various | Cycle focus / toggle panels |
Ctrl+L |
Log view | Copy log + command to clipboard |
Ctrl+H |
Any | Browse run history |
Ctrl+C |
Log view | Kill running processes |
Ctrl+Q |
Any | Save and quit |
Esc |
Various | Back / cancel |
Colors are in theme.json. 17 slots map names to ANSI colors:
1: Running 2: Stopped 3: DirColor 4: FileColor
5: CmdColor 6: ArgColor 7: ActiveBg 8: ActiveFg
9: Border 10: FocusedBorder 11: KeyColor 12: NewFileColor
13: ParamLabelColor 14: ParamValueColor 15: ParamHintColor 16: PreviewColor
17: HintBg
Available colors: Black, Red, Green, Yellow, Blue, Magenta,
Cyan, White, DarkGray, LightRed, LightGreen, LightYellow,
LightBlue, LightMagenta, LightCyan, Gray.
MIT

