Skip to content
Conduit

mcp server

Moonwalker

A floating AI assistant for whatever is on your screen. Click the bubble, ask about your game, film or app, get an answer in seconds. Works with Claude, GPT-4o, Gemini, Groq, OpenRouter or a local mod

morpheusadam/Moonwalkercommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

Before you start

  • uv (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "moonwalker": {
      "command": "uvx",
      "args": [
        "moonwalker"
      ]
    }
  }
}

same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12

Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs

README

synced Oct 21, 2026

Moonwalker

An open-source desktop assistant that captures your screen on a click and answers questions about what is on it, for anyone who wants to ask an AI about a game, a film, an unfamiliar app or an error dialog without leaving it.

License: MIT Python PySide6 Platform MCP Telemetry

Table of contents

Overview

Moonwalker is a small glass bubble that floats above every other window. One click captures the screen exactly as it looks, and a frosted panel opens beside it with a text box. You type a question, and the answer streams back over your game, your video player, or the app you have never used before.

It never takes keyboard focus, so a fullscreen game underneath keeps running instead of minimising itself.

The design brief was deliberately general. It began as a Persian-subtitle tool for a single game and was rebuilt as something game-agnostic, app-agnostic and language-agnostic, because the underlying problem — "I can see it, but I do not understand it" — is the same everywhere.

Where it helps

SituationWhat you askWhat you get
Stuck in a game"Which of these three upgrades should I take?"What each one actually does, and which is worth it
Foreign-language game or film"Translate this."The dialogue, translated, with the speaker's tone kept
A scene you did not follow"What is happening here?"The scene explained, from what is visibly on screen
First time in an unfamiliar app"What do these buttons do?"The interface explained, in place
An error dialog you have never seen"What broke and how do I fix it?"A read of the actual message, plus next steps
A dense document or chart"Summarise this."The point of it, without retyping anything

How it works

flowchart LR
    A["Click the bubble"] --> B["Screen captured as PNG<br>downscaled, in memory"]
    B --> C{"Provider<br>you configured"}
    C -->|"no API key"| D["Claude Code CLI<br>persistent session"]
    C -->|"API key"| E["Anthropic · OpenAI · Gemini<br>Groq · OpenRouter · local"]
    D --> F["Answer streams into<br>the glass panel"]
    E --> F
    F --> G["Session log<br>text only, on your disk"]
    G --> H["@eye MCP server<br>hands it to Claude Code"]

The bubble and panel ask Windows to exclude them from screen capture (WDA_EXCLUDEFROMCAPTURE), so Moonwalker never photographs itself and never has to flicker out of the way. Where the OS does not support that, it hides them for one frame instead.

Requirements

  • Python 3.10 or newer
  • PySide6 6.6 or newer (installed automatically)
  • For the Claude Code provider: Claude Code, installed and signed in. Every other provider needs only an API key.

Install

git clone https://github.com/morpheusadam/Moonwalker.git
cd Moonwalker
pip install -e .
moonwalker

Or straight from the source tree, with no install step:

python -m moonwalker

Using it

ActionResult
Click the bubbleCaptures the screen and opens the panel. Click again to close
Drag the bubbleMoves it; the position is saved
Right-click the bubbleSettings, autostart, panel side, quit
Type and press EnterAsk anything about what was captured
Quick buttonsTranslate, Explain, What now?
Bin icon in the headerWipes the conversation; nothing earlier is remembered
EscapeCloses the panel; the bubble stays

[!NOTE] A game in exclusive fullscreen hides every overlay, Moonwalker included. Switch it to borderless or windowed mode.

Supported AI providers

Pick one in settings and change it at any time. Keys are stored per provider, so switching back and forth never loses them.

ProviderAPI keyDefault modelNotes
Claude Code (CLI)not neededhaikuReuses the Claude Code subscription already signed in on your machine
Anthropic APIrequiredclaude-haiku-4-5Also Sonnet 5 and Opus 5
OpenAIrequiredgpt-4o-miniAlso GPT-4o, GPT-4.1-mini
Google Geminirequiredgemini-2.0-flashGoogle AI Studio's free tier covers casual use
Groqrequiredllama-4-scout-17bFree tier, vision models
OpenRouterrequiredgemini-2.0-flash-exp:freeModels ending :free cost nothing; Llama 3.2 Vision, Qwen2.5-VL and others
Custom or localrequiredyour choiceAny OpenAI-compatible server: LM Studio, Ollama, vLLM, or your own gateway

