Tell Claude "look at the latest screenshot" and it just works — no pasting images, no copying file paths. It finds the most recent screenshot, reads it (Claude is multimodal), and can copy it into your project. Use cases: OCR, UI review, saving images into slides, checking designs, reading error messages.
Three things need to be configured to make this seamless. Each solves a different problem.
| Problem | Cause | Solution |
|---|---|---|
| Claude doesn't know where screenshots are | No default behavior | CLAUDE.md instructions |
| Permission prompts on Read/Glob | No allow rules | settings.json rules |
Permission prompts on cp |
Bash(cp *) patterns break with paths containing spaces |
PreToolUse hook |
cp fails with "No such file" |
macOS uses invisible Unicode U+202F before AM/PM in filenames | Glob patterns in cp command (CLAUDE.md instructions) |
Add this to your CLAUDE.md (global ~/.claude/CLAUDE.md or per-project). Replace the screenshots path with yours.
### Screenshots
**Folder:** `/Users/YOURNAME/Documents/screenshots/`
**When I say "recent screenshot", "latest screenshot", "look at the screenshot", or similar:**
1. **Glob** with pattern `*` and path `/Users/YOURNAME/Documents/screenshots/` to find the most recent file (sorted by modification time, most recent first)
2. **Read** that file to view it
**When copying a screenshot to another location:**
1. **Glob** to find the filename (never guess the exact timestamp)
2. **Bash cp** using glob patterns to match the file — do NOT use the full quoted filename
# Correct: glob pattern avoids Unicode issue
cp /Users/YOURNAME/Documents/screenshots/Screenshot*10.16*AM.png dest.png
# Wrong: quoted exact path fails because macOS uses U+202F (narrow no-break space)
# between time and AM/PM — Claude writes a regular space, so cp can't find the file
cp "/Users/YOURNAME/Documents/screenshots/Screenshot 2026-02-09 at 10.16.30 AM.png" dest.png
**Why globs are mandatory:** macOS screenshot filenames contain a Unicode narrow no-break space (U+202F) before AM/PM. The Glob tool resolves this correctly, but when the path is passed as a quoted string to Bash cp, the Unicode character is replaced with a regular space, causing "No such file or directory."What this does: Tells Claude where your screenshots live and how to find/copy them. Without this, Claude has no idea where to look.
macOS tip: You can change where screenshots are saved with defaults write com.apple.screencapture location ~/Documents/screenshots && killall SystemUIServer. This keeps them out of your Desktop clutter.
Add these to ~/.claude/settings.json under permissions.allow:
{
"permissions": {
"allow": [
"Glob(*)",
"Read(~/Documents/screenshots/**)"
]
}
}What this does: Lets Claude find and read screenshots without prompting. Glob(*) allows file discovery anywhere (it's read-only and safe). Read(~/Documents/screenshots/**) allows viewing screenshot images.
Note: Use the tilde ~ form for Read rules, not the full /Users/YOURNAME/... path. Claude Code matches Read permissions against tilde paths.
This is the piece that took the most debugging. Claude Code's Bash(cp *) permission pattern in settings.json does not work for commands with long quoted paths containing spaces. No pattern variation fixes this — it's a fundamental limitation of the pattern matcher.
The solution: a PreToolUse hook that inspects the command and auto-approves safe operations.
Save allow-screenshot-cp.sh (included in this gist) to ~/.claude/scripts/ and make it executable:
mkdir -p ~/.claude/scripts
# Save the script (see allow-screenshot-cp.sh in this gist)
chmod +x ~/.claude/scripts/allow-screenshot-cp.shAdd this under hooks in ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/Users/YOURNAME/.claude/scripts/allow-screenshot-cp.sh",
"timeout": 5000
}
]
}
]
}
}- Reads the Bash command from stdin (JSON with
tool_input.command) - Auto-approves all
lscommands (read-only, always safe) - Auto-approves
cpcommands where the source is in/Documents/screenshots/ - Handles chained commands like
cd /screenshots && cp ...by stripping thecdprefix first - Everything else falls through to normal permission checks
The first version used \bcp\b (match cp anywhere in the command) instead of ^cp\b (must start with cp). That's dangerous — a command like rm -rf /important && cp /Documents/screenshots/foo bar would match both checks and auto-approve the rm. The fix: strip only a leading cd ... && prefix, then require the remainder to start with cp. This means cd /path && cp ... works, but rm ... && cp ... doesn't.
# Should output approval JSON:
echo '{"tool_name":"Bash","tool_input":{"command":"cp /Users/me/Documents/screenshots/Screenshot*10.16*AM.png dest.png"}}' | ~/.claude/scripts/allow-screenshot-cp.sh
# Should also approve (cd + cp pattern):
echo '{"tool_name":"Bash","tool_input":{"command":"cd /Users/me/Documents/screenshots && cp Screenshot*10.16*AM.png dest.png"}}' | ~/.claude/scripts/allow-screenshot-cp.sh
# Should output nothing (falls through — rm is not allowed):
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /important"}}' | ~/.claude/scripts/allow-screenshot-cp.sh
# Should also fall through (rm chained with cp — not safe):
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /important && cp /Documents/screenshots/foo bar"}}' | ~/.claude/scripts/allow-screenshot-cp.shWhen you say "look at the latest screenshot":
- Claude reads CLAUDE.md, knows to check the screenshots folder
Glob(*, path=screenshots/)finds the most recent file — auto-approved byGlob(*)Read(screenshot.png)displays the image — auto-approved byRead(~/Documents/screenshots/**)
When you say "copy that screenshot into my slides folder":
Globresolves the filename and timestampls destination/checks the target exists — auto-approved by PreToolUse hookcp /path/Screenshot*10.16*AM.png dest.pngcopies the file — auto-approved by PreToolUse hook (matches screenshots folder)
Zero permission prompts. Zero "file not found" errors.
The settings.json permission pattern Bash(cp *) is supposed to match any cp command. It works for simple cases like cp file1 file2. But it silently fails for:
cp "/Users/me/Documents/screenshots/Screenshot 2026-02-09 at 10.16.30 AM.png" "/Users/me/project/dest.png"We tested every variation:
| Pattern | Result |
|---|---|
Bash(cp *) |
Still prompted |
Bash(cp) |
Still prompted |
Bash(cp **) |
Still prompted |
The pattern matcher can't handle quoted paths with spaces. PreToolUse hooks bypass this entirely because they parse the actual command string with real tools (jq + grep) instead of relying on glob matching.
- macOS (the Unicode issue is macOS-specific)
jqinstalled (brew install jqor it may already be at/usr/bin/jq)- Claude Code CLI