I Got Tired of Hunting Screenshot Paths in Terminals. So I Fixed Ctrl+V.

Published: (April 6, 2026 at 06:10 PM EDT)
4 min read
Source: Dev.to

Source: Dev.to

The Idea

The fix seemed obvious: Ctrl + V should be context‑aware.

  • In a terminal, if an image is on the clipboard, paste the file path instead of the raw image data.
  • In a text editor or browser, paste normally.

The behavior should be invisible—no new command to memorize. Pressing Ctrl + V just does the right thing depending on where you are.

How It Works

The keyboard layer

An AutoHotkey v2 script runs in the background as a tray process. It intercepts Ctrl + V at the OS level, checks which window is focused, and:

  • If the focused window is a terminal → hands off to the Python core.
  • Otherwise → does nothing, letting the normal paste go through.

The Python core

The core implements the logic:

  1. Inspect the clipboard – is there image data?
  2. If yes:
    • Look in the OS screenshot folder for a file that matches, using a recency window (default = 5 seconds).
    • If a recent screenshot exists → type its full file path into the terminal.
    • If no match → save the clipboard image to disk, then type the new path.
  3. If no image: fall back to normal paste behavior.

Alt + V is the override: it force‑pastes the image path regardless of the focused window, useful for GUI apps that need a path.

Zero Config by Design

TCP works immediately after installation—no setup required.

  • Screenshot folder detection is automatic on every platform (Windows registry keys, macOS defaults, XDG paths on Linux).
  • Terminal detection uses a built‑in list of process names:
WindowsTerminal.exe, powershell.exe, pwsh.exe, cmd.exe,
Code.exe, warp.exe, alacritty.exe, mintty.exe

You can add more in %APPDATA%\tcp\config.toml if needed.

Optional configuration (TOML)

save_dir = ""                          # Auto‑detected from OS settings
filename_pattern = "tcp_%Y%m%d_%H%M%S.png"
recency_window = 5                    # Seconds
format = "png"
path_style = "native"                 # native, forward, or backslash
extra_terminals = ["hyper.exe"]

Why AutoHotkey

On Windows, intercepting keyboard input at the OS level can be done with raw Win32 hooks, PowerShell + P/Invoke, or AutoHotkey. AHK was chosen because:

  • It’s mature and widely used in the Windows power‑user community.
  • The v2 API is clean and concise.
  • The shim is only ~50 lines, handling hotkey interception and delegating to Python.

The Python core is cross‑platform, so the same logic works on macOS and Linux. The missing pieces for those platforms are hotkey‑interception layers (Swift/Hammerspoon for macOS, xdotool for Linux), slated for future development.

What I Learned

  • The hardest part wasn’t the clipboard logic but getting AHK keystroke injection right.

    • Early versions leaked modifier keys (Ctrl, Shift) from the intercepted hotkey into the sent keystrokes, garbling the output.
    • The fix was using {Raw} and {Blind} modes in AHK to ensure clean sending.
  • Implementing the clipboard‑swap approach for normal Ctrl + V passthrough was also tricky.

    • TCP must let the keypress go through unchanged when a normal text paste is required, without generating synthetic keystrokes or double‑fires.

What’s Next

  • macOS support (Swift hotkey shim)
  • Linux support (xdotool‑based shim)
  • Optional path quoting for paths containing spaces
  • “Watcher” mode – detect new screenshots in real time and pre‑cache the path so the first Ctrl + V is instant even if the file write is slow

Try It

TCP is free software (BSL 1.1) – free for all use.

One‑click installer: TCPSetup.exe

PowerShell one‑liner:

irm https://raw.githubusercontent.com/CodeWarrior4Life/TerminalCopyPaste/main/install.ps1 | iex

Repository:

If you use Claude Code, Codex CLI, Aider, or any terminal‑heavy workflow, give it a try.

If you found this useful, consider buying me a coffee to keep the ideas flowing. ☕
The goal is for the tool to become invisible after a day – exactly what I was aiming for.

0 views
Back to Blog

Related posts

Read more »