Visual feedback for iOS apps that goes straight to your coding agent.
Freeze your running app, draw on it, tap an element or hold on an exact spot, and say what should change. Hit send, and the agent already open on your Mac gets the screenshots, the exact coordinates and your notes. You don't copy and paste anything or tag any views, and it lives only in your DEBUG build.
How you use it
- Tap the Annotate pill in your running app. The screen freezes.
- Draw around anything, tap an element to outline it, or hold for half a second to pin an exact spot.
- Type what should change. The chip says Fix; switch it to Question when you only want an explanation.
- Add as many notes as you like. To cover another screen, leave annotate mode, navigate and come back. One send carries them all.
- Hit ↑. Claude Code, already open on your Mac, picks it up.
- Keep watching the pill. It narrates the agent's progress, and each note's badge spins until it's handled, then turns into a green check.
It works the same from the Simulator and from a physical iPhone, with no extra setup. Every
overlay type is behind #if DEBUG, so none of it ships in Release.
What your agent gets
An agent finds things by looking, so every note arrives with numbers it can check instead of a description it has to interpret.
- 1x screenshots where pixel = point. A 402×874 pt screen is a 402×874 image, so a vision model sees it unscaled and a pin at (84, 322) is pixel (84, 322).
- Annotated screens and crops. A copy of each screen with numbered blue markers, outlines and your red drawings, plus a native-resolution crop around every pin.
- Exact coordinates. Each pin has an anchor (where you tapped, or a drawing's center), the element's frame, and its position as percentages across and down. All in iOS points, origin top-left.
- Nearby visible text. Each pin lists the text around it, and each screen lists every visible label with its frame. That's usually enough to grep straight to the right view.
- Device info. Model, iOS version, screen size and scale, appearance and Dynamic Type size.
Without it, you write "the blue button near the bottom is too small" and the agent guesses
which one. With it, the agent reads Button "Get started" at (24, 300, 120×44),
tapped at (84, 322), next to the text "Light that follows your day".
Part of the prompt the agent receives:
UI annotations from the running app: 3 pins on 1 screen. Please make these changes in the code.
Device: iPhone 17 Pro · iOS 26.0 · 402×874 pt @3x · dark · Dynamic Type L
Coordinates are iOS points, origin top-left. Screen images are 1x, so pixel = point.
1. Button "Get started" at (24, 300, 120×44) — tapped (84, 322), 21% across, 37% down
bigger, tighter
Nearby text: "Light that follows your day"
Crop: …/crops/1.png
2. Spot at (179, 678, 44×44) — tapped (201, 700), 50% across, 80% down
too much empty space here
Agents talk back
Sending isn't the end of it. The agent reports to the phone while it works, pin by pin.
annotation_waitblocks until you send (or answer a question), then returns everything. That gives hands-free delivery in any MCP client. The dot on the pill is green while an agent listens, yellow while it reconnects and red when nothing is listening.- Resolve or dismiss. Each pin comes back resolved, with what changed, or dismissed, with why. Tap the note count to see them sorted into Current, In Progress, Resolved and Failed.
- Ask. When a pin is unclear, the agent asks about it. The pill says so, the notes sheet shows a Reply button, and your answer goes back to the agent, from a phone too.
- Intent. Every note carries its chip into the prompt: Fix to change the code, Question to explain it without editing.
Agents report with the MCP tools or with the CLI:
annotate resolve <id> <pin> "what changed"
annotate dismiss <id> <pin> "why not"
annotate ask <id> <pin> "question" # waits for the answer and prints it
Install
Let your agent do it
Tell Claude Code, Cursor or Codex:
Set up AnnotateKit from github.com/ooolzhas/annotatekit in this app.
The repo ships an annotate-setup skill that walks the agent through every project
shape (Xcode project, XcodeGen, Tuist, SwiftPM), the CLI and the connection. In Claude Code,
the plugin brings the skill, the MCP server and the CLI in one step:
/plugin install annotate --marketplace ooolzhas/annotatekit
On Claude Code older than 2.1.275, run /plugin marketplace add ooolzhas/annotatekit,
then /plugin install annotate@annotatekit.
By hand
1. The overlay. Add the package with Swift Package Manager and link AnnotateKit to your app target (iOS 17+).
https://github.com/ooolzhas/annotatekit
import AnnotateKit
@main
struct MyApp: App {
init() {
Annotate.install() // DEBUG-only; a no-op in Release
}
var body: some Scene { WindowGroup { ContentView() } }
}
Then add .annotate/ to your .gitignore.
2. The CLI. Skip this if you installed the Claude Code plugin. Pick one:
brew install ooolzhas/tap/annotate
npm install -g annotate-ios
mint install ooolzhas/annotatekit
Connect your agent
Pick how a send reaches your agent.
- Claude Code + channels Recommended
-
Pushed into your open session the moment you hit send, even while Claude is idle. Start
with
claude --dangerously-load-development-channels plugin:annotate@annotatekit, orserver:annotatewithout the plugin. - Claude Code, no flags
- Run
/annotate-watch. A watcher picks up each send. - Unattended
-
annotate runin the project root runsclaude -pper send, with--permission-mode acceptEdits, resuming the conversation. - Cursor, Codex, VS Code, Claude desktop, any MCP client
- Add the MCP server and ask the agent to "keep calling annotation_wait". Each call waits for your next send. Or say "check my latest annotation" now and then.
Channels are a Claude Code research preview. The development-channels flag lifts the allowlist check only for the server you name, and Claude Code asks you to confirm. Team and Enterprise orgs need an admin to turn channels on.
MCP configs for Cursor, VS Code and Codex
The server is annotate mcp over stdio, run from the project root.
// Cursor: .cursor/mcp.json
{ "mcpServers": { "annotate": { "command": "annotate", "args": ["mcp"] } } }
// Nothing installed? npx fetches the CLI on first run (macOS)
{ "mcpServers": { "annotate": { "command": "npx", "args": ["-y", "annotate-ios", "mcp"] } } }
// VS Code: .vscode/mcp.json
{ "servers": { "annotate": { "type": "stdio", "command": "annotate", "args": ["mcp"] } } }
# Codex: ~/.codex/config.toml
[mcp_servers.annotate]
command = "annotate"
args = ["mcp"]
Claude Code without the plugin: claude mcp add annotate --scope project -- annotate mcp