His computer
A shell, an editor and a browser of his own, on your Mac, with rails.
One toolset, everywhere
Edward has the same fourteen tools in every turn: your chat, voice, pings, his wakes, the screens’ pulse and scheduled events. What a turn may do with them is its policy (did you ask? may it reach people? may it push?), checked when a tool is called; a refused call comes back as an honest Tool error: with the reason.
| Tool | What it does |
|---|---|
bash | A persistent shell in his home folder, sandboxed |
str_replace_based_edit_tool | View, create and edit files, under the same rails |
web_search, web_fetch | Search the web and read pages |
browser | His own invisible browser |
chrome | Your Chrome, through the Edward extension (off by default) |
look | See images, PDFs, a web page or the screen as pictures |
messages | Read iMessage and mail |
send_message | The one guarded way to message someone |
tell_owner | Reach you: a note on Today, or a push |
memory | Search, remember, close, explain or forget memories; read and write documents |
schedule | Reminders, follow-up wakes, your calendar and Reminders |
screen | His screen, the household screen and the iPhone widget |
plan | A visible checklist for longer work |
Skill switches only take tools away: Shell/Bash gates the shell and editor, Web Search the web tools, iMessage the message tools, iOS Widget the widget, Push Notifications the urgent push.
His home and his shell
~/edward-home is his: bin/ (on his PATH), projects/, skills/, downloads/, jobs/ for background logs, and a Python 3.12 environment of his own. He may pip install, use uv and npm, and brew install ordinary formulae.
- One persistent
bashper conversation, socdand variables carry over between commands. - 180 seconds a command; long work is a background job plus a scheduled wake to check on it.
- A watchdog kills a session past 2 GB of memory or when the disk runs low; at most four sessions at once.
- Every output is scanned and secrets are redacted before the model sees it.
- Its environment is an allowlist: no API keys, no
.envvalues, no database address. - If the sandbox can’t apply,
bashfails closed. It never silently runs unsandboxed.
The rails
The shell runs under a macOS Seatbelt profile rendered from one table of rails, which the in-process editor checks too:
- Not his own credentials: the session-signing key, the setup code and
.env, however the path is spelled (compared by the file’s identity on disk, so case variants, symlinks and hard links count). - Not his own running code: no writes to the checkout Edward runs from, his releases or his own sandbox config, and none of the directories above them can be renamed or moved.
- Not what production runs on: no writes to either Postgres cluster’s data or to Homebrew’s
[email protected]andpostgresql@16, and no upgrading them. - Not the services that act as you: no connection to Edward’s own API (:8000, :3000), the WhatsApp bridge, or his databases (:5432, :5433).
- Not your other apps: no launching or scripting apps (messages go through
send_message, nevertell application "Messages"), never a second Google Chrome, and signals only to his own processes.
The sandbox is not a containment boundary. The shell runs as your macOS user. Reads are open (except his own credentials), and writes are open everywhere but the protected paths, including your shell startup files, ~/Library/LaunchAgents and Homebrew, from which programs later run as you, outside the sandbox. The rails stop accidents and turn misuse into deliberate work; they don’t make it impossible. For real isolation, run Edward under his own macOS user (prompt G in Adapting to your Mac). Short of that, keep friends’ pings on their default, which gives them no shell.
Two browsers
browser: his own
Playwright’s bundled headless shell, never Google Chrome, with his own cookies (never yours). It opens http and https only, and every request and redirect is checked: nothing on this Mac or your network, only public addresses. He can open, read, find, click, type, scroll and download.
chrome: yours, if you allow it
With EDWARD_CHROME_HANDS=on and the unpacked extension in chrome-extension/ loaded, Edward can use your own, signed-in Chrome. The extension connects only directly from this Mac, and only Edward’s own extension ID is accepted. Rails:
- Typing outside a search box, pressing Enter there, or clicking anything labelled send, post, delete, accept, confirm, share and the like acts as you, so it runs only when you asked in that turn.
- A payment step, or typing anything that looks like a card number, is refused in every turn.
- Taking a picture of a tab never switches your active tab.
Chrome shows its “being debugged” bar while he works, unless you set EDWARD_CHROME_SILENT_DEBUGGER=on. With the hands on, /screen also opens as a tab in your Chrome (see Widget, screen & hub).
look
look hands the model the picture itself, not another model’s description of it: a photo from a chat, a file, a PDF, a web address, his own page, your Chrome tab, or this Mac’s screen (which needs Screen Recording for the backend’s python). Images are scaled to 1600 pixels at most, never up; a turn carries at most 40 images.
The web
On Claude, web_search and web_fetch are Anthropic’s server tools: the search and fetch run at Anthropic. With EDWARD_SERVER_WEB_TOOLS=off (or on the Codex fallback) they run locally: Brave Search with your key, and a local fetch that refuses this Mac and your network on every hop.
Your calendar and Reminders
- Reading: straight from Calendar’s and Reminders’ own databases on this Mac (Full Disk Access), read-only, in every turn. If they can’t be read he says so; he never reports an empty day instead. apple-mcp, if set up, is the calendar’s fallback.
- Changing: only when you ask, through a small signed EventKit helper (macOS 14+). Grant it once, at the Mac, with
bash backend/scripts/eventkit_request_access.sh. Edward never asks macOS himself, because a dialog nobody answers would hang a turn.
The long form, including the full list of what the sandbox does not prevent, is computer.md.