Documentation

ClipSlots reference

Every command, every config option. For the 30-second pitch see clipslots.dev.

Getting started

Install #

Install via Homebrew, grant accessibility, start the daemon. Three commands, ~30 seconds.

$ brew tap olafglad/clipslots
$ brew install clipslots
$ clipslots permissions   # grant accessibility (one-time)
$ clipslots start

Other install methods (.pkg download, build from source) are listed on the GitHub releases page.

First-time setup #

ClipSlots needs macOS accessibility permission to register global hotkeys. Without it, the daemon runs but hotkeys do nothing.

  1. Run clipslots permissions — it opens System Settings → Privacy & Security → Accessibility.
  2. Find clipslots in the list and toggle it on.
  3. Run clipslots start. The daemon launches and registers your hotkeys. It will also start on login from now on.
  4. Copy something, press Ctrl+Option+1, then press Ctrl+1 to paste it back.

Keybind syntax #

Hotkeys are configured in ~/.config/clipslots/config.toml under [keybinds]. Each value is a string with +-separated modifiers and one key. Use {n} as a placeholder for the slot number — ClipSlots registers one hotkey per slot (1 through your configured slots count).

ModifiersKeysPlaceholder
ctrl, option, cmd, shift 0-9, a-z, f1-f12 {n} = slot number

Examples:

# Default: Ctrl+Option+N to save, Ctrl+N to paste
save  = "ctrl+option+{n}"
paste = "ctrl+{n}"

# Cmd+Shift+N to save, F-keys to paste
save  = "cmd+shift+{n}"
paste = "f{n}"

Config changes hot-reload — no restart needed. If a binding conflicts with another app, the daemon logs a warning and skips that slot.

Daemon

start#

Start the ClipSlots daemon and install a launchd agent so it boots on login.

$ clipslots start

stop#

Stop the daemon and unload the launchd agent. Hotkeys go inert until you start again.

$ clipslots stop

restart#

Stop the daemon, then start it again. Useful after a manual binary swap. Most config changes hot-reload, so you rarely need this.

$ clipslots restart

status#

Show daemon state, accessibility permission, slot usage, and active keybinds. In a wide colour TTY it renders a fastfetch-style layout with the ClipSlots ASCII logo; piped output or NO_COLOR=1 falls back to plain stacked sections.

$ clipslots status

permissions#

Check accessibility and pasteboard permission state, and open System Settings → Privacy & Security if accessibility is not granted yet. Idempotent — safe to run any time.

$ clipslots permissions

Slots

save#

Save the current clipboard contents into a slot. Works with text, images, RTF, HTML, and file references — whatever the pasteboard holds. The equivalent of pressing your save hotkey.

$ clipslots save <slot>
$ clipslots save 3
$ echo "hi" | pbcopy && clipslots save 5

Refuses to overwrite locked slots. Saving an empty clipboard is a no-op.

paste#

Load a slot's content back onto the system clipboard. The equivalent of pressing your paste hotkey.

$ clipslots paste <slot>
$ clipslots paste 3

peek#

Print a slot's text content to stdout without touching the clipboard. Useful for shell scripting and quick inspection. Non-text slots (images, files) print a short type description instead of binary data.

$ clipslots peek <slot> [--truncate <N>]
$ clipslots peek 3
$ TOKEN=$(clipslots peek 7)
$ diff <(clipslots peek 1) <(clipslots peek 2)
FlagDescription
--truncate NTruncate output to N characters (no truncation by default).

list#

Show every slot with a content preview, age, and (when colour is on) a lock indicator. Use --verbose for size and type metadata, or --grep to filter.

$ clipslots list [--grep <pattern>] [--verbose]
$ clipslots list
$ clipslots list --verbose
$ clipslots list --grep token
FlagDescription
--grep PATTERNFilter slots whose label or preview contains the pattern (case-insensitive).
-v, --verboseShow per-slot size, type, age, label, and lock state.

open#

Open a slot in the appropriate application based on its content type — text in $EDITOR, files in their default app, images in Preview, rich text in TextEdit.

$ clipslots open <slot>
$ clipslots open 3

clear#

Clear a single slot or every slot. Locked slots are protected by default — use --force to wipe them too, or --keep-locked to skip them non-interactively.

$ clipslots clear [<slot>] [--force] [--keep-locked]
$ clipslots clear 3
$ clipslots clear 3 --force
$ clipslots clear --keep-locked
FlagDescription
<slot>Optional. Omit to target every slot.
--forceClear every slot, including locked ones. Non-interactive.
--keep-lockedClear only unlocked slots. Non-interactive.

Organize

label#

Attach a human-readable label to a slot so you can spot it in list output. Labels persist across writes and survive the manifest cache being rebuilt.

$ clipslots label <slot> [<name>] [--clear]
$ clipslots label 3 "API token"
$ clipslots label 3 --clear

lock#

Lock a slot so save, clear, and undo refuse to touch it. Useful for slots holding tokens or boilerplate you don't want to overwrite by accident.

$ clipslots lock <slot>
$ clipslots lock 3

unlock#

Unlock a slot so it can be overwritten again.

$ clipslots unlock <slot>
$ clipslots unlock 3

swap#

Exchange the contents of two slots. Labels and lock state move with the content.

$ clipslots swap <a> <b>
$ clipslots swap 1 4

copy#

Duplicate the contents of one slot into another, overwriting the destination (unless it is locked).

$ clipslots copy <src> <dst>
$ clipslots copy 1 4

undo#

