Guide
Install, configure, and debug Moosh
Moosh is a native Mac app and an MCP server. The assistant you already use — Cursor, Claude, ChatGPT, Codex, or any other MCP client — calls tools on this Mac. Clicks and files stay here.
Install
Use the app if you want the window, approvals, and the menu bar. Use Homebrew if you only want the moosh command. They are the same engine.
The Mac app
Download Moosh for Mac. Open the disk image and run Install Moosh. That puts Moosh in Applications.
The first launch opens a short setup window. After that, the menu bar has Open Moosh, Settings, Reload assistants, Emergency Stop, and Exit. The window has Live, Activity, Flows, Access, Tools, and Clients.
The command
Homebrew installs moosh from the public formula on this site. The git repository is private, so this is the install path.
brew tap imehdihosseini/moosh
brew trust imehdihosseini/moosh
brew install mooshFind the binary with which moosh. On Apple silicon that is usually /opt/homebrew/bin/moosh. On Intel it is usually /usr/local/bin/moosh. Use that full path in client configs. Apps opened from the Dock do not see the same PATH as your terminal.
Permissions
Nothing works until you grant these yourself. Moosh cannot flip the switches. Access in the window opens the matching System Settings pane.
- Accessibility is required for every UI tool. Grant it to the app that starts the server: Cursor, Claude, ChatGPT, or Terminal. If you later run
moosh install, grant it to themooshbinary itself. A launchd agent does not inherit your terminal’s permission. - Screen Recording is only for Screenshot and OCR. Grant it to the same app.
- Speech Recognition is only for
listen_to_audio, and only after you turn audio on.
Quit the client completely and open it again. macOS keeps the old decision until that process is gone. Closing a window is not enough for Claude Desktop.
Configure
Connect an assistant
Open Moosh, go to Clients, and choose Connect all. That writes the clients it finds and reloads them. Reload assistants in the menu bar does the same thing. Existing MCP servers in those files are left in place.
To write a client by hand, point it at the full path and pass no arguments.
Claude Code
claude mcp add moosh /opt/homebrew/bin/mooshClaude Desktop
Claude menu, then Settings, then Developer, then Edit Config. The file is ~/Library/Application Support/Claude/claude_desktop_config.json. Quit Claude and open it again.
{
"mcpServers": {
"moosh": {
"command": "/opt/homebrew/bin/moosh"
}
}
}Cursor
~/.cursor/mcp.json for every project, or .cursor/mcp.json inside one project.
{
"mcpServers": {
"moosh": {
"type": "stdio",
"command": "/opt/homebrew/bin/moosh"
}
}
}Codex
codex mcp add moosh -- /opt/homebrew/bin/mooshChatGPT
ChatGPT does not launch a local stdio server. Business and Enterprise or Edu workspaces can add a remote MCP app. For a server on your Mac, use OpenAI’s Secure MCP Tunnel. Clients in the Moosh window links the current instructions.
Ollama
Ollama has no MCP client of its own. Use ollmcp.
uv tool install --upgrade ollmcp
ollmcp mcp add moosh -- /opt/homebrew/bin/moosh
ollmcpAny other client
The server speaks MCP over stdio. The command is the binary, with no arguments. It prints nothing when it starts. That is correct: stdout is the protocol, and a stray line there breaks the session.
What it is allowed to do
Optional file: ~/.moosh/config.json. Override the path with OSXMCP_CONFIG or --config. If the JSON does not parse, Moosh ignores the file and starts with safe defaults: Shell off, audio off, protected paths on.
Access in the window shows the path rules as they are actually applied, including protected folders the file cannot remove. Open config folder jumps to ~/.moosh.
{
"capabilities": {
"shell": false,
"audio": false,
"screenshots": true
},
"tools": {
"exclude": ["Drag"]
},
"policy": {
"confirmation": "prompt",
"allowed_paths": ["~/Documents", "~/Desktop"],
"protected_paths": ["~/.ssh"],
"background": "prefer"
}
}Empty allowed_paths means your home directory, still minus protected paths. Blocked and protected always win. background is prefer by default: if a control can only be reached by taking the front window for a moment, Moosh does that and puts your app back. Set it to strict and those tools fail instead of borrowing focus.
Shell stays off until OSXMCP_SHELL=1 or "shell": true. Even then every command asks you. Do not enable it on a machine you cannot afford to lose.
Environment variables win over the file. Flags win for transport.
| Variable | Effect |
|---|---|
OSXMCP_SHELL=1 | Advertise and allow Shell. Each call still asks. |
OSXMCP_AUDIO=1 | Advertise listen_to_audio. |
OSXMCP_SCREENSHOTS=0 | Turn screenshots off. |
OSXMCP_COORDINATE=0 | Turn off Click, Move, Drag, and Scroll by pixel. |
OSXMCP_BACKGROUND=strict | Never take the front window. |
OSXMCP_CONFIRM=prompt | prompt, deny, or allow. allow is for tests. |
OSXMCP_EXCLUDE_TOOLS | Comma-separated tool names hidden from the client. |
OSXMCP_AUTH_KEY | Bearer token required on HTTP. |
OSXMCP_CONFIG | Path to the config file. |
One server for several clients
By default each client starts its own moosh. If you keep two or three open, one shared server is simpler:
moosh installThat installs a launchd agent which runs moosh --transport http --host 127.0.0.1 --port 8000 now and at every login. Logs are ~/.moosh/server.log and ~/.moosh/server.error.log. Remove it with moosh uninstall. moosh reload restarts the workers so they pick up a new build or config.
Grant Accessibility to the moosh binary, not only to Terminal. Clients that only speak stdio reach the shared server through mcp-remote:
{
"mcpServers": {
"moosh": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://127.0.0.1:8000/mcp", "--transport", "http-only"]
}
}
}Binding an address other than this Mac, without an auth key, is refused. An open port is full control of the machine. The key is sent as Authorization: Bearer … on every request, and it should travel over TLS if it leaves the machine.
moosh install --host 0.0.0.0 --auth-key "$(openssl rand -hex 32)" \
--ip-allowlist 192.168.1.0/24 \
--ssl-certfile ~/.moosh/cert.pem --ssl-keyfile ~/.moosh/key.pemmoosh --help lists every flag. The same settings can live under server in config.json.
Work with Moosh
Ask in the assistant you already use. Moosh is the tool layer, not a second chat. A quiet start is normal.
To check the connection, ask it to run cursor_demo. A cyan and magenta arrow crosses the screen with a label. Nothing is sent to an app.
Prefer tools that name a control — press_element, set_value, read_text, find_element — over pixel clicks. Those work in a background window and leave your pointer where it is. Use Click, Move, and Scroll when Accessibility cannot see the control.
Risky tools ask in the Moosh window before they run. Deny is the default button, so holding Return declines. Shell, trash, quit, and opening a URL ask every time. There is no “always allow” for those. A tool cannot click Allow for you.
Emergency Stop is Control-Option-Shift-Escape, or Emergency Stop in the menu bar. Every assistant stops. No tool, remote command, or this website can clear it. Reset Emergency Stop in the menu bar when you want work to continue.
Live shows who is driving the Mac. Activity is the log of what ran. Flows holds automations you choose to keep. Tool calls are captured as a candidate, and a candidate is not a flow until you accept it. Tools lists what the connected assistant can call, and is where you can take a tool away.
The arrow on screen is a drawing. It is not a second macOS pointer.
The app runs for 7 days without an account, then it is $9.99 once, in the app or on Account. The server reads the same unlock the app writes.
Debug
Most failures are the permission on the process that launched the server. Walk this list from the top.
- Every tool fails with a permission error. System Settings, Privacy & Security, Accessibility. The switch has to be on for the app that starts Moosh. After
moosh install, that app is themooshbinary. Quit the client all the way and open it again. - Screenshots fail and everything else works. The same pane, Screen Recording, same app, then restart it.
- The client says the server exited or the transport closed. Read that client’s MCP log. Moosh writes diagnostics to stderr only, prefixed with
[lifecycle +…].received SIGTERMmeans Emergency Stop, Reload assistants, or logout. It is a requested stop, not a crash. A silent start, with nothing on stdout, is healthy. - The shared server does not answer. Check the agent and the two log files:
Accessibility has to include the reallaunchctl print gui/$(id -u)/com.moosh.server tail -n 80 ~/.moosh/server.error.logmooshbinary. Homebrew’s path is a symlink. The agent records the resolved binary so an upgrade does not leave a stale path, but a permission granted only to Terminal will not cover it. - The client never lists Moosh. The config command must be the full path from
which moosh, not the bare name. Then use Reload assistants, or Connect all on Clients. Claude Desktop has to be quit, not left in the menu bar. - A config edit does nothing. The file is read when the process starts. Run
moosh reloador restart the client. A trailing comma makes the whole file invalid, and invalid JSON is skipped in favor of the safe defaults. - You want a record of what ran.
~/.moosh/audit/audit.jsonlstores the tool, target, risk, and whether you confirmed. It does not store passwords, shell command text, file contents, or screenshot pixels. Files rotate around 2 MB. Activity in the window is the same trail in readable form. - Everything is refused and the menu says Emergency stopped. Reset Emergency Stop in the menu bar. A tool cannot do that.
moosh --help and moosh --version confirm you are running the binary you think you are. Website account questions — sign-in, the lifetime purchase, deleting the account — are on Support.