
Cleanshotx
- 3 installs
- Updated August 3, 2026
- ljagiello/agent-skills
Helps with ai & agent building tasks during AI-assisted development.
About
cleanshotx is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- cleanshotx
- AI & Agent Building
- AI-coding skill
Cleanshotx by the numbers
- 3 all-time installs (skills.sh)
- Ranked #13,657 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/ljagiello/agent-skills --skill cleanshotxAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3 |
|---|---|
| Last updated | August 3, 2026 |
| Repository | ljagiello/agent-skills ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Driving CleanShot X via the cleanshot:// URL scheme
CleanShot X is a macOS screenshot and screen-recording app from MagicLasso. It exposes a URL scheme (cleanshot://command?param=value&…) that triggers any of its capture, recording, OCR, annotation, pin, history, or settings actions. Opening such a URL launches the app (if needed) and runs the action. That URL scheme is the only supported automation surface — there is no public CLI, AppleScript dictionary, or HTTP API. macOS Shortcuts.app actions internally invoke the same scheme.
The full per-command reference with every parameter and version constraint lives in references/url-scheme.md. Read it before automating any command this SKILL.md does not show in full.
Gotchas — read these before automating
- Requires an Aqua login session.
open "cleanshot://…"goes through LaunchServices and the app's UI. It needs an active logged-in graphical session for the same user — over SSH it fires only when that user is also logged in locally. It will not run from a launchdBackgroundagent or before login. Use a user-context launchd agent (LimitLoadToSessionType: Aqua), Screen Sharing, or run it as a step inside a logged-in session. - CleanShot X must be installed and able to launch. If the app is not installed, opening the URL silently does nothing or prompts the user to choose an app. Verify with
mdfind "kMDItemCFBundleIdentifier == 'pl.maketheweb.cleanshotx'", or check the common install paths:/Applications/CleanShot X.app(direct/App Store) and~/Applications/Setapp/CleanShot X.app(Setapp). - No return value, no completion signal. The URL fires asynchronously; the calling shell gets exit code 0 as soon as
openhands off. There is no built-in way to wait for "capture finished" or to recover the resulting file path. To know what happened: inspect the configured save folder (CleanShot ▸ Settings ▸ Screenshots ▸ "Save to") or watch the clipboard. - URL parameters must be URL-encoded. Spaces in a
filepathbecome%20. Always quote the URL when passing it toopen, and percent-encode user-supplied paths. See the helper at the bottom of this file. - Version-gated parameters may not work on older builds. Parameters added in 4.7 (
action=…,x/y/width/height/displayon most commands,start=true,autoscroll=true,tab=…) are not supported on earlier versions and are typically ignored — the command still runs without the parameter. Don't rely on a version-gated parameter without first checkingdefaults read "/Applications/CleanShot X.app/Contents/Info" CFBundleShortVersionString. - `action` is a single value, not a chain.
action=annotatealone is valid;action=copy,uploadis not. Pick one ofcopy | save | annotate | upload | pin. To compose actions (e.g. annotate then upload), drive subsequent steps from a follow-up URL or from the annotator UI. - `filepath` parameter rules. When you supply a
filepathto any command that takes one (pin,open-annotate,capture-text,add-quick-access-overlay), it must be an absolute path — not~-relative. Expand~in the shell before passing. The parameter is optional forpin/open-annotate/capture-text(omitting it falls back to an interactive picker or area selection — see references/url-scheme.md) and required foradd-quick-access-overlay. Accepted formats: PNG and JPEG for screenshot commands;add-quick-access-overlayadditionally accepts MP4. - `capture-window` is always interactive — wrong tool for "screenshot the X window" automation. It enters a hover-and-click selection mode; there is no parameter to target a window by name, PID, or window ID. For unattended capture of a known window, use
capture-areawith explicitx,y,width,height(4.7+) computed from the window's frame — see Capture a specific named window unattended below. Do not drop down toscreencapture -ljust becausecapture-windowdoes not fit; CleanShot's URL scheme can do this headlessly. - Don't infer point dimensions by halving a Retina pixel resolution.
system_profiler SPDisplaysDataTypereportsResolution: 3456 x 2234 Retina— that is the native pixel grid. Dividing by 2 happens to be right on the default macOS display mode but is wrong on any scaled mode ("More Space", "Larger Text"), where points are decoupled from native pixels. Read points directly: AppleScripttell application "Finder" to get bounds of window of desktop(main display, 4th comma-field), or JXANSScreen.frame.size.height(any display) — both return points. - The save-folder defaults key is `exportPath`, not `CaptureFolder`.
defaults read pl.maketheweb.cleanshotx CaptureFolderdoes not exist — the command errors with a non-zero exit and any|| echo "$HOME/Desktop"fallback silently leaves you scanning~/Desktop, where the file will never appear if the user has moved their save folder. Always readexportPath(the user's "Save to" path from CleanShot ▸ Settings ▸ Screenshots). - Stick to stock macOS — do not reach for PyObjC. Tempting alternatives like
python3 -c "import Quartz; ..."orfrom AppKit import NSScreenwill fail withModuleNotFoundErroron a default install: PyObjC ships with Apple's system Python 2 historically but is not present in/usr/bin/python3or in Homebrew Python withoutpip install pyobjc. Useosascript(AppleScript or JavaScript-for-Automation) instead — it always works. - Apple-backend / sandbox surprises. Capturing a window or area may require Screen Recording permission for the app. Recording the screen also requires Microphone permission if audio is enabled. The first run of any command may surface a TCC prompt that needs a user click — agents cannot auto-accept TCC.
- `scrolling-capture` only proceeds with `start=true` on 4.7+; without it the user has to click "Start" in the overlay. Use
start=true&autoscroll=truefor a fully unattended capture (4.7+). - `record-screen` does not stop itself. There is no
stop-recordingURL. Stop recording from the menu-bar item, the global shortcut (default ⌘⇧⌥3 stop, or click the floating control), or by sending acleanshot://record-screentoggle — but the toggle behavior depends on the user's settings and is not guaranteed. Treat recording as user-supervised. - `display=` is a 1-based index of the display ordering CleanShot sees. Display 1 is typically the main display; multi-display indices may not match
system_profiler SPDisplaysDataTypeordering. Test on the target machine. - No undo for `delete`-style actions inside CleanShot. The URL scheme has no destructive commands directly, but
restore-recently-closedandopen-historyboth touch the history database — back it up before bulk operations.
Quick start: invoking the URL scheme
The single primitive is open with a cleanshot:// URL. From a shell:
# Launch the area-selection capture, then open the result in the annotator.
open "cleanshot://capture-area?action=annotate"
# Repeat the previous-area capture and copy the result to the clipboard.
open "cleanshot://capture-previous-area?action=copy"
# OCR text out of an existing image and copy it to the clipboard.
open "cleanshot://capture-text?filepath=/Users/me/Desktop/screenshot.png&linebreaks=true"
# Pin an image on top of all windows.
open "cleanshot://pin?filepath=/Users/me/Desktop/diagram.png"
# Open the Recording tab in CleanShot's settings.
open "cleanshot://open-settings?tab=recording"From AppleScript / osascript:
osascript -e 'open location "cleanshot://capture-fullscreen?action=upload"'From Python (when you need URL-encoding done for you):
import subprocess, urllib.parse, pathlib
path = pathlib.Path("~/Desktop/My Screenshot.png").expanduser().resolve()
url = "cleanshot://pin?filepath=" + urllib.parse.quote(str(path), safe="/")
subprocess.run(["open", url], check=True)Command catalog (summary)
The 19 commands fall into seven groups. For full parameters, defaults, and per-parameter version requirements, see references/url-scheme.md.
| Group | Commands |
|---|---|
| Screenshots | capture-area, capture-previous-area, capture-fullscreen, capture-window, self-timer, scrolling-capture, pin |
| Recording | record-screen |
| OCR | capture-text |
| Annotation | open-annotate, open-from-clipboard |
| All-In-One | all-in-one |
| Desktop icons | toggle-desktop-icons, hide-desktop-icons, show-desktop-icons |
| History / overlays / settings | add-quick-access-overlay, open-history, restore-recently-closed, open-settings |
Common parameter shapes:
action=copy | save | annotate | upload | pin— what to do with the result. Requires CleanShot 4.7+. Default is whatever the user has configured in CleanShot ▸ Settings ▸ Screenshots ▸ "After capture".x,y,width,height,display— capture region. Requires 4.7+ on most commands. Coordinates use the macOS native coordinate system: origin (0,0) is the lower-left corner of the screen, withyincreasing upward (per the CleanShot docs). Units are points, not Retina pixels.displayis a 1-based integer; if omitted it defaults to the display under the cursor.filepath— absolute path to a PNG or JPEG (MP4 also foradd-quick-access-overlay). Must be URL-encoded.
Common workflows
One-shot: capture an area and upload to the cloud
open "cleanshot://capture-area?action=upload"The user drags out a region; CleanShot uploads to the configured destination (CleanShot Cloud, S3, Dropbox, etc.) and copies the resulting URL to the clipboard. The URL is not returned to the caller — read it from the clipboard:
pbpaste # → https://cln.sh/abcd1234Repeat the previous capture region and save to disk
Useful for taking a sequence of "same region" shots while a UI updates:
open "cleanshot://capture-previous-area?action=save"OCR text out of an image file
open "cleanshot://capture-text?filepath=$(python3 -c 'import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))' "$HOME/Downloads/menu.jpg")&linebreaks=false"
sleep 1
pbpaste # OCR'd textlinebreaks=false flattens the text into a single paragraph; true preserves line breaks. CleanShot's standard OCR flow writes the recognized text to the clipboard — read it with pbpaste (the URL itself returns nothing).
Capture a specific named window unattended
The right tool for "screenshot Ghostty's window" with no clicks is not capture-window (that command always opens an interactive picker). It is capture-area with explicit x/y/width/height (4.7+) computed from the window's frame, plus action=save. The only twist is the coordinate flip: macOS UI APIs (System Events, AppKit, Accessibility) report top-left-origin bounds, but CleanShot's URL scheme uses the lower-left origin (cs_y = display_height - top_y - height).
The snippet below uses only tools shipping in stock macOS — osascript (AppleScript and JXA), defaults, find. Do not reach for PyObjC / import Quartz / pip install pyobjc here: those are not part of a stock macOS python3, and any agent that tries them will hit ModuleNotFoundError: No module named 'Quartz'. AppleScript covers everything you need.
There are two flavours of "the right window":
- "This window" (the one the user is currently looking at, e.g. when the user types "screenshot this window" inside the agent's host terminal). Resolve the frontmost application's frontmost window — do not hard-code an app name like
Ghostty, because that breaks the moment the user runs the agent inside iTerm2, Terminal.app, Alacritty, Wezterm, Kitty, or any other terminal. - "Window of app X" (the user explicitly named the app, e.g. "screenshot Slack"). Pin the AppleScript to that app by name.
Both flavours share the rest of the pipeline (raise the window so it isn't occluded; flip y; fire the URL; poll for the file). The only difference is how APPNAME and the window-bounds query are resolved at the start.
# 1a. Resolve "this window" — the frontmost app's frontmost window. Atomic
# in one AppleScript pass so the answer can't drift between calls.
read -r APPNAME WX WY WW WH <<<"$(osascript <<'AS'
tell application "System Events"
set frontApp to first application process whose frontmost is true
-- Skip menu-bar-only apps (no windows) and walk to the next visible app.
if (count of windows of frontApp) = 0 then
repeat with proc in (every application process whose visible is true)
if (count of windows of proc) > 0 then set frontApp to proc
if (count of windows of frontApp) > 0 then exit repeat
end repeat
end if
set w to window 1 of frontApp
-- Raise it so a region-capture doesn't grab whatever is currently on top.
try
set frontmost of frontApp to true
end try
try
perform action "AXRaise" of w
end try
delay 0.2
set pos to position of w
set sz to size of w
return (name of frontApp) & " " & (item 1 of pos as text) & " " & (item 2 of pos as text) & " " & (item 1 of sz as text) & " " & (item 2 of sz as text)
end tell
AS
)"
# 1b. Alternative: pin to a specific named app (e.g. APP="Slack").
# Use this when the user explicitly named the target app.
# APP="Slack"
# read -r APPNAME WX WY WW WH <<<"$(osascript <<EOF
# tell application "System Events" to tell process "$APP"
# set w to window 1
# try
# set frontmost to true
# end try
# try
# perform action "AXRaise" of w
# end try
# delay 0.2
# set p to position of w
# set s to size of w
# return "$APP" & " " & (item 1 of p as text) & " " & (item 2 of p as text) & " " & (item 1 of s as text) & " " & (item 2 of s as text)
# end tell
# EOF
# )"
# 2. Read the *point* height of the display the window lives on. Use JXA so it
# works for any display, not just the primary one. NSScreen frames are in
# points already — do NOT divide a Retina pixel resolution from
# system_profiler by 2; that breaks on scaled modes ("More Space",
# "Larger Text") where points are decoupled from native pixels.
SH=$(osascript -l JavaScript -e '
ObjC.import("AppKit");
(function () {
var screens = $.NSScreen.screens, x = '"$WX"', y = '"$WY"';
for (var i = 0; i < screens.count; i++) {
var f = screens.objectAtIndex(i).frame;
if (x >= f.origin.x && x < f.origin.x + f.size.width
&& y >= f.origin.y && y < f.origin.y + f.size.height) {
return f.size.height; // points
}
}
return $.NSScreen.mainScreen.frame.size.height; // fallback: main display
})();
')
# 3. Flip the y origin: CleanShot measures from the bottom of the screen.
CSY=$(( SH - WY - WH ))
# 4. Drop a marker so we can find the new file later, then fire the capture.
MARK=$(mktemp -t cs.marker)
open "cleanshot://capture-area?x=${WX}&y=${CSY}&width=${WW}&height=${WH}&action=save"
# 5. Resolve CleanShot's *real* save folder. The defaults key is `exportPath`
# — NOT `CaptureFolder` (which does not exist; `defaults read` errors and
# you silently end up looking in ~/Desktop, where no file ever appears).
SAVE_DIR=$(defaults read pl.maketheweb.cleanshotx exportPath 2>/dev/null \
|| echo "$HOME/Desktop")
# 6. Poll the save folder for a brand-new file written after our marker.
for _ in 1 2 3 4 5 6 7 8 9 10; do
NEW=$(find "$SAVE_DIR" -type f -newer "$MARK" \
\( -name '*.png' -o -name '*.jpg' \) -print -quit 2>/dev/null)
[ -n "$NEW" ] && { echo "$NEW"; break; }
sleep 0.3
doneAdd &display=N (1-based) to the URL if you also want CleanShot to disambiguate; the capture-area math above already handles non-primary displays through JXA's NSScreen.screens lookup. CleanShot may still flash a save-confirmation overlay unless the user has set "After capture: Save" in their settings.
If you have a single primary display and want a one-liner instead of the JXA snippet, AppleScript's Finder also returns the main display height in points: osascript -e 'tell application "Finder" to get bounds of window of desktop' | awk -F', ' '{print $4}'. Same caveat — points, not pixels.
Caveat: multi-tab/multi-window terminals and "this window"
System Events models a macOS application process as having an ordered list of windows. It does not expose tabs, panes, or per-TTY window mappings. So when the agent runs inside one tab/pane of a multi-tab terminal (Ghostty, iTerm2, Wezterm, Kitty, Alacritty…) and the user has also opened other windows or tabs in that same terminal app, the recipe above resolves to the application's most-recently-active window — which may not be the agent's own host tab/window.
Tempting fixes that don't work reliably:
- OSC 0/2 title-marker injection (writing an
ESC ] 0 ; MARKER BELsequence to/dev/<user-tty>). The marker reaches the right pty, but Claude Code (and many shell prompts) re-set the window title on every render, so the marker is overwritten well under a second after you write it — System Events usually reads the post-restore title, not the marker. - `screencapture -l <windowID>`. It bypasses CleanShot entirely and produces a file CleanShot's pipeline doesn't know about; only fall back to it when CleanShot is genuinely unavailable.
- Ghostty's `GHOSTTY_SURFACE_ID` env var. Ghostty exposes the surface id but does not (as of 1.3.x) provide a CLI/AppleScript hook to focus a surface by id, so reading the env var doesn't get you to the right window.
What to do instead: 1. Resolve the frontmost app + its frontmost window atomically (the snippet above) and capture immediately. In the common case — single-window terminal, or the user is actively staring at the agent — this is correct. 2. If the user explicitly names a target ("screenshot Slack"), use the APP=… variant in 1b so the result doesn't depend on what happens to be frontmost. 3. If the user has multiple windows of the same app and demands the agent's host window specifically, the only fully reliable path is to ask them to bring that window to the front first, or to run the agent in a single-window terminal session for the duration of the capture.
Unattended scrolling capture of a long page (4.7+)
open "cleanshot://scrolling-capture?start=true&autoscroll=true"Without autoscroll=true, the user has to scroll manually; without start=true, they have to click Start in the overlay.
Pin an image as a floating reference
ABS_PATH=$(python3 -c 'import os,sys;print(os.path.abspath(os.path.expanduser(sys.argv[1])))' "~/Desktop/spec.png")
ENC_PATH=$(python3 -c 'import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))' "$ABS_PATH")
open "cleanshot://pin?filepath=$ENC_PATH"The image floats above all windows until the user closes the pin. The URL scheme has no documented unpin command — close the pin manually or via UI scripting.
Locate the file CleanShot just saved
The open "cleanshot://…" call returns immediately and prints nothing — there is no synchronous way to recover the saved file path. Three workable patterns:
1. Poll the configured save folder. Read the user's "Save to" path from pl.maketheweb.cleanshotx's exportPath default (do not read CaptureFolder — that key does not exist; defaults read will error out and your fallback to ~/Desktop will look in the wrong place for any user who has changed their CleanShot save folder), then pick the newest file written after a marker:
SAVE_DIR=$(defaults read pl.maketheweb.cleanshotx exportPath 2>/dev/null \
|| echo "$HOME/Desktop")
MARK=$(mktemp -t cs.marker)
open "cleanshot://capture-area?x=0&y=0&width=800&height=600&action=save"
# Wait briefly for CleanShot to write the file, then grab the newest one.
for _ in 1 2 3 4 5; do
NEW=$(find "$SAVE_DIR" -type f -newer "$MARK" \
\( -name '*.png' -o -name '*.jpg' \) -print -quit)
[ -n "$NEW" ] && { echo "$NEW"; break; }
sleep 0.5
donefind … -newer works because CleanShot writes a brand-new file per capture. (annotateLastSaveURL in the same defaults domain also tracks the most recently saved capture, but it's only updated when CleanShot's annotator wrote the file — exportPath + a fresh-file scan is more reliable.)
2. Use `action=copy` instead of `save`. The image goes on the clipboard; pull bytes with pbpaste (or the AppKit NSPasteboard) and write them yourself.
3. Use `action=upload`. CleanShot copies the upload URL (not the image) to the clipboard — pbpaste returns it, e.g. https://cln.sh/abcd1234.
Do not assume open prints the file path: it never does, regardless of action=.
Detect installed version before using 4.7-only parameters
VERSION=$(defaults read "/Applications/CleanShot X.app/Contents/Info" CFBundleShortVersionString 2>/dev/null || echo "0")
# Compare with sort -V; bail out cleanly if too old.
if [ "$(printf '%s\n4.7\n' "$VERSION" | sort -V | head -n1)" != "4.7" ]; then
echo "CleanShot $VERSION is too old for action= / spatial parameters" >&2
exit 1
fiURL-encode a path safely (helper)
CleanShot accepts only percent-encoded URLs. The most reliable encoder for an arbitrary path:
encode_path() {
python3 -c 'import sys,urllib.parse,os;print(urllib.parse.quote(os.path.abspath(os.path.expanduser(sys.argv[1])),safe="/"))' "$1"
}
open "cleanshot://open-annotate?filepath=$(encode_path "~/Pictures/My Shot.png")"Bash-only fallback (no Python): printf '%s' "$path" | jq -sRr @uri if jq is available.
Verifying CleanShot is present and runnable
Before firing any URL, agents should confirm:
# 1. App installed? (covers /Applications and Setapp)
if [ ! -d "/Applications/CleanShot X.app" ] && [ ! -d "$HOME/Applications/Setapp/CleanShot X.app" ]; then
# Fallback: query LaunchServices by bundle ID (also handles non-standard paths)
if [ -z "$(mdfind "kMDItemCFBundleIdentifier == 'pl.maketheweb.cleanshotx'")" ]; then
echo "CleanShot X not installed" >&2; exit 1
fi
fi
# 2. URL scheme registered? (LaunchServices)
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -dump 2>/dev/null \
| grep -A1 "scheme:" | grep -q "cleanshot" \
&& echo "URL scheme registered"
# 3. Logged-in graphical session? (must be Aqua)
launchctl managername | grep -qi Aqua || echo "Warning: not an Aqua session — URL scheme may not fire"When the URL scheme isn't enough
Things the URL scheme cannot do — escalate or document the limitation rather than inventing a command:
- Programmatically stop a recording (no
stop-recordingURL). - Compose multiple post-capture actions in one call (
action=copy,upload). - Read the resulting file path or upload URL from the command — must read the clipboard or scan the configured save folder.
- Drive Quick Access overlay placement, size, or z-order beyond "added".
- Change settings programmatically (only open the settings tab).
- Capture without a user-visible UI (every command surfaces some on-screen affordance).
- Unpin a pinned image.
For workflows that need richer integration than the URL scheme exposes, fall back to macOS Shortcuts.app (CleanShot ships several Shortcut actions that wrap these URLs). Drop down to OS-level alternatives (screencapture, xcrun simctl io … screenshot, native AVFoundation recorders) only when CleanShot is genuinely unavailable. In particular, do not reach for screencapture -l <windowID> to dodge capture-window's click — cleanshot://capture-area with explicit x/y/w/h (see Capture a specific named window unattended) covers that case headlessly.
Where to look next
- references/url-scheme.md — every command, every parameter, version requirements, examples.
- Vendor docs: <https://cleanshot.com/docs-api> (authoritative; check for new commands when this skill seems incomplete).
- App version:
defaults read "/Applications/CleanShot X.app/Contents/Info" CFBundleShortVersionString. - App support directory (per-user CleanShot state):
~/Library/Application Support/pl.maketheweb.cleanshotx/. - Default save folder for captured files: shown in CleanShot ▸ Settings ▸ Screenshots ▸ "Save to".
CleanShot X cleanshot:// URL scheme — full command reference
Every public command exposed by CleanShot X, with parameters, version requirements, and a worked example. Source: <https://cleanshot.com/docs-api>. Verify against that page if a command appears to behave differently — Magic Lasso adds new parameters between minor versions.
Contents
1. `capture-area` — area-selection screenshot 2. `capture-previous-area` — repeat the last area capture 3. `capture-fullscreen` — full screen, no UI 4. `capture-window` — pick a window 5. `self-timer` — area capture with a countdown 6. `scrolling-capture` — long-page / scrollable capture 7. `pin` — pin an image as a floating window 8. `record-screen` — start a screen recording 9. `capture-text` — OCR an image or screen region 10. `open-annotate` — open an image in the annotator 11. `open-from-clipboard` — annotate the clipboard image 12. `all-in-one` — unified capture/recording overlay 13. `toggle-desktop-icons` 14. `hide-desktop-icons` 15. `show-desktop-icons` 16. `add-quick-access-overlay` — add a file to the Quick Access overlay 17. `open-history` 18. `restore-recently-closed` 19. `open-settings` — open a specific settings tab
Plus: Quick parameter index and `action=` value behavior at the end.
Conventions
- All commands use the form
cleanshot://<command>?param1=value1¶m2=value2. - Fire with
open "cleanshot://…"from a logged-in macOS Aqua session. - All parameter values must be URL-encoded (spaces →
%20,&→%26, etc.). - Values shown as
true | falseaccept the literal lowercase strings. display=is a 1-based integer index (1, 2, …) of the displays as CleanShot sees them. If omitted, CleanShot defaults to the display under the cursor.- Coordinate system: origin
(0,0)is the lower-left corner of the screen, withyincreasing upward (per the CleanShot docs). Spatial parameters (x,y,width,height) are integers in points, not Retina pixels. - Version cells refer to the CleanShot X version the command (or that specific parameter) first appeared in. macOS minimums are called out where they apply.
- The
action=parameter, when present, accepts exactly one of:copy,save,annotate,upload,pin. It overrides the user's "After capture" default for that one invocation.
---
1. capture-area
Open the standard area-selection capture overlay.
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
x | integer | no | 4.7+ | x of the pre-selected region (points; lower-left origin). |
y | integer | no | 4.7+ | y of the pre-selected region (points; measured from the bottom of the screen). |
width | integer | no | 4.7+ | Width of pre-selected region. |
height | integer | no | 4.7+ | Height of pre-selected region. |
display | integer | no | 4.7+ | 1-based display index. |
action | enum | no | 4.7+ | `copy \ |
Min CleanShot version: 3.5.1+.
Examples:
cleanshot://capture-area
cleanshot://capture-area?action=annotate
cleanshot://capture-area?x=100&y=200&width=640&height=480&display=1&action=uploadIf all four spatial parameters are supplied, CleanShot still shows the selection rectangle pre-positioned but allows the user to adjust before confirming — there is no documented "fire immediately" mode for a non-fullscreen area.
---
2. capture-previous-area
Repeat the most recent area capture using the previous coordinates.
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
action | enum | no | 4.7+ | `copy \ |
Min CleanShot version: 3.5.1+.
Example:
cleanshot://capture-previous-area?action=copyIf there is no "previous area" yet (first run after launch), CleanShot falls back to a normal area capture.
---
3. capture-fullscreen
Capture the entire screen immediately — no UI, no selection.
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
action | enum | no | 4.7+ | `copy \ |
Min CleanShot version: 3.5.1+.
Example:
cleanshot://capture-fullscreen?action=saveThere is no per-display restriction — fullscreen captures every connected display unless the user has disabled "Capture all displays" in settings.
---
4. capture-window
Enter window-selection capture mode (hover and click a window to capture it).
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
action | enum | no | 4.7+ | `copy \ |
Min CleanShot version: 3.5.1+.
Example:
cleanshot://capture-window?action=annotateRequires Screen Recording permission for CleanShot to read window contents on macOS 10.15+.
---
5. self-timer
Open the area capture overlay with the self-timer enabled. The user picks the area; CleanShot counts down before snapping.
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
action | enum | no | 4.7+ | `copy \ |
Min CleanShot version: 3.5.1+.
Example:
cleanshot://self-timer?action=uploadThe countdown duration is whatever the user has configured in CleanShot settings; the URL scheme cannot override it.
---
6. scrolling-capture
Open the scrolling-capture overlay for capturing long pages, scrollable lists, etc.
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
x | integer | no | 4.7+ | x of the pre-selected region (lower-left origin). |
y | integer | no | 4.7+ | y of the pre-selected region (from screen bottom). |
width | integer | no | 4.7+ | Region width. |
height | integer | no | 4.7+ | Region height. |
display | integer | no | 4.7+ | 1-based display index. |
start | bool | no | 4.7+ | true to begin capturing immediately without the user clicking Start. |
autoscroll | bool | no | 4.7+ | true to make CleanShot drive the scroll itself instead of the user. |
Min CleanShot version: 3.5.1+. Spatial / start / autoscroll parameters require 4.7+.
Examples:
cleanshot://scrolling-capture
cleanshot://scrolling-capture?start=true
cleanshot://scrolling-capture?start=true&autoscroll=true
cleanshot://scrolling-capture?x=0&y=0&width=1280&height=800&display=1&start=true&autoscroll=trueautoscroll=true only works for windows whose scroll area CleanShot can drive — most native macOS apps and Chromium/WebKit browsers. Some Electron apps and custom views require manual scroll.
---
7. pin
Pin an image as a floating window above all other windows.
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
filepath | absolute path | no | 3.5.1+ | PNG or JPEG. If omitted, CleanShot prompts the user to pick a file (per the docs). |
Min CleanShot version: 3.5.1+.
Examples:
cleanshot://pin
cleanshot://pin?filepath=/Users/john/Desktop/my%20screenshot.pngThere is no URL to programmatically unpin; the user must close the pin window manually.
---
8. record-screen
Start a screen recording. Whether the recording begins immediately or shows a region overlay depends on the user's CleanShot settings.
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
x | integer | no | 4.7+ | x of the recording region (lower-left origin). |
y | integer | no | 4.7+ | y of the recording region (from screen bottom). |
width | integer | no | 4.7+ | Region width. |
height | integer | no | 4.7+ | Region height. |
display | integer | no | 4.7+ | 1-based display index. Capture entire display when no x/y/width/height. |
Min CleanShot version: 3.5.1+. Spatial parameters require 4.7+.
Examples:
cleanshot://record-screen
cleanshot://record-screen?display=1
cleanshot://record-screen?x=0&y=0&width=1920&height=1080&display=1There is no stop-recording URL. Stop via the menu-bar item, the floating recording control, or the user's configured shortcut. Audio recording (microphone or system audio) follows the user's settings — the URL cannot override them.
---
9. capture-text
Run OCR on either an existing image or a region of the screen. CleanShot's standard OCR flow places the recognized text on the clipboard.
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
filepath | absolute path | no | 3.8.1+ | PNG or JPEG. If omitted, CleanShot opens an interactive selection (area overlay) for OCR — the docs do not enumerate the exact UI but the spatial parameters below imply a region selection. |
x | integer | no | 4.7+ | x of the region to OCR (only when filepath omitted; lower-left origin). |
y | integer | no | 4.7+ | y of the region to OCR (from screen bottom). |
width | integer | no | 4.7+ | Region width. |
height | integer | no | 4.7+ | Region height. |
display | integer | no | 4.7+ | 1-based display index. |
linebreaks | bool | no | 3.8.1+ | true keeps line breaks in the recognized text; false flattens to a single paragraph. |
Min CleanShot version: 3.8.1+. macOS minimum: 10.15+ (uses Apple's Vision framework).
Examples:
cleanshot://capture-text
cleanshot://capture-text?linebreaks=true
cleanshot://capture-text?filepath=/Users/john/Desktop/screenshot.png&linebreaks=falseIn CleanShot's standard OCR flow the recognized text lands on the clipboard; there is no parameter to write it to a file. Pipe pbpaste from the calling shell after the URL fires.
---
10. open-annotate
Open an image in CleanShot's annotator.
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
filepath | absolute path | no | 3.8.1+ | PNG or JPEG. If omitted, CleanShot prompts the user to pick a file (per the docs). |
Min CleanShot version: 3.8.1+.
Example:
cleanshot://open-annotate?filepath=/Users/john/Desktop/image.png---
11. open-from-clipboard
Open whatever image is on the clipboard in the annotator.
No parameters. Min CleanShot version: 3.5.1+.
Example:
cleanshot://open-from-clipboardIf the clipboard does not contain an image, CleanShot shows a "no image on clipboard" banner and exits.
---
12. all-in-one
Open the All-In-One mode (a unified capture/recording overlay added in 4.x).
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
x | integer | no | 4.7+ | x of the pre-selected region (lower-left origin). |
y | integer | no | 4.7+ | y of the pre-selected region (from screen bottom). |
width | integer | no | 4.7+ | Region width. |
height | integer | no | 4.7+ | Region height. |
display | integer | no | 4.7+ | 1-based display index. |
Min CleanShot version: 4.2+. Spatial parameters require 4.7+.
Examples:
cleanshot://all-in-one
cleanshot://all-in-one?x=100&y=120
cleanshot://all-in-one?x=0&y=0&width=1280&height=800&display=1---
13. toggle-desktop-icons
Toggle the visibility of macOS desktop icons.
No parameters. Min CleanShot version: 3.5.1+.
Example:
cleanshot://toggle-desktop-icons---
14. hide-desktop-icons
Hide macOS desktop icons (idempotent — safe to call when already hidden).
No parameters. Min CleanShot version: 3.8.1+.
Example:
cleanshot://hide-desktop-icons---
15. show-desktop-icons
Show macOS desktop icons (idempotent).
No parameters. Min CleanShot version: 3.8.1+.
Example:
cleanshot://show-desktop-icons---
16. add-quick-access-overlay
Add a file to the Quick Access Overlay (a per-screen palette of recent media that CleanShot can keep visible).
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
filepath | absolute path | yes | 3.8.1+ | PNG, JPEG, or MP4. |
Min CleanShot version: 3.8.1+.
Example:
cleanshot://add-quick-access-overlay?filepath=/Users/john/Desktop/screenshot.pngWithout filepath, the URL is a no-op.
---
17. open-history
Open CleanShot's capture history window.
No parameters. Min CleanShot version: 4.4+.
Example:
cleanshot://open-history---
18. restore-recently-closed
Re-open the most recently closed CleanShot capture or pin (the docs do not enumerate the full set of items this command tracks).
No parameters. Min CleanShot version: 3.5.1+.
Example:
cleanshot://restore-recently-closed---
19. open-settings
Open the CleanShot Settings window, optionally focused on a specific tab.
| Parameter | Type | Required | Min version | Notes |
|---|---|---|---|---|
tab | enum | no | 4.7+ | One of: general, wallpaper, shortcuts, quickaccess, recording, screenshots, annotate, cloud, advanced, about. |
Min CleanShot version: 4.7+.
Examples:
cleanshot://open-settings
cleanshot://open-settings?tab=recording
cleanshot://open-settings?tab=cloudUnknown tab values fall back to the General tab on most builds.
---
Quick parameter index
| Parameter | Used by |
|---|---|
action | capture-area, capture-previous-area, capture-fullscreen, capture-window, self-timer |
x, y, width, height, display | capture-area, scrolling-capture, record-screen, capture-text, all-in-one |
start, autoscroll | scrolling-capture |
linebreaks | capture-text |
filepath | pin, capture-text, open-annotate, add-quick-access-overlay |
tab | open-settings |
Behavior of action= values
| Value | What CleanShot does after the capture |
|---|---|
copy | Copies the image to the clipboard. No save dialog. |
save | Writes the image to the configured save folder using the user's filename template. |
annotate | Opens the result in the CleanShot annotator. |
upload | Uploads to the configured destination (CleanShot Cloud / S3 / Dropbox / etc.) and copies the resulting URL to the clipboard. |
pin | Pins the image as a floating window. |
action= is single-valued. To compose actions, drive a follow-up URL after the first one resolves (e.g. capture with action=save, then cleanshot://open-annotate?filepath=… against the saved file).