claudeyes
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@claudeyeswhat changed on my screen in the last minute?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
claudeyes
A macOS perception daemon for Claude Code that only tells the agent about screen changes it did not cause.
Why it exists
Give an agent eyes and the obvious design is: watch the screen, and when pixels change, wake up and look. That design is useless in practice, because the agent is the loudest thing on its own screen. It runs a test suite and the terminal floods. It moves the mouse and a button lights up. It types and the caret blinks. Change-triggered perception fires hardest on exactly the changes that carry no information, and the one thing you actually wanted — a build failing on its own, a Slack message, a dialog appearing behind the window — arrives in the same undifferentiated stream as the agent's own echo.
The fix is an old idea from motor neuroscience. When you move your eyes, the whole visual field sweeps across your retina, and you perceive nothing: the brain sends a copy of the motor command — an efference copy — to the visual system, which predicts the resulting sensory change and cancels it. Same reason you cannot tickle yourself. What survives the subtraction is exafference: change the world produced without you. That is the signal worth reacting to.
An agent has it far easier than a brain does. A brain has to estimate its motor consequences from noisy corollary discharge. We know the click was at (x, y) and the scroll was 400 px, because we issued it. The prediction is free.
Related MCP server: PeepIt MCP
How it works
Before an action runs, it registers a predicted screen delta. The capture loop reports the observed delta. Subtract, and what is left is the residual.
action ──► predicted delta ──┐
▼
screen ──► observed delta ──(−)──► residual ──► gate ──► wake the agent
│
└── suppressed (most of it)Everything is expressed on one coarse grid of ~32-logical-pixel cells — observed change, predicted change, habituation, priority are all "a value per region of screen", so each is another array layer rather than another data structure. A full-screen operation is a few thousand floats, and exact rectangle algebra never has to be written.
Predictions are envelopes, not masks. An action licenses a region to change, over a time window, at a confidence that decays as the window closes. A click registers a tight, certain envelope on the thing you clicked and a wide, weaker one over the window — because a click sometimes opens a modal — with the confidence falling off by distance from the pointer, so a notification in the far corner still survives the click's uncertainty window. Suppression is proportional and never absolute: a fully suppressed region is a blind spot.
"Did I cause this" is not one bit. The first version had a single suppression threshold and could not both silence a scroll repaint and surface a notification landing mid-click. That is a modelling failure, not a tuning one. Each changed cell is now attributed to one of three classes:
class | meaning | what happens |
| high-confidence motor echo — cursor, hover, caret, scroll repaint | never surfaces |
| plausibly downstream of your action but not directly predicted — the page your click navigated to | surfaces, but labelled, and routed to action verification rather than to the interrupt |
| nothing you did explains this | the interrupt. The whole point. |
Biology does the same thing: sensory attenuation reduces gain rather than gating, and "was that me?" is read out separately from "did something happen?".
Ownership beats geometry. Geometry alone cannot tell a toolbar spinner your click triggered from a banner that arrived on its own — both are far from your finger. The Swift shim tags each dirty rect with the app owning the window under it, so change in an app you never touched is foreign no matter how close it landed. Geometry is the fallback for when ownership is unavailable.
A resting cursor is state, not an event. Modelling hover as a decaying
envelope woke the agent every time it paused over a button, which is the most
common thing it does. Envelopes carry a group; a new one retires the old, so
where the pointer came to rest stays explained until the pointer actually moves.
Tool calls have no coordinates, but they do have an app. Bash does not
click anywhere — it floods a terminal. A Claude Code PreToolUse hook registers
an app-scoped envelope before the tool runs and shortens it when the tool
returns, so the agent stops waking itself on its own build output. One useful
consequence: once that scope has lapsed, a terminal that repaints on its own is
WORLD. That is a long-running process printing something after Claude thought
it was done.
What Claude gets
Three MCP tools, backed by an append-only SQLite log:
tool | for |
| ambient context. What happened that we did not cause. |
| blocks until the world does something. Use instead of sleep-and-screenshot when waiting on a build or a deploy. Past ~2 minutes it auto-backgrounds and returns as a notification. |
| is it actually watching, and is the suppression rate healthy. |
watch_for is the one that changes how it feels: the agent stops polling and
starts getting woken.
Try it without a Mac
python3 tools/demo.pyRuns a synthetic 13-frame trace — cursor moves, hover, click, page repaint, scroll, typing — with three things the world does on its own dropped into it. A correct run wakes on exactly those three:
* 2.40 *** Slack message arrives *** 48 0 0 48 WAKE
* 5.60 *** tests fail on their own *** 136 0 0 136 WAKE
* 6.70 *** popup during the click's ... *** 48 0 0 48 WAKE
13 frames -> 3 wake-upsRun it for real
cd capture && swift build -c release # macOS 13+, Xcode toolchain
cd .. && ./run.sh # capture | daemon -> ~/.claudeyes/events.dbGrant Screen Recording permission when macOS asks, or ScreenCaptureKit returns empty frames without erroring.
Wire it into Claude Code:
python3 -m claudeyes.install --apply --editor "Code"That merges the PreToolUse/PostToolUse hooks into ~/.claude/settings.json
(with a backup) and prints the two commands you still run yourself: the
claude mcp add, and the daemon.
python3 -m claudeyes.doctorchecks every link in the chain. Worth having, because the failure modes are mostly silent — ScreenCaptureKit returns empty results rather than erroring when it lacks permission, the hook exits 0 by design when it cannot reach the socket, and an unregistered MCP server just never appears.
Layout
path | what |
| Swift ScreenCaptureKit shim. One JSON line per frame: dirty rects plus the owning app. macOS only. |
| The coarse cell grid everything else is expressed on. |
| Predicted-delta envelopes: decay, distance falloff, sticky groups, app scopes. |
| observed − predicted, and the three-way attribution. The core. |
| Append-only SQLite log. Every frame, not just surfaced ones. |
| Glue. Capture JSONL in, events out. |
| The MCP server and a small JSON-RPC stdio implementation. |
| Merges the hooks into |
| Diagnoses the pipeline. |
| The |
| Synthetic trace. Runs anywhere, no Mac needed. |
| Unrelated side tool: a deliberately tiny allowlisted stdio MCP shell, so a cloud session can run |
Status
Prototype. The model is the finished part; the plumbing is not.
Working: the grid, the action bus, three-way attribution, the event log, the
MCP server, the Claude Code hooks, the installer and the doctor. 12 unit tests
pass (python3 -m unittest discover -s tests) covering confidence decay,
attribution, the sticky-cursor case and the gate. tools/demo.py runs the
whole loop end to end on any platform with no Mac and no capture binary.
The Swift shim compiles clean against the current toolchain, but it has not been run through a real session with Screen Recording granted, so the frame rate, the dirty-rect fidelity and the window-ownership index are all unproven against a live desktop. That is the gap between this being a nice model and being something I use daily.
Not built: habituation dynamics (spontaneous recovery, generalisation gradient, dishabituation) and the priority map's selection-history term. Both already have their array layer allocated on the grid and are currently identity.
The envelope constants in actionbus.py are the actual content of the model and
they were tuned against the synthetic trace, not against a real desktop. Expect
to retune them. They are deliberately generous — over-predicting costs a missed
event, under-predicting costs a false wake-up, and a false wake-up is the
failure mode this whole thing exists to kill.
License
MIT. See LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Deploy sims to any screen. Control your displays with Claude.
- SimSenseOAuthai.simsense
Deploy sims to any screen. Control your displays with Claude.
Give an AI agent eyes on the web: turn any feed, page, or stream into deduplicated change events.
- mcpOAuthcom.screenshotink
Screenshot, diff, audit and sitemap-capture any web page — 5 MCP tools for AI agents.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables Claude to see and interact with any macOS application using natural language commands. Perfect for testing Mac applications, UI automation, and app development with AI assistance.33-
- AlicenseAqualityDmaintenanceEnables AI agents to capture and analyze screenshots of macOS applications, windows, or the entire screen using local (Ollama) or cloud-based AI vision models, with non-intrusive, fast screen capture via Apple's ScreenCaptureKit.372MIT
- AlicenseNot gradedqualityDmaintenanceEnables Claude to remember and search everything that appeared on your screen using local OCR and embeddings. Provides tools for semantic search, activity timeline, and code change tracking.MIT
- AlicenseAqualityCmaintenanceEnables Claude to capture screenshots of the screen, windows, regions, and web pages, and compare screenshots for visual regression testing.6MIT