Your local command library.
Save shell commands you always forget. Find them instantly. Run them safely.
Built with Bun, SQLite, Ink, and zero cloud dependencies.
- Bun v1.0+
bun install -g clipsnipcs # home screen + snippet count
cs run # interactive picker (persistent session)| Command | Description |
|---|---|
cs add "desc" -- <cmd> |
Save a new snippet |
cs list |
Show all snippets |
cs search <query> |
Fuzzy search by description |
cs search <query> --tag <tag> |
Search within a tag |
cs run [desc] |
Run a snippet (interactive if no arg) |
cs run <desc> --with val1 val2 |
Run with template values |
cs run <desc> --dry-run |
Preview resolved command |
cs edit <desc> -- <new-cmd> |
Update a snippet's command |
cs edit <desc> --desc <new-desc> |
Rename a snippet |
cs edit <desc> --tag <tags> |
Change tags (preserves tag otherwise) |
cs copy <desc> |
Copy command to clipboard |
cs delete <desc> |
Delete a snippet |
cs history |
Show recent adds and edits |
cs history <desc> |
Show history for one snippet |
cs export > file.json |
Export all snippets |
cs import file.json |
Import snippets (skips duplicates) |
cs import --replace file.json |
Import and replace everything |
cs uninstall |
Remove all data and config |
cs run opens a persistent interactive session. You never leave it just to run a command — info commands print their output and return you to the picker.
| Key | Action |
|---|---|
↑ ↓ |
Navigate snippets |
↵ |
Run selected snippet |
tab |
Enter slot-fill for a template |
/ |
Open command palette |
esc |
Quit / back |
ctrl+c |
Exit cleanly |
Type / from the search screen to open the palette. Type to filter, ↑↓ to navigate, ↵ to run.
| Command | Description | Args |
|---|---|---|
/add |
Add a new snippet inline | description, command |
/search |
Fuzzy search | query |
/list |
List all snippets | — |
/history |
View recent edits | — |
/edit |
Edit a snippet | pick snippet, new command |
/delete |
Delete a snippet | pick snippet |
/copy |
Copy to clipboard | pick snippet |
/import |
Import from a JSON file | file path |
/export |
Export to JSON (stdout) | — |
/help |
Show all commands | — |
/uninstall |
Remove all data (confirms inline) | type "yes" |
Commands that target an existing snippet (/edit, /delete, /copy) open a sub-picker — the full snippet list with fuzzy search. Pick with ↵, esc to go back.
Store commands with {{named}} placeholders and fill them at runtime:
cs add "git commit" -- git commit -m "{{message}}"
cs run "git commit" --with "fix navbar bug"
# runs: git commit -m 'fix navbar bug'
cs add "docker tag" -- docker tag {{source}} {{target}}
cs run "docker tag" --with myapp:latest registry/myapp:v1In the interactive picker, tab or ↵ on a template snippet opens slot-fill mode — step through each placeholder with a live preview of the resolved command.
Use --dry-run to preview before executing:
cs run "docker tag" --with myapp:latest registry/myapp:v1 --dry-run
# dry-run: docker tag 'myapp:latest' 'registry/myapp:v1'Values are shell-escaped automatically — injection attempts are treated as literal strings.
Tags are auto-detected from the first word (basename) of your command:
cs add "prune docker" -- docker system prune -af
# auto-tagged: #docker
cs add "deploy" --tag k8s -- kubectl apply -f .
# override tag: #k8sTags are preserved when you edit a command without specifying --tag:
cs edit "deploy" -- helm upgrade myapp ./chart
# tag remains: #k8s
cs edit "deploy" --tag helm -- helm upgrade myapp ./chart
# tag updated: #helmSearch within a tag:
cs search "prune" --tag docker| Platform | Path |
|---|---|
| macOS | ~/Library/Application Support/clipsnip/snippets.db |
| Linux | ~/.local/share/clipsnip/snippets.db |
| Config | ~/.config/clipsnip/config.json |
XDG environment variables (XDG_DATA_HOME, XDG_CONFIG_HOME) are respected.
Data directories are migrated from snip/ to clipsnip/ automatically on first launch. No manual steps required.
~/.config/clipsnip/config.json:
{
"colors": true
}Set "colors": false or export NO_COLOR=1 to disable color output.
NO_COLOR takes precedence over the config file and applies to both the CLI output and the interactive UI.
cs uninstall # removes all data and config
bun remove -g clipsnip # removes the binaryOr from inside cs run, open the palette with / and select /uninstall.
All --with values and inline slot-fill values are POSIX single-quote escaped before execution. Commands run via sh -c so pipes and redirects in stored commands work.
cs run "echo test" --with '$(rm -rf ~)'
# runs: echo '$(rm -rf ~)' ← literal string, not executedgit clone https://github.com/grimmy-dev/clipsnip
cd clipsnip
bun install # also installs the pre-commit hook
bun test # run all tests
bun test --watch # watch mode
bun run typecheck # type-check without emittingsrc/
index.ts entry point — wires Commander, nothing else
commands.ts CLI handlers + interactive palette dispatcher
snippets.ts service layer — business logic, throws CliError
db.ts SQLite connection, schema, prepared statements
shell.ts shell escaping, template resolution, tag helpers
format.ts terminal color helper, table printer
config.ts config loading, NO_COLOR flag
paths.ts data/config directory resolution, v1.0.x migration
__tests__/
shell.test.ts unit tests — pure functions, no DB
snippets.test.ts integration tests — in-memory SQLite
ui/
index.ts public exports — launchSelector, renderHome
selector.tsx interactive picker — all five modes
home.tsx home screen rendered by `cs` with no subcommand
theme.ts color tokens, NO_COLOR helper, layout constants
components/
Banner.tsx figlet banner with gradient
SnippetRow.tsx single row in the snippet list
KeyHints.tsx footer key-hint bar
scripts/
install-hooks.ts installs pre-commit git hook on bun install
bun src/index.ts add "test" -- echo hello
bun src/index.ts run- Bun — runtime + SQLite
- Ink — interactive terminal UI
- Commander — CLI framework
- Fuse.js — fuzzy search
MIT — see LICENSE
Found a bug or something not working as expected? Please open an issue on the repository — all reports and accessibility-related feedback are welcome.
