I Rebuilt Claude Code's Browser and Memory for Pi A developer whose Anthropic account was banned rebuilt two Claude Code capabilities for the Pi coding agent as open-source projects: pi-in-chrome, a browser extension and bridge, and pi-project-memory, project-scoped Markdown memory. Both were reverse-engineered from Claude Code's Bun-compiled binary using the multi-agent framework REA (rea-agents), which extracted NUL-delimited UTF-8 sources from the __BUN/__bun section at file offset 67993600; of the derived subset, 9 JS files parsed and 0 failed, a picture the author calls partial by construction. The author argues the Chrome extension and auto memory are capabilities wired to an Anthropic account — gated by claude.ai OAuth consent, a url_hash_check call and remote flags including the auto-dream consolidation pass — so the ban removed them even though the code remained on disk. I Rebuilt Claude Code's Browser and Memory for Pi My Claude account got banned. Anthropic https://www.anthropic.com did not explain, and I am not going to invent a reason on its behalf. But the enthusiasm with which it shuts out users in mainland China is genuinely hard to understand — it stopped looking like a business decision a while ago. What I can say is what happened next: the subscription stopped, and with it stopped the two parts of Claude Code https://github.com/anthropics/claude-code I used every day. Not the chat. The other two: the Chrome extension that lets the agent actually click around a page, and the auto memory that lets it remember a project between sessions. Pi already has a healthy plugin ecosystem, and both of these areas are covered. There are several memory extensions, and several browser bridges built on Playwright https://playwright.dev or MCP https://modelcontextprotocol.io . I tried a few of each, and none of them was quite what I wanted. The memory plugins mostly stop at store-and-recall, or reach for a database and an embedding pipeline to manage a folder of Markdown. The browser bridges tend to open a browser of their own instead of the Chrome window I am already logged into, and few offer the accessibility-tree plus stable ref X workflow that made the original extension pleasant to use. So I took both apart and rebuilt them for Pi https://github.com/earendil-works/pi-coding-agent . They are open source now: - pi-in-chrome https://github.com/adlternative/pi-in-chrome — the browser extension and its bridge - pi-project-memory https://github.com/adlternative/pi-project-memory — project-scoped Markdown memory Both were reverse-engineered from Claude Code’s own artifacts with REA https://github.com/morluto/rea . There is a lens that makes the whole thing legible. Anthropic is an Apple company: a polished walled garden, a login wall, app-store logic, and a quiet confidence about who deserves to hold the device. In the taxonomy popularized by the Chinese streamer 户晨风 https://zh.wikipedia.org/wiki/%E6%88%B7%E6%99%A8%E9%A3%8E , I am an Android person — the kind who unpacks the extension, reimplements the protocol, keeps the files on his own disk, and expects the model endpoint to be his too. This post is what happened when the wall met the screwdriver: two rebuilt projects, and the four places where copying Claude Code does not work. Why these two capabilities Everything in Claude Code looks like a feature. Only some of it is a capability you can lose. A prompt template is a feature: you can rewrite it. A tool schema is a feature: you can re-declare it. But the Chrome extension and auto memory are capabilities wired to an account . The extension needs a claude.ai login and OAuth consent, it asks Anthropic’s cloud whether a URL is allowed url hash check , and its background jobs sit behind remote flags. Auto memory’s extraction and its consolidation pass auto-dream are also flag-gated. That is why the ban did not degrade my workflow, it amputated it. The code was still on disk. The gates were closed. REA: turn a product back into a protocol Claude Code ships as a Bun-compiled binary. REA https://github.com/morluto/rea rea-agents is a multi-agent reverse-engineering framework: it maps the artifact, extracts the embedded JavaScript, and runs several analysis agents over different slices, cross-checking each other. For the memory work I kept the receipts, because “I decompiled it” is not an argument. The installed claude.exe was identified by hash, and the BUN/ bun section at file offset 67993600 yielded NUL-delimited UTF-8 sources. That is extraction, not decompilation: no original source is recovered. Of the derived subset, 9 JS files parsed, 0 failed, and several semantic graphs were too large for the result budget. So the picture is partial by construction , and I wrote that down instead of pretending otherwise. The single most important discipline came out of this: presence is not activation. A shipped branch can sit behind a remote flag forever. auto-dream is gated by tengu onyx plover before its own autoDreamEnabled check; extraction is gated by another flag with a false fallback. If you read the code and conclude “Claude Code does X for every user”, you are usually wrong. You have to separate what shipped from what runs for you . That distinction is also what makes the rebuild honest: I am not cloning a product, I am re-implementing a protocol and a data layout, then choosing my own defaults. pi-in-chrome The extension turned out to have four layers, in increasing order of interest: 1. A pairing tunnel. Claude Code and Chromium talk over a Unix domain socket with AES-GCM encrypted frames. 2. A CDP driver https://chromedevtools.github.io/devtools-protocol/ . Clicks, keys, scrolls and screenshots go through chrome.debugger , not synthetic DOM events. 3. An accessibility index. Pages are flattened into a screen-reader tree with stable ref X identifiers, so the model can point at elements instead of guessing pixel coordinates. 4. Artificial bottlenecks. A cloud URL check, a 600×600 confirmation modal that aborts automation after 30 seconds, and a regex censor that rewrites anything matching /author|auth|token|session/i into BLOCKED . The rebuild keeps 1–3 and deletes 4. localhost , intranet hosts and offline apps just work; there is no login, no API key, and no popup. Tool calls stay inside a dedicated Pi tab group so personal tabs are untouched, and a 3-second heartbeat plus chrome.alarms reconnects the native host instead of dying on the first disconnect. Then I hit the interesting bug. Pitfall 1: find insists on calling Haiku find is a natural-language element finder: “the submit button in the second card”. Of the whole tool set, it is the only one that needs a model, because someone has to map a sentence onto an accessibility tree. Claude Code hard-wires that call into the extension’s own Anthropic client, using a small fast model claude-3-5-haiku https://www.anthropic.com/claude/haiku . No login or anthropicApiKey in chrome.storage meant every find failed with Anthropic client not available . The keyword fallback in the extension was dead code, because the MCP tool context always injects createAnthropicMessage . My first port kept that shape, and it failed exactly the same way. The fix was to invert the ownership: the host owns the model. - Pi advertises relay inference: true when it executes a tool and has a model. - The extension answers by emitting an inference request notification instead of calling Anthropic. - Pi runs ctx.modelRegistry.complete with the current session model and returns the sample. - The reply travels as {method:"inference response", params:{request id, result}} rather than a new top-level frame type, because the installed native host forwards frames only as {type:"tool request", method, params} . If Pi has no model, the tool falls back to read page plus refs. The model is optional again. The design point is not “Haiku is bad”. Routing a cheap model for “pick one element” is a sensible cost optimization. The problem is that it also makes “can I automate my own localhost” depend on a vendor account. A browser extension should not own a model; the agent it is attached to already has one. Spending a few more tokens is a much better trade than a single point of failure. Pitfall 2: the bridge has an owner The extension does not talk to the browser directly. It talks to a native messaging host, and Claude Code’s host binary and extension ID are fixed. Rebuilding means owning the whole chain: a new extension ID, your own native host manifest, your own socket directory, and a packaging step that rebuilds the service worker without Vite’s hashed chunks. There is a subtle failure mode here. Once your extension and Claude Code’s extension are both installed, a tool call can be routed back into Claude Code’s bridge, and you get a confusing half-working session where some calls are answered by the thing you were trying to escape. The last commit on the project is literally fix: never route tool calls into Claude Code's bridge by default . pi-project-memory Memory is a design argument, not a feature. Three agents, three answers: | | Claude Code | Codex | This plugin | |---|---|---|---| | Store | ~/.claude/projects/