Agent start here
You can see the Mac, and drive it.
Action is a local macOS runtime. It gives an agent two connected surfaces: native control of the machine — observe a window, resolve a target, act, record the run as video plus a trace — and a real Chrome the agent owns, with DOM-level tools.
Everything runs on the user's Mac. Nothing is hosted.
What you get
Two MCP servers. Ask for both when the work crosses between the browser and the rest of the desktop.
| Server | Tools | Use it for |
|---|---|---|
actionnative runtime |
action.observe.* (screenshot, accessibility tree, OCR, vision), action.resolve.target, action.act.execute, action.record.*, action.drive.*, action.artifacts.list |
Any native macOS app — including the user's own Chrome window. Recording a run as .mov plus trace, screenshots, AX snapshot, and a manifest. |
action-browserplugin |
browser_open, browser_snapshot, browser_click, browser_fill, browser_screenshot, browser_tabs, browser_profiles, browser_use_profile, browser_import_cookies, browser_close |
Web work in a real, non-headless Chrome that Action owns. Stable CSS selectors instead of pixel-hunting. |
Action separates the two on purpose. Native control works on anything on screen but reasons about pixels and accessibility. Browser control gives you the DOM, but only inside a browser Action owns. Which one you need is usually decided by the next section.
Which browser am I driving?
Three different browsers can be meant by "open it in Chrome". They are not interchangeable, and the difference is what kind of control you get.
| Browser | What it is | What you can do |
|---|---|---|
| The user's regular Chrome | Their everyday browser and its real profiles — Default, Profile 1 / “Work” — with their tabs, history, extensions, and logins. |
browser_open { mode: "regular" } opens a URL there and stops. No DOM tools. To act on that window, use native control: action.observe.snapshot → action.resolve.target → action.act.execute. |
| An Action browser | A real Chrome that Action owns, on its own user-data-dir. The default identity agent-browser is blank and signed into nothing. |
Full DOM tooling — snapshot, click, fill, screenshot. This is the default and the right answer for anything public. |
| An Action identity seeded from a Chrome profile | The same Action-owned Chrome under a name you choose, carrying cookies copied from one of the user's real profiles for an explicit list of domains. | Full DOM tooling, on sites the user is already signed in to. This is how you get both. |
The tradeoff in one line: the user's Chrome has their session but only screen-and-accessibility control; an Action browser has DOM control but starts as a stranger. Seeding is how you get both — and it is a boundary Action does not cross, because Chrome 136+ ignores remote-debugging switches for the default profile.
Seed, then drive
The user's “Work” browser is a display name; the directory behind it is usually Profile 1. Map it, preview the cookies, get approval, then write.
browser_import_cookies { listSourceProfiles: true }
// -> [{ dir: "Default", name: "Personal" }, { dir: "Profile 1", name: "Work" }]
browser_import_cookies { into: "work", source: "Profile 1", domains: ["github.com"] }
// dry run: lists exactly which cookies would be copied
browser_import_cookies { into: "work", source: "Profile 1", domains: ["github.com"], confirm: true }
browser_open { url: "https://github.com/notifications", profile: "work" }
browser_snapshot
browser_screenshot
Always pass a domain allowlist, never the whole cookie jar. confirm: true needs the user's approval, and cookies alone may not carry passkeys or SSO device trust — observe the page before claiming it is signed in.
Connect
Requires macOS on Apple Silicon, Google Chrome, and Bun. The browser plugin installs from the Action marketplace; the native runtime needs the app built locally.
Codex
codex plugin marketplace add arach/lattices codex plugin add action-browser@action
Start a new task afterwards so the MCP tools load.
Claude Code
claude plugin marketplace add arach/lattices claude plugin install action-browser@action --scope user
Then /reload-plugins, and /mcp to confirm action-browser is connected. After a plugin version bump, reinstall so cached metadata is replaced.
Kimi Code
/plugins install https://github.com/arach/lattices/tree/main /reload
Pin the branch — a bare repository URL installs the latest release, which may predate the manifest.
Native runtime
Clone Lattices, install the Action product dependencies, build the signed app, and grant Accessibility plus Screen Recording. native:doctor reports the current permission state.
git clone https://github.com/arach/lattices.git cd lattices bun --cwd products/action install bun --cwd products/action native:app:build bun --cwd products/action native:doctor bun --cwd products/action mcp
First move once connected: browser_open then browser_screenshot for the browser, or action.health then action.observe.snapshot for the desktop. Before multi-step UI work, call action.drive.begin so the operator can see who is driving and why.
Canonical docs
Plain markdown at stable URLs, safe to fetch and quote.
- /action/llms.txtIndex of everything below, in one file.
- AGENTS.mdRepo rules, structure, and navigation for agents working on Action itself.
- browser-profiles.mdThe three browsers, cookie seeding, identities, and plugin versioning.
- api.mdThe local WebSocket agent protocol.
- getting-started.mdShortest path to a working local loop.
- overview.mdWhat exists today and where the edges are.
- ARCHITECTURE.mdHow the app, agent, and runtime split responsibilities.
- recording.mdRecording lifecycle and the finished-marker contract.