Isolation & permissions
How Chataway contains local apps — who runs isolated, what is enforced for files, programs and the network (network.domains + the network grant, the macOS sandbox), why exec means everything Chataway may do, and the macOS privacy permissions.
A local app runs code on the user's Mac, so "what can it do?" deserves a precise answer. Chataway's answer depends on where the code came from, and the app page always says which applies — never more than is actually enforced.
#Who runs isolated
| The app | Runs | Label |
|---|---|---|
Your own (an app project, or a folder linked with chataway dev) | Inside Chataway, with full access — unless you switch on Run isolated | DEV |
Installed from GitHub or npm, with a server | Always isolated, in its own process | Unverified · Isolated |
| A Node MCP server from GitHub or npm | In the macOS sandbox (until the user chooses Give it full access…) | Unverified · Isolated |
| From the store | No code on the Mac at all — only its sandboxed panel | Verified |
| Built in (Media, Browser, Artifacts, Computer use) | Inside Chataway | Built in |
Run isolated is a switch on your app's page in Apps. It applies to every project the app is on in. Turn it on before you share an app: it runs exactly the way people who install it from GitHub will run it, so you catch a missing grant or host before they do.
#What's enforced
An isolated app gets its own Node process per project it's on in. On macOS that process runs inside a sandbox profile as well as Node's permission model; the two walls together enforce:
| Isolated app | |
|---|---|
| Read files | Its own install folder and its storage. Paths are checked after resolving symlinks, so a symlink in a repo can't point it at ~/.ssh. |
| Write files | Its storage folders only — not even its own code. |
| The project | Through ctx.project with project:read / project:write, relayed by Chataway — never hidden paths (.git/, .claude/, .mcp.json…) or files that run by themselves (package.json, Makefile, CLAUDE.md…). |
| Start programs | Only with the exec grant. Without it: no child processes, workers, native addons or WASI. |
| Network | Only the hosts in network.domains, and only with the network grant — below. |
| Other processes | It can signal itself and its own children, nothing else. |
| Secrets | Declared names only, read over Chataway; the process environment carries none. |
| Memory and time | 512 MB of JavaScript heap; a tool call gets 11 minutes; a process that stops answering for 15 s is restarted. |
| Crashes | Never take Chataway down. The app restarts after 1 s, 5 s and 30 s, then shows failed with the error. |
Your code doesn't need to know about any of this — except that every ctx call must be awaited.
#Network
Declare the hosts your app talks to, and ask for the network grant:
"grants": ["network"],
"network": { "domains": ["api.github.com", "*.slack.com", "localhost:4100"] },
"permissions": ["Read your repositories on GitHub and post to Slack"]- An isolated app's traffic goes through a small proxy Chataway runs for it. The proxy lets through only declared hosts — plain names on ports 443 and 80,
*.example.comfor subdomains — and resolves names itself, refusing any that point at your own machine or local network. localhost:<port>entries are honoured for your own apps only (a dev server you run); never for apps from GitHub.- No
networkgrant → no network. Grant but no domains → no network either. - Blocked requests appear in the app's Inspector as network blocked: host:port — reason, so a missing domain is easy to spot.
- Use
fetchor Node'shttp/https: they pick up the proxy automatically.
Apps from GitHub that are plain MCP servers declare their hosts in package.json: "chataway": { "network": { "domains": ["api.acme.dev"] } }.
#Without the macOS sandbox
On systems without sandbox-exec, Node's permission model is the only wall. Files and child processes are still limited, but the network limit becomes cooperative — fetch and http use the proxy, raw sockets don't — and Node doesn't restrict signals. The app page says "Network limits are advisory on this system" instead of claiming them.
#exec is full access
With exec, an isolated app may start programs. Those programs run in the same sandbox (same network and write limits) — but macOS privacy permissions don't belong to the app. They belong to the app at the top of the process tree, which is Chataway, and every program Chataway starts inherits them. If the user allowed Chataway Screen Recording or Accessibility (for Chataway's own computer use, say), a program your app starts can record the screen and drive the mouse and keyboard.
That's why Chataway words exec the same way everywhere:
Run programs on this Mac — including anything Chataway is allowed to do (screen recording, mouse & keyboard) if you granted it
and labels an exec app as having full access to this Mac, isolated or not. Ask for exec only when no host service or kernel API does the job, and say exactly which program you run in permissions.
#macOS privacy permissions
Screen Recording, Accessibility, and Files & Folders / Full Disk Access are granted to the app at the top of the process tree:
- Chataway in the installed app — users switch on Chataway in System Settings → Privacy & Security;
- Terminal (or whichever terminal app) when Chataway runs from source in development.
Your app's code and every program it starts inherit those grants. Never tell users to add node or your script to the list — it does nothing.
To open the right pane for the user, run open "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture" (other panes: Privacy_Accessibility, Privacy_AllFiles).
#What isolation doesn't do
Honest limits, so you can describe your app truthfully:
- Declared hosts are trusted. An app can send whatever it can read — its storage, files handed to it, its secrets — to the hosts it declares.
- Disk and CPU aren't capped. Only the heap is.
- Without
exec, privacy permissions are out of reach (no programs, no native code). Withexec, they aren't. - Your own apps aren't isolated by default. They run inside Chataway with full access until you switch on Run isolated.