<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Alfred on Matt Goodrich</title><link>https://mattgoodrich.com/tags/alfred/</link><description>Recent content in Alfred on Matt Goodrich</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Tue, 14 Jul 2026 00:01:00 -0700</lastBuildDate><atom:link href="https://mattgoodrich.com/tags/alfred/index.xml" rel="self" type="application/rss+xml"/><item><title>Pasting Screenshots Into a Remote Claude Session</title><link>https://mattgoodrich.com/posts/pasting-screenshots-into-a-remote-claude-session/</link><pubDate>Tue, 14 Jul 2026 00:01:00 -0700</pubDate><guid>https://mattgoodrich.com/posts/pasting-screenshots-into-a-remote-claude-session/</guid><description>&lt;img src="https://mattgoodrich.com/posts/pasting-screenshots-into-a-remote-claude-session/header.png" alt="Featured image of post Pasting Screenshots Into a Remote Claude Session" />&lt;p>In &lt;a class="link" href="https://mattgoodrich.com/posts/my-ai-workspace-tmux-cloudflared/" >Agents Don&amp;rsquo;t Travel Well&lt;/a> I called pasting screenshots into a remote Claude Code session my biggest day-to-day gripe with the whole setup. The clipboard lives on the laptop in front of me. The session lives on the Mac Studio at home. Copy an image, switch to the tmux pane, hit paste, and nothing lands. I closed that section with &amp;ldquo;if you&amp;rsquo;ve solved this, please find me.&amp;rdquo; I solved it myself a while ago and never wrote it up. The fix is one Alfred hotkey and about thirty lines of shell, and it has been smooth enough since that I stopped thinking about it.&lt;/p>
&lt;h2 id="the-clipboard-was-never-going-to-cross">The Clipboard Was Never Going to Cross
&lt;/h2>&lt;p>The workaround I described back then was dropping the screenshot into a synced folder and pasting the path, which is fine for one image and miserable by the tenth. What made it painful was never the syncing. It was the manual steps in between: take the capture, find the file, wait for the sync, then work out what that file&amp;rsquo;s path looks like on the other machine. Four small frictions per image, multiplied by every image.&lt;/p>
&lt;p>The fix came from restating what the session needs. Claude Code can &lt;code>Read&lt;/code> any file on the machine it runs on, images included, and an image file read from disk lands in the conversation the same as a pasted one. So the session needs two things: the file on its own disk, and the path in the prompt. The path is text, and text pastes across SSH just fine.&lt;/p>
&lt;p>The automation moves the file to where the session lives, then hands me the remote path. Ship the file, paste the path.&lt;/p>
&lt;h2 id="one-hotkey-two-things-cross">One Hotkey, Two Things Cross
&lt;/h2>&lt;p>⌘⇧0 fires an Alfred workflow whose only job is to run a script. The screenshot ships to the Studio over the tailnet, the path to it crosses back as text on the clipboard, and the two meet at the session.&lt;/p>
&lt;p>&lt;img src="https://mattgoodrich.com/posts/pasting-screenshots-into-a-remote-claude-session/diagram-ship-file-paste-path.png"
width="2314"
height="804"
srcset="https://mattgoodrich.com/posts/pasting-screenshots-into-a-remote-claude-session/diagram-ship-file-paste-path_hu6280149262169079855.png 480w, https://mattgoodrich.com/posts/pasting-screenshots-into-a-remote-claude-session/diagram-ship-file-paste-path_hu4445526190751145523.png 1024w"
loading="lazy"
alt="Ship the File, Paste the Path: on the Laptop a Region Capture From screencapture Ships the File to the Mac Studio Over the Tailnet via scp, Where It Lands on Disk in ~/.cc-shots, While the Remote Path to It Goes Onto the Clipboard as Text; Pasting That Path Into the Claude Code Session on the Studio Points It at the File, Which Claude Reads Off Local Disk"
class="gallery-image"
data-flex-grow="287"
data-flex-basis="690px"
>&lt;/p>
&lt;p>From my side it feels like a native screenshot. Hit the hotkey, drag a rectangle, and by the time I&amp;rsquo;ve switched to the tmux pane the path is on the clipboard. Paste it into the conversation, Claude reads the image off its own disk, done. Ten screenshots is ten hotkeys at a few seconds each, which in practice is the difference between describing an error dialog in words and just showing it.&lt;/p>
&lt;p>Here is the script:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/bin/zsh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -euo pipefail
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># The Studio answers to one MagicDNS name from anywhere on the tailnet.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">HOST&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;mac-studio&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">REMOTE_DIR&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;.cc-shots&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">ts&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>date +%Y%m%d-%H%M%S&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># mktemp creates an empty stub; screencapture writes the .png alongside it.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Trap cleans both even on ESC / empty / unreachable-Studio exits.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">tmp_base&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>mktemp -t ccshot&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">tmp&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">tmp_base&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.png&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">trap&lt;/span> &lt;span class="s1">&amp;#39;rm -f &amp;#34;$tmp_base&amp;#34; &amp;#34;$tmp&amp;#34;&amp;#39;&lt;/span> EXIT
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ESC during region select returns success with an empty file.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">screencapture -i &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$tmp&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="nb">exit&lt;/span> &lt;span class="m">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span> -s &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$tmp&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="nb">exit&lt;/span> &lt;span class="m">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># The mkdir doubles as the reachability check: if the Studio isn&amp;#39;t on the&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># tailnet, this fails and we bail before touching the clipboard.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! ssh -o &lt;span class="nv">ConnectTimeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">5&lt;/span> -o &lt;span class="nv">BatchMode&lt;/span>&lt;span class="o">=&lt;/span>yes &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$HOST&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;mkdir -p &lt;/span>&lt;span class="nv">$REMOTE_DIR&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> osascript -e &lt;span class="s1">&amp;#39;display notification &amp;#34;Mac Studio unreachable over the tailnet&amp;#34; with title &amp;#34;CC screenshot&amp;#34; sound name &amp;#34;Basso&amp;#34;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">scp -q &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$tmp&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$HOST&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="nv">$REMOTE_DIR&lt;/span>&lt;span class="s2">/&lt;/span>&lt;span class="nv">$ts&lt;/span>&lt;span class="s2">.png&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;~/%s/%s.png&amp;#39;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$REMOTE_DIR&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$ts&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> pbcopy
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">osascript -e &lt;span class="s1">&amp;#39;display notification &amp;#34;Path copied — paste into Claude Code&amp;#34; with title &amp;#34;CC screenshot&amp;#34;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The Alfred side is two nodes, a hotkey trigger wired to a script action, exported to a &lt;code>.alfredworkflow&lt;/code> file so it survives a laptop rebuild. The only prerequisites are a Studio reachable at its MagicDNS name and the Screen Recording permission &lt;code>screencapture&lt;/code> needs.&lt;/p>
&lt;h2 id="the-details-that-matter">The Details That Matter
&lt;/h2>&lt;p>The path lands on the clipboard as &lt;code>~/.cc-shots/&amp;lt;timestamp&amp;gt;.png&lt;/code> with a literal tilde, and that is deliberate. The tilde belongs to the Studio&amp;rsquo;s shell, where Claude Code will expand it, and to nothing on the laptop. Expanding it laptop-side would produce a path into the wrong home directory on the wrong machine.&lt;/p>
&lt;p>Every SSH call runs with &lt;code>BatchMode=yes&lt;/code>, so there is no password fallback anywhere. If auth breaks or the Studio is off the tailnet, the SSH call fails and the script tells me the Studio is unreachable instead of hanging on a prompt no one will ever see inside an Alfred action.&lt;/p>
&lt;p>ESC during region-select exits silently: success code, empty clipboard, no notification. So does a zero-byte capture. Both are deliberate, because the alternative is a stale path on the clipboard pointing at a screenshot that does not exist, which is a worse bug than a hotkey that sometimes appears to do nothing. It reads as broken the first time. It is the correct behavior every time after.&lt;/p>
&lt;p>One Alfred quirk worth knowing: the hotkey binding does not travel with the exported workflow file. Alfred zeroes it on export, so after a fresh import the workflow exists but fires nothing until the key is rebound by hand.&lt;/p>
&lt;h2 id="what-it-doesnt-fix">What It Doesn&amp;rsquo;t Fix
&lt;/h2>&lt;p>This is a fix for exactly one topology: macOS laptop in front of me, macOS server running the session, Alfred with a Powerpack license in between. &lt;code>screencapture&lt;/code>, &lt;code>pbcopy&lt;/code>, and &lt;code>osascript&lt;/code> are all Mac-isms. The pattern ports anywhere, any launcher or keybinding daemon can run a script that captures, ships, and puts a path on a clipboard, but the script itself does not.&lt;/p>
&lt;p>It is also still one screenshot per hotkey. Ten images into one conversation is ten capture-paste cycles, quick ones, but a &amp;ldquo;share this whole folder&amp;rdquo; flow does not exist yet, and a genuinely bidirectional clipboard does not either. Files the session produces still come back to me over the sync-folder route from the original post.&lt;/p>
&lt;p>And it is one more piece of personal infrastructure. The note documenting it in my vault carries a new-laptop checklist for a reason: an unbound hotkey, a missing script, or an expired SSH key each silently turn the automation into nothing. Small tools like this are cheap to build and easy to forget you depend on.&lt;/p>
&lt;h2 id="one-name-from-anywhere">One Name, From Anywhere
&lt;/h2>&lt;p>The script reaches the Studio at a single hostname, &lt;code>mac-studio&lt;/code>, and that one name works whether I&amp;rsquo;m home or on hotel wifi because it&amp;rsquo;s a MagicDNS name on the &lt;a class="link" href="https://mattgoodrich.com/posts/collapsing-a-pile-of-tunnels-onto-tailscale/" >Tailscale overlay I moved the house onto&lt;/a>. It was not always one name. An earlier version of this script probed a LAN hostname first, on a three-second timeout, then fell back to a Cloudflare tunnel hostname when I was away from home, a small two-host dance every capture had to run. Consolidating onto the overlay deleted the dance: one name that resolves from anywhere, no LAN probe, no fallback branch. The automation got shorter because the layer underneath it got simpler. That is what a good consolidation does, and this hotkey is the smallest, most concrete example of it I have. Ship the file, paste the path, over one overlay that does not care where the laptop is.&lt;/p></description></item></channel></rss>