How to Use Clipboard and Screenshot Tools From the CLI
Use clipboard and screenshot tools from the CLI: pbcopy, xclip, wl-copy, screencapture, grim and maim, with a portable wrapper for scripts.

Sending output to the clipboard instead of selecting it by hand, or capturing a window to a file from a script, are two of the small habits that make a terminal workflow quick. The commands differ by platform, and a wrapper hides that. The examples use macOS 14, maim 5.7 and grim 1.4; the deeper Linux versions are in clipboard automation on Linux and screenshots on Linux.
The clipboard
git rev-parse HEAD | pbcopy # macOS
git rev-parse HEAD | xclip -selection clipboard # X11
git rev-parse HEAD | wl-copy # Wayland
pbpaste | wc -lThe tool reads standard input and puts it on the clipboard, and the paste command prints it. On X11, xclip needs -selection clipboard to use the buffer behind Ctrl-V, otherwise it fills the primary selection. Trailing newlines matter: printf '%s' "$text" | pbcopy avoids adding one. Over SSH, the remote clipboard is not yours; terminals that support the OSC 52 escape sequence let a remote program set the local clipboard.
Screenshots
screencapture -i ~/shots/$(date +%F_%H-%M-%S).png # macOS: interactive selection
screencapture -c # to the clipboard
maim -s ~/shots/area.png # X11: select an area
grim -g "$(slurp)" ~/shots/area.png # Wayland: select an area
grim -g "$(slurp)" - | wl-copy --type image/png # to the clipboardscreencapture is built into macOS, and the first use asks for the Screen Recording permission for the terminal, which is a common cause of blank images. -i selects, -w picks a window and -c copies to the clipboard. grim with slurp is the Wayland pair for wlroots-based compositors, and GNOME and KDE use their own tools through portals. Writing to - sends the image to stdout, which pipes to the clipboard tool.
A portable wrapper
clip() {
if command -v pbcopy >/dev/null; then pbcopy
elif [[ -n ${WAYLAND_DISPLAY:-} ]] && command -v wl-copy >/dev/null; then wl-copy
elif command -v xclip >/dev/null; then xclip -selection clipboard
elif command -v xsel >/dev/null; then xsel --clipboard --input
else echo "no clipboard tool found" >&2; return 1; fi
}
shot() {
local f=${1:-$HOME/shots/$(date +%F_%H-%M-%S).png}
mkdir -p "$(dirname "$f")"
if command -v screencapture >/dev/null; then screencapture -i "$f"
elif [[ -n ${WAYLAND_DISPLAY:-} ]]; then grim -g "$(slurp)" "$f"
else maim -s "$f"; fi
echo "$f"
}
uptime | clipPut these in a dotfiles repository so every machine has them, see aliases versus a tools repository. The functions choose the tool at call time, so the same dotfiles work on a Mac, an X11 desktop and a Wayland session. The detection by WAYLAND_DISPLAY matters because X11 tools capture only XWayland windows under Wayland, often as a black image.
Useful combinations
history | tail -20 | clip
ssh web1 'journalctl -u app -n 50 --no-pager' | clip
cat ~/.ssh/id_ed25519.pub | clipCopy a public key, a log excerpt or the last commands to paste into a ticket or chat, and check what you copy first: logs and history can contain secrets, and a clipboard manager keeps entries on disk. Clear sensitive values afterwards, as discussed in password store and keyring from the terminal.
What the clipboard tools really do
A clipboard is a service, and a command line tool is a client of it. On macOS, pbcopy and pbpaste talk to the pasteboard server, which holds typed data, so the same copy can offer plain text, rich text and an image at once. On X11 the owner of the selection holds the data and serves it on request, which has a consequence that surprises people: when the program that copied the text exits, the clipboard content disappears with it, unless a clipboard manager has taken ownership. xclip forks into the background to stay alive as the owner, and exits after the first paste unless you ask it to keep serving. Wayland follows a similar model, and wl-copy likewise stays resident, so that a script which copies and immediately quits may find the content gone when the owner is a short-lived process.
Two selections exist on X11 and in many Wayland compositors. The clipboard is the one filled by Ctrl-C and read by Ctrl-V. The primary selection is filled by merely highlighting text and read with a middle click. Tools default to different ones, which explains most "it copied but will not paste" reports; name the selection explicitly in scripts.
Text, binary data and encodings
Copying text is easy and copying anything else needs a MIME type. wl-copy --type image/png < shot.png and xclip -selection clipboard -t image/png -i shot.png put an image on the clipboard so that a chat window or an editor can paste it. Reading it back uses wl-paste --type image/png or xclip -o -t image/png. List what is offered with wl-paste --list-types or xclip -o -t TARGETS, which shows why a paste into one program gives text and into another gives an image.
Encoding is the other trap. The clipboard stores bytes with a declared type, and a terminal pipeline hands the tool whatever the previous command printed. Make sure the locale is UTF-8, or accented letters turn into question marks in the destination. On macOS, pbcopy uses the locale of the process, and in a script started from launchd that may be the C locale, so set LANG=en_US.UTF-8 when text looks damaged.
Over SSH and inside tmux
A remote shell cannot reach your desktop clipboard through pbcopy, because the tool runs on the remote machine. Terminals that support the OSC 52 escape sequence solve this: a program writes a specially formatted string to the terminal, and the terminal puts the decoded content on the local clipboard. The sequence is printf '\033]52;c;%s\a' "$(printf '%s' "$text" | base64)", and tmux can pass it through when set-clipboard is on. Support differs between terminals and some disable it for safety, since a remote program can otherwise write to the local clipboard silently. Treat anything pasted from a remote-controlled clipboard with the same care as typed input, and read it before running it.
Screenshots as part of a bug report
The most common reason to combine these tools is to attach a picture of a problem to a report. A short function can capture a selection, save it with a timestamp and place it on the clipboard in one step, so the next paste into the ticket system uploads the image. Keep the saved file too, because the clipboard holds one item at a time and the next copy replaces it. When the image shows a terminal, set a readable font size first and crop to the relevant lines, since a full-screen capture of a mostly empty window is harder to read than three lines of output.
Habits that keep the clipboard safe
A clipboard is shared with every program in the session, and clipboard managers write history to disk. Avoid copying tokens, private keys and passwords through it when another route exists, such as reading a secret straight into a command from a password manager's command line tool. When a secret must be copied, set a short expiry: many password managers clear the clipboard after thirty seconds, and a one-line sleep 30; pbcopy < /dev/null & does the same by hand. Check the clipboard manager's own settings for an option to ignore entries from the terminal or from specific applications.
Where this does not apply
A script running from cron or a service has no display and no clipboard, so these tools fail there; use a file or a notification instead, see shell script notifications. For a web page, a headless browser takes screenshots without a screen. See the screencapture manual summary and the wl-clipboard project.