Swap a slot with its prior content. Each slot keeps one undo snapshot, taken at the moment of its last write — running undo twice round-trips back to the current value. Locked slots are protected.

$ clipslots undo <slot>
$ clipslots undo 3

Backup

export#

Bundle all slots, labels, and locks into a single tar archive — for backup, machine migration, or sharing a snapshot of your boilerplate.

$ clipslots export <path>
$ clipslots export ~/clipslots-backup.tar

import#

Restore slots from a tar archive previously created by export. By default, non-empty slots in the destination are preserved — pass --force to overwrite them.

$ clipslots import <path> [--force]
$ clipslots export ~/clipslots-backup.tar
$ clipslots import ~/clipslots-backup.tar --force
FlagDescription
--forceOverwrite existing non-empty slots.

Config

config#

Print the current configuration: config-file path, general settings, and active keybinds. Reads the same file the daemon does.

$ clipslots config

config edit#

Open ~/.config/clipslots/config.toml in $EDITOR (or nano if unset). The daemon hot-reloads on save — no restart needed.

$ clipslots config edit

config validate#

Parse and validate the config file. Exits non-zero with a specific error and file path on stderr if something is wrong — handy in shell scripts or pre-commit hooks for a synced dotfiles repo.

$ clipslots config validate

config path#

Print the absolute path to the config file. Composes nicely with other tools.

$ clipslots config path
$ vim $(clipslots config path)

Configuration

config.toml schema #

ClipSlots reads ~/.config/clipslots/config.toml. Every option is optional — omit any line and ClipSlots uses a sensible default. The daemon hot-reloads on save.

# Number of slots (1-10)
slots = 5

# Show daemon logs in terminal (true/false)
verbose = true

# Optional: auto-expire stale slots after this many hours.
# Locked slots are never expired. Omit to disable.
# expire_after_hours = 24

# Optional: play a system sound on successful hotkey actions.
# Valid values: "off", "sound". CLI commands never play sound.
# feedback = "sound"

[keybinds]
save  = "ctrl+option+{n}"
paste = "ctrl+{n}"

# Optional: append-mode hotkey. See "Append mode" below.
# append           = "ctrl+option+shift+{n}"
# append_separator = "\n"
KeyTypeDefaultDescription
slots int 5 How many slots to register hotkeys for. 1–10.
verbose bool true Write save/paste actions and errors to /tmp/clipslots.log.
expire_after_hours int off Auto-clear slots untouched for N hours. Locked slots are never expired.
feedback string "off" Play a system sound on successful hotkey actions. "off" or "sound".
keybinds.save string "ctrl+option+{n}" Hotkey to save the clipboard into slot N.
keybinds.paste string "ctrl+{n}" Hotkey to paste slot N back onto the clipboard.
keybinds.append string off Optional hotkey to append clipboard text to a slot. See Append mode.
keybinds.append_separator string "\n" Separator inserted between existing content and the appended text.

Append mode#

Append mode is an optional third hotkey that adds clipboard text to an existing slot instead of overwriting it — handy for collecting snippets while you read or research. Disabled by default. Uncomment the two lines under [keybinds] to enable.

[keybinds]
save             = "ctrl+option+{n}"
paste            = "ctrl+{n}"
append           = "ctrl+option+shift+{n}"
append_separator = "\n"

Appending to an empty slot acts as a normal save. Appending to a locked slot, or appending non-text clipboard content, is silently skipped. Rich-text slots collapse to plain text on append.

Slot expiry#

Set expire_after_hours to automatically clear stale slots. The daemon sweeps once per hour and clears any slot whose last write is older than the threshold. Locked slots are never expired.

# Clear slots untouched for more than 24h
expire_after_hours = 24

Sound feedback#

When feedback = "sound", the daemon plays a short system sound on successful save, paste, or append from a hotkey. CLI commands (clipslots save 3 etc.) never play sound — only hotkeys do.

feedback = "sound"

Reference

Troubleshooting#

Hotkeys do nothing after install

Almost always missing accessibility permission. Run clipslots permissions, toggle clipslots on in System Settings, then clipslots restart.

Accessibility permission doesn't stick after rebuild

macOS ties accessibility to the binary's code signature. Unsigned (or differently-signed) builds register as a new app and lose permission. The Homebrew and .pkg distributions are signed consistently and don't have this issue.

Daemon won't start

Check /tmp/clipslots.err for the actual error. Common causes: another process bound a hotkey first (the daemon logs which one), or the config file has a syntax error (clipslots config validate will say so).

A specific hotkey doesn't fire

Some macOS shortcuts (Ctrl+Space, Cmd+Tab) and third-party tools like Raycast, Alfred, or Karabiner can claim a binding before ClipSlots gets it. Try a different combo (see the keybind syntax) or check the offending app's hotkey settings.

Saved an image but pasting gives garbled text

Some apps only accept the clipboard type they expect. ClipSlots restores the original pasteboard types faithfully — if the destination app only reads text, an image won't show. Try pasting into Preview or Finder to confirm the slot does contain an image.

How do I uninstall?

clipslots stop to unload the daemon, then brew uninstall clipslots. Slot data lives at ~/.local/share/clipslots/ and config at ~/.config/clipslots/ — delete those too for a full wipe.

File paths#

PathWhat
~/.config/clipslots/config.tomlConfiguration file.
~/.local/share/clipslots/slots/Slot contents, labels, locks.
~/Library/LaunchAgents/com.clipslots.daemon.plistlaunchd agent that boots the daemon on login.
/tmp/clipslots.logDaemon stdout (when verbose = true).
/tmp/clipslots.errDaemon stderr — check here when something breaks.