Anything speaking OpenAI's dialect works without new code; a base URL is enough. Adding a whole new service is usually one entry in providers/__init__.py.

To run fully offline, point the custom provider at a local vision model in Ollama or LM Studio. Nothing then leaves your machine.

Features

Interface

  • Glassmorphism using the platform's acrylic blur behind a translucent pane
  • Automatic light and dark glass, chosen from how bright the screen behind actually is
  • Animated bubble: three colour blobs drifting under a glass disc, with a progress ring while it thinks
  • Drag the bubble anywhere; the position is remembered
  • Every icon is vector-drawn at runtime, so it looks identical on every OS
  • Answers stream in token by token, re-rendered on a 60 ms cadence

Behaviour

  • Never steals focus, so fullscreen games stay open
  • Excluded from its own screenshots at the OS level
  • Multi-monitor aware: captures the screen the bubble is on
  • Quick asks: Translate, Explain, What now?
  • One-click history wipe
  • Autostart at login on Windows, Linux and macOS, without admin rights

Language

  • Answers in 11 preset languages, or any language you type in
  • Right-to-left support with bidi isolates, so +112% never renders backwards inside Persian text
  • Arabic-to-Persian letter and digit normalisation (ي to ی, ك to ک)
  • Persian punctuation, applied only where it is genuinely punctuation
  • Vazirmatn bundled (SIL OFL), so RTL text renders correctly with no system font installed
  • The input box flips direction as you type

Engineering

  • One dependency: PySide6. Everything else is the standard library
  • Markdown rendered by a small purpose-built renderer, escaped first, so model output cannot inject markup
  • Persistent CLI session: roughly 8 s cold start paid once, follow-ups around 2.5 s
  • Atomic writes for config and session log, so a reader never sees a half-written file
  • Failures degrade instead of crashing: no blur, no autostart, corrupt config, and the app still starts

Claude Eye, the MCP server

Moonwalker ships an MCP server called eye, which gives Claude Code sight of your screen. A VS Code extension in moonwalker/vscode-extention/ registers it for you.

MentionAttaches
@eye:screen://nowA screenshot of your screen as it looks right now
@eye:moonwalker://sessionThe conversation from the Moonwalker floating panel
What does @eye:screen://now say? Translate it.
Continue from @eye:moonwalker://session — what should I pick?

Three tools are exposed as well — capture_screen, read_moonwalker_session and clear_moonwalker_session — so "have a look at my screen and tell me what's wrong" works with no mention at all. This is what makes a question portable: start it over a game with one click, finish it in your editor with the full context intact.

Run the server standalone with python -m moonwalker.mcp_server. The protocol is implemented directly against the JSON-RPC spec rather than through the mcp package, to keep the dependency count at one.

Privacy and trust

This section is written to be checked, not believed. Every claim below points at the code that backs it.

ClaimWhere to verify
No telemetry, no analytics, no account, no sign-upSearch the tree for a network call: the only ones are to the provider you configured — providers/http.py
Screenshots are never written to diskCaptured to memory as PNG bytes and passed straight to the provider — capture.py
The session log stores text onlyhistory.py — questions, answers, timestamps. No images
Old screenshots are dropped from historyReplaced by a short placeholder after answering, so a fifth question does not resend five images — providers/http.py
API keys stay on your machine~/.moonwalker/config.json, chmod 600 where the OS supports it — config.py
The screen is captured only when you clickThe capture call has exactly one caller, on the bubble's click handler — app.py
One dependencyPySide6. Everything else is Python's standard library — pyproject.toml

The whole project is about 3,300 lines of Python across 24 files, plus 363 lines of JavaScript in the VS Code extension. There is no build step, no minification, no bundled binary and no obfuscation, so what is in this repository is exactly what runs. Every module opens with a comment explaining why it exists and what trade-off it makes.

[!IMPORTANT] Moonwalker sends your screenshot to whichever AI provider you select, and that provider's own privacy policy then applies to it. Only capture screens you are willing to share with it. To keep everything local, point the custom provider at Ollama or LM Studio.

