Screenshot your iPhone, straight from the Mac menu bar.
USB or Wi-Fi · pixel-perfect captures · saved to a folder you choose · copied to your clipboard.
Website · npm · Install · Docs · Support
npm install -g tethershot
Status — shipping. USB + Wi-Fi capture, clipboard, global hotkey, per-device folders, npm install, and in-app self-update are all working. Built and tested on macOS 26 (Tahoe) with iOS 26.
macOS already lets QuickTime/OBS mirror a tethered iPhone's screen (it appears as an AVCaptureDevice of media type .muxed). TetherShot wraps that into a one-click menu-bar capture that writes straight to disk and your clipboard — and adds cable-free Wi-Fi capture through Apple's developer-services tunnel. It's the iPhone screenshot tool Apple never shipped.
- 🔌 USB capture — a trusted, cabled iPhone is grabbed at full resolution via native AVFoundation. Instant, zero setup.
- 📶 Wi-Fi capture — cable-free over your local network via a RemoteXPC tunnel (
pymobiledevice3). Pixel-perfect, even when the phone is locked. - 📋 Clipboard — every capture is copied, ready to paste (toggle on by default).
- ⌨️ Global hotkey — press ⌘⇧7 anywhere to capture every connected device.
- 🗂️ Your folder, your rules — any destination, timestamped filenames, optional per-device subfolders.
- ⬆️ Self-updating — in-app Check for Updates pulls the latest from npm, rebuilds, and relaunches.
- 🚀 Launch at login, runs as a background menu-bar agent (no Dock icon).
- 🔒 Local-first — no account, no analytics, no servers. Screenshots never leave your Mac.
- macOS 14 (Sonoma)+ — developed/tested on macOS 26 (Tahoe)
- Xcode Command Line Tools —
xcode-select --install(needed to build from source) - Node.js 18+ — to install via npm
- An iPhone you can set to Trust This Computer
- For Wi-Fi: iPhone + Mac on the same network, plus
pymobiledevice3
npm install -g tethershot # installs the CLI (and builds the app)
tethershot install # ensure the app is built into ~/Applications
tethershot # launch itIt builds from source on your machine, so the app gets no Gatekeeper quarantine — it just runs, no "unidentified developer" wall, no notarization. It lands in ~/Applications (no sudo).
npm 11+ blocks
postinstallscripts by default, so if the app isn't built afternpm install, the explicittethershot installstep always does it.
git clone https://github.com/apoorvdarshan/TetherShot.git
cd TetherShot
./build.sh # compiles + packages TetherShot.app
open TetherShot.app # launches the menu-bar agentOn first USB capture, macOS asks for Camera permission — expected: the iPhone screen is delivered through the AVFoundation (camera) privacy bucket. TetherShot never uses your Mac's camera.
Click the menu-bar icon → pick your phone → the PNG saves to your folder (default ~/Pictures/TetherShot) and copies to your clipboard. Or just press the hotkey.
| Option | What it does |
|---|---|
| ⌘⇧7 | Quick-capture every connected device, from anywhere |
| Copy to Clipboard | Also place each capture on the clipboard (default on) |
| Organize by Device | Save into a per-device subfolder |
| Choose Folder… | Pick any destination; remembered across launches |
| Launch at Login | Keep TetherShot in your menu bar across reboots |
| Check for Updates | Update via npm and relaunch |
Wi-Fi capture uses a root LaunchDaemon (tunneld) that keeps a RemoteXPC tunnel alive so captures need no sudo.
pip3 install -U pymobiledevice3 # the engine
tethershot setup-wifi # installs the tunnel daemon (admin password once)Then, with the iPhone connected by USB once:
- Enable Developer Mode — Settings ▸ Privacy & Security ▸ Developer Mode
- Enable Wi-Fi reachability —
pymobiledevice3 lockdown wifi-connections --state on
After that you can unplug. While the iPhone and Mac share a Wi-Fi network, the menu shows it as (Wi-Fi) and tunneld discovers it automatically. Remove the daemon with bash scripts/uninstall-tunneld.sh.
Why not AirPlay mirroring? On macOS Tahoe, a mirrored iPhone window blacks out whenever a capture context is active — so TetherShot uses the developer-services path instead, capturing the device's own framebuffer regardless of transport.
tethershot # launch the app
tethershot install # build & install to ~/Applications
tethershot update # update to the latest published version
tethershot setup-wifi # install the Wi-Fi tunnel service
tethershot uninstall # remove the app
tethershot version # print the installed version| Component | Role |
|---|---|
USBCapture |
Flips the CoreMediaIO screen-capture flag, finds the iPhone as a .muxed device, grabs one frame → PNG |
WirelessCapture |
Talks to the tunneld HTTP API, runs pymobiledevice3 developer dvt screenshot over the Wi-Fi tunnel |
Updater |
Checks the npm registry, runs npm install -g tethershot@latest, relaunches via a detached helper |
AppModel |
Main-actor state: device list, destination folder, options, status |
MenuContent / TetherShotApp |
SwiftUI MenuBarExtra UI, runs as an LSUIElement agent |
Capture backends sit behind a CaptureBackend protocol, so USB and Wi-Fi share one code path. The marketing/docs site lives in /web and deploys to tethershot.apoorvdarshan.com.
Contributions are welcome — see CONTRIBUTING.md for how to build, the project layout, and the PR flow.
Found a vulnerability? Please report it privately — see SECURITY.md.
If TetherShot is useful to you:
- 🚀 Vote on Product Hunt
- ⭐ Star the repo
- ☕ Support on Ko-fi
- 🐦 Follow @apoorvdarshan on X
MIT © 2026 Apoorv Darshan
Not affiliated with Apple Inc. iPhone, macOS, and Apple are trademarks of Apple Inc.