CLI
Snippety ships with a snippety command that lets you create, search, and
expand snippets straight from the terminal.
The CLI doesn't touch the database on its own - it talks to the running Snippety app. Everything you do stays in sync with the app window and iCloud, exactly as if you did it by hand.
The CLI requires Snippety Pro and a running Snippety app.
Installation
Open App Settings -> Integrations -> CLI and click Install.
Installing only creates a symlink at /usr/local/bin/snippety pointing to the
binary bundled inside the app. Updating Snippety therefore updates the CLI as
well, and uninstalling is just removing the symlink.
Because /usr/local/bin is owned by root, the two builds ask for permission
in different ways:
- Standalone: macOS asks for your administrator password.
- App Store: the app is sandboxed and cannot ask for elevated privileges, so you need to add the symlink manually. See Manual Installation below.
The Status section shows whether the CLI server inside the app is running.
If a different snippety binary is already on your PATH (for example one
installed with Homebrew), Snippety will not overwrite it. Remove it first, or
install the symlink manually.
Manual Installation
sudo mkdir -p /usr/local/bin && sudo ln -sf "/Applications/Snippety.app/Contents/Tools/snippety" /usr/local/bin/snippety
Auto-Completion
Snippety bundles completion scripts for commands, subcommands, and parameters.
In App Settings -> Integrations -> CLI click Copy Completion Command and
add the copied line to your shell profile (~/.zshrc):
source "/Applications/Snippety.app/Contents/Resources/completions/snippety.zsh"
The script is shipped inside the bundle, so sourcing it doesn't launch the CLI on every new shell.
Basics
snippety --help # every command
snippety <command> --help # options of a single command
snippety status # is the app reachable?
Selecting a Snippet
Most commands take a snippet selector: a name, a keyword, an id, or a
snippety:// deeplink. The form is inferred from what you type:
snippety get "Email signature"
snippety get sig
snippety get snippety://snippet?id=SNIPPET_ID
If the guess is wrong, force the interpretation:
| Option | Matches |
|---|---|
--id <id> | Snippet id |
--match-name <name> | Exact name |
--match-keyword <keyword> | Expansion keyword |
--match-deeplink <url> | snippety:// deeplink |
--last | Most recently expanded snippet |
--most-used | Most frequently expanded one |
Ids can be abbreviated to the short form printed by snippety list, the same
way git accepts short commit hashes. Add more characters if more than one
snippet matches:
snippety get 113A25BB
Global Options
Every command accepts:
| Option | Description |
|---|---|
--json | Print raw JSON instead of formatted output. |
--no-color | Never colorize output. The NO_COLOR environment variable works too. |
--timeout <seconds> | How long to wait for Snippety. Defaults to 30s, or 600s for backups and fill forms. |
Exit Codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Error |
3 | Snippety is not running |
4 | Snippety Pro required |
5 | Snippet not found |
6 | Timeout |
7 | Fill form dismissed |
64 | Usage error |
Commands
Snippets
| Command | Description |
|---|---|
expand | Print a snippet with its placeholders resolved. |
list | List snippets matching provided criteria. |
get | Print snippet details. |
add | Create a snippet. |
edit | Edit an existing snippet. |
delete | Delete one or more snippets. |
Grouping
| Command | Description |
|---|---|
collection list | List collections and how many snippets each holds. |
collection rename | Rename a collection, moving every snippet in it. |
collection delete | Delete a collection and every snippet inside it. |
tag list | List tags and how many snippets carry each. |
tag add | Create a tag with no snippets attached. |
tag rename | Rename a tag everywhere it's used. |
tag delete | Delete a tag and strip it from every snippet. |
tag assign | Attach tags to snippets. |
tag unassign | Detach tags from snippets. |
App
| Command | Description |
|---|---|
app-show | Reveal a snippet in the Snippety window. |
app-show-collection | Reveal a collection in the Snippety window. |
app-edit | Open a snippet in Snippety's editor. |
app-new | Open Snippety's new-snippet editor. |
Backup
| Command | Description |
|---|---|
export | Export every snippet and setting to a file. |
import | Import snippets from a file produced by export. |
Other
| Command | Description |
|---|---|
status | Check the connection to Snippety. |
stats | Show usage statistics. |
formats | List the syntax formats accepted by --format. |
config | Read and change Snippety settings. |
Expanding Snippets
snippety expand writes the resolved text to stdout with no trailing newline of
its own, so it composes with other tools:
snippety expand sig | pbcopy
git commit -m "$(snippety expand --match-keyword fixmsg)"
Passing Values
Snippets that ask for input take values with --var, applied in the order the
placeholders appear in the template - the same order the app's search bar fills
them:
snippety expand invite --var "Alice" --var "Monday 10am"
The search bar's inline form works
too, but < is a shell redirect, so the whole argument has to be quoted:
snippety expand "invite < Alice < Monday 10am"
Placeholders you leave uncovered fall back to their defaults.
Fill Form
Pass --show-form to be asked for the missing values instead. Snippety opens
its normal fill form, pre-filled with whatever you supplied, and the resolved
text is printed once you confirm:
snippety expand invite --show-form
snippety expand invite --var "Alice" --show-form | pbcopy
Dismissing the form exits with code 7 and prints nothing.
Expanding In The Front App
With --in-app the text never comes back to the terminal. Snippety expands the
snippet the way it does from its own search bar - pasting into whatever app is
in front (or copying, depending on your expansion mode) and asking for any
values you left out. The command returns immediately:
snippety expand sig --in-app
snippety expand invite --var "Alice" --in-app
Placeholders that run scripts or call AI can take a while. Raise --timeout if
you hit it.
This is the mode you want when a snippet is triggered by a global hotkey - see Global Hotkeys with skhd.
Listing & Searching
Without a query every snippet is listed. With one, it goes through the same search engine as the app.
snippety list
snippety list "reply email" --scope name --collection Work --json
snippety list --tag email --tag urgent
snippety list --expand
| Option | Description |
|---|---|
-s, --scope <scope> | Where to look: name, keyword, content, everywhere (default). |
-c, --collection <name> | Only snippets in this collection. Repeatable. |
-t, --tag <name> | Only snippets carrying this tag. Repeatable. |
-e, --expand | Resolve placeholders that need no input. |
Filters combine with OR.
Creating & Editing
The template can be given inline, read from a file, or piped in:
snippety add "License header" --template-file LICENSE.txt
pbpaste | snippety add "Clipboard grab"
snippety add "Signature" --keyword sig --tag email --template "Best,\nWojciech"
snippety edit touches only the fields you pass. Because an omitted option
means "leave alone", clearing a value needs an explicit flag:
snippety edit "Signature" --keyword sig
snippety edit --id 4F2C1A0B --template-file new.txt
snippety edit "Old note" --clear-tags --name "Archived note"
Available flags: --name, --template, --template-file, --keyword,
--description, --format, --collection, --tag, --quick-access /
--no-quick-access, --clear-collection, --clear-tags.
Deleting resolves every target first, so a typo in one name aborts the whole command instead of leaving it half-applied:
snippety delete "Old note"
snippety delete --id 4F2C1A0B --id 91BA33DE --yes
Collections & Tags
Collections have no records of their own - one exists as long as a snippet names
it. That's why there is no create: assign a collection when adding or editing
a snippet.
snippety collection list
snippety collection rename Work "Work Notes"
snippety collection delete Archive
For tags, add, rename, and delete act on the tag itself, while assign
and unassign change which snippets carry it:
snippety tag list
snippety tag assign email urgent --snippet "Signature" --snippet "Follow-up"
snippety tag unassign urgent --snippet "Signature"
snippety collection delete also deletes every snippet inside the collection.
Deleting a tag only strips it from your snippets.
Export & Import
snippety export writes the same JSON as the app's Export button, so the two
files are interchangeable.
snippety export ~/Backups/snippety.json
snippety export > snippety.json
snippety export --no-settings snippets-only.json
Importing replaces the database by default, exactly like the app's Import
button. Use --mode append to add to what's already there:
snippety import snippety.json
snippety import snippety.json --settings
snippety import team-snippets.json --mode append --collection Team
cat snippety.json | snippety import --yes
Settings are left alone unless --settings is passed, so restoring snippets on
a machine you already configured doesn't undo that configuration. See also
Import app settings.
Replacing asks for confirmation first. Piping the dump in takes stdin away from
the prompt, so that form needs --yes.
Snippety reads and writes these files itself, because a database of formatted snippets can run to hundreds of megabytes - more than the CLI connection carries. On the App Store build the app is sandboxed, so a path outside its container will be refused. Redirect stdout or pipe the dump in instead.
Settings
snippety config get lists every exposed setting with its current value.
Booleans take true or false.
snippety config get
snippety config set expansion-mode copyToClipboard
snippety config set prefix ":"
snippety config set suffixes "space return . ,"
| Key | Description |
|---|---|
expansion-mode | What happens after expanding: pasteToApplication, copyToClipboard, pasteAndCopy. |
expand-with-prefix | Require a prefix character before the keyword. |
prefix | The prefix character, or 2x space. |
expand-with-suffix | Expand only once a suffix character is typed. |
suffixes | Which suffixes trigger it, space-separated: . , ! space return tab nbsp. |
keep-suffix | Leave the typed suffix in place after expanding. |
require-double-suffix | Need the suffix twice, so ordinary punctuation doesn't expand. |
expand-within-words | Expand even when the keyword is glued to other characters. |
expand-selected | Expand only snippets in the collection and tags selected in the app. |
See Snippet Expander for what these options do.
Global Hotkeys with skhd
Snippety gives its own hotkeys to the search bar and the Quick Access Menu, but not to individual snippets. With the CLI you can bind any snippet to any key combination yourself, using skhd - a tiny hotkey daemon for macOS.
brew install koekeishiya/formulae/skhd
skhd --start-service
macOS will ask for Accessibility permission the first time the service starts.
Hotkeys are declared in ~/.config/skhd/skhdrc, one per line, as
modifiers - key : command:
# Paste the signature into whatever app is in front
cmd + alt - s : /usr/local/bin/snippety expand sig --in-app
# Placeholders you don't pass are asked for in Snippety's fill form
cmd + alt - i : /usr/local/bin/snippety expand invite --in-app
# Put an expanded snippet on the clipboard instead
cmd + alt - c : /usr/local/bin/snippety expand sig | pbcopy
Reload the config after editing it:
skhd --restart-service
Always use the full path /usr/local/bin/snippety. skhd runs commands from a
non-interactive shell that doesn't load your ~/.zshrc, so a bare snippety
may not be found.
--in-app is what makes this useful: the text goes to the front app exactly as
if you expanded the snippet from Snippety's search bar, and any values you left
out are asked for in the fill form. Without it the output would be printed to a
terminal that isn't there.
A Leader Key for Snippets
Binding one combination per snippet runs out of free keys quickly. skhd modes
let you press a leader key first and then a single letter, the way tmux and
Vim leader mappings work:
:: default
:: snippets @
# Enter the snippet layer
cmd + alt - space ; snippets
# Inside the layer, one letter per snippet
snippets < s : /usr/local/bin/snippety expand sig --in-app; skhd -k 'escape'
snippets < i : /usr/local/bin/snippety expand invite --in-app; skhd -k 'escape'
snippets < m : /usr/local/bin/snippety expand meeting --in-app; skhd -k 'escape'
# Leave the layer
snippets < escape ; default
The @ marks the mode as capturing, so keys that aren't mapped do nothing
instead of reaching the app underneath. Each action ends with
skhd -k 'escape', which triggers the last line and drops you back to
default.
snippety list --json prints every snippet with its keyword, which makes it
easy to see what is worth a hotkey - and snippety stats shows what you expand
most often.
Troubleshooting
Snippety is not running(exit code 3): start the app. The CLI needs it.Snippety Pro required(exit code 4): the CLI is a Pro feature. Runsnippety statusto confirm the license state.- Command not found: the symlink was not installed, or
/usr/local/binis not on yourPATH. Reinstall fromApp Settings -> Integrations -> CLIor use the manual command above. - A different
snippetyis on the PATH: remove the other binary, then install again. - An skhd hotkey does nothing: run the same line in a terminal first. If it works there but not from skhd, use the absolute path to the binary and check that skhd has Accessibility permission.