Cost control

Two things dominate the bill, and both are tunable in settings.

The screenshot. Vision models charge by area, so cost scales with the square of the width.

Capture widthApprox. tokens per question
800 px~570
1200 px (default)~1,280
1600 px~2,270
2000 px~3,550

The conversation. Every follow-up resends what came before. Turning "Remember context" off makes each question independent, which is the cheapest mode, at the cost of not being able to say "and the second one?".

On the Claude Code provider a third factor applies: the CLI's default system prompt. Moonwalker replaces it outright, disables every built-in tool, and skips CLAUDE.md, user settings and other MCP servers, measured at 14.1k input tokens per turn against 35.5k with the defaults, roughly halving the round trip.

Platform support

PlatformStatus
Windows 11 / Windows 10 (2004+)Full: acrylic blur, capture exclusion, registry autostart
Linux / X11Works. No blur; the pane thickens to compensate. XDG autostart
macOSWorks. No blur; the pane thickens to compensate. LaunchAgent autostart
Linux / WaylandScreen capture is blocked by design and needs an XDG desktop portal backend. Not implemented yet; contributions welcome

Configuration

Settings live in ~/.moonwalker/config.json and are editable from the panel or by hand. Set MOONWALKER_HOME to move the directory.

KeyDefaultPurpose
providerclaude_cliWhich backend answers
answer_languagePersianLanguage of the answers; the interface stays English
capture_width1200Screenshot width before sending; the main cost dial
keep_historytrueOff makes every question independent and cheapest
persian_digitsfalseRender digits as ۰۱۲۳ in RTL answers
system_promptsee config.pyResent every turn, so keep it short
panel_themeautoauto picks light or dark glass from the screen behind
panel_opacity7220 to 100
panel_width / panel_side460 / rightPanel geometry

FAQ

Over borderless and windowed fullscreen, yes, and it will not minimise the game, because it never takes keyboard focus. Over exclusive fullscreen, no: that mode gives the game the display outright and hides every overlay on the system, not just this one. Switch the game to borderless.

The application is MIT-licensed and free. The model behind it is whatever you choose. There are three genuinely free routes: the Claude Code provider on a subscription you already pay for, the free tiers at Google AI Studio, Groq and OpenRouter, or a local model through Ollama or LM Studio.

One request per question, containing the system prompt, the current screenshot, your question, and, if "Remember context" is on, the text of earlier turns in this session. Screenshots from earlier questions are replaced by a placeholder and never resent. Nothing is sent when you are not asking, and nothing goes anywhere except the provider you configured.

Yes. Choose the custom provider and point it at a local OpenAI-compatible server running a vision model: LM Studio, Ollama or vLLM. No traffic leaves your machine.

Deliberate. A translated interface has to be maintained in lockstep with the code, while the answer language is a single setting that costs nothing to change. Answers detect their own direction and flip to right-to-left on their own.

Carefully, because the naive result is wrong. A Persian sentence containing Latin runs, which in a gaming context is most sentences, gets reordered by the Unicode bidi algorithm so that +112% can render with the sign on the wrong side, turning a buff into a debuff. Each Latin run is wrapped in bidi isolates so it resolves independently. Arabic letter forms are normalised to Persian, and punctuation is converted only where it is genuinely punctuation, never inside 1,024. See rtl.py.

If it speaks OpenAI's dialect, add one Backend(...) entry to CATALOGUE in providers/__init__.py with a base URL, and no new code is needed. If it has its own wire format, subclass _HttpProvider in providers/http.py and implement four small methods.

No. There is no background capture loop, no recording and no index. The screen is grabbed at the moment you click the bubble, or when Claude calls capture_screen through the MCP server, and at no other time.

Contributing

Issues and pull requests are welcome. The most useful things right now:

  • Wayland screen capture through the XDG desktop portal
  • macOS and Linux polish; the blur path is Windows-only today
  • More providers, especially local ones
  • Language coverage; the RTL work is Persian-tuned and needs testing for Arabic, Hebrew and Urdu

Every module starts with a comment explaining its reasoning; please keep that convention.

Licence

MIT — see LICENSE.

Vazirmatn is bundled under the SIL Open Font License.

↑↓ navigate openesc close