A fork of
zed-industries/claude-agent-acpthat restores Zed's Review Changes diff UI for Claude Code file edits.
This adapter connects Claude Code to Zed via the Agent Client Protocol (ACP). It adds a transparent PostToolUse intercept that routes file Write/Edit operations through Zed's buffer system, triggering the native Review Changes multibuffer where users can accept or reject each edit inline.
The upstream adapter (v0.18.0+) writes files directly to disk. This fork lets the built-in Edit/Write tools execute normally, then immediately reverts the file and routes the new content through Zed's fs/write_text_file ACP API, so every file change gets a diff review.
This fork also carries a small set of local session-config improvements on top of rohan/main:
- Model capability tracking so config options can react to model support
- A
fast_modeselector for models that expose fast mode - An
effort_levelselector that keeps the public ACP config ID aseffort_level
Compatibility note: the effort_level support depends on Ben Brandt's upstream PR #464, "Support effort levels". If that PR is not present upstream, keep this forked implementation (or an equivalent patch) for the effort selector to work as documented.
Zed ◄──ACP──► ClaudeAcpAgent ◄──Claude Agent SDK──► Claude API
│
├── FileEditInterceptor (PostToolUse hook)
│ ├── Edit: revert + route through ACP → Review UI
│ └── Write: revert + route through ACP → Review UI
│
└── PostToolUse onFileRead (caches content for revert)
- Claude calls the built-in Edit or Write tool — it executes normally, writing to disk
- The PostToolUse hook fires and calls the
FileEditInterceptor - The interceptor reverts the file to its pre-edit state on disk
- The interceptor routes the new content through
writeTextFile→ Zed's Review Changes UI - The user accepts or rejects the change inline
This works for both main sessions and subagents — since Claude uses its built-in tools directly, there are no MCP tool access issues.
In v0.18.0 (PR #316), the upstream repo removed an earlier MCP server that provided this functionality because it had critical bugs:
- Subagent failures — MCP tools couldn't be accessed by subagents (Task tool), causing silent write failures
- Stale reads —
mcp__acp__Readreturned outdated buffer content - Binary file crashes — Image and binary files broke the ACP text routing
- Permission bypass — Custom permissions engine conflicted with Claude Code's
.claude/settings.json
This fork fixes all of those by using a PostToolUse intercept instead of an MCP server:
| Decision | Rationale |
|---|---|
| PostToolUse intercept, not MCP | Built-in tools work everywhere (main session + subagents). No MCP tool access issues. |
| Write/Edit only (no Read, no Bash) | Read works fine built-in. Only write operations need ACP routing for the Review UI. |
| Read-before-edit cache | Files are cached when Read completes. Cache is used for reverting to the pre-edit state. Consecutive edits work without re-reading. |
| No system prompt or PreToolUse hook | Claude uses its built-in tools naturally. No tool redirection needed. |
| No custom permissions | Relies on Claude Code's built-in canUseTool and settings files. |
git clone https://github.com/rohanpatra/claude-code-zed-acp.git
cd claude-code-zed-acp
npm install
npm run buildAdd to your Zed settings (~/.config/zed/settings.json):
{
"agent_servers": {
"Claude Code by Rohan Patra": {
"type": "custom",
"command": "node",
"args": ["/absolute/path/to/claude-code-zed-acp/dist/index.js"]
}
}
}Restart Zed. The custom agent will appear in the Agent Panel under the + menu.
Everything from the upstream adapter, plus:
The main feature. When Claude edits or creates a file, the change appears in Zed's Review Changes multibuffer with inline accept/reject controls — instead of being written directly to disk.
- Edit review — File edits appear in the diff viewer with accept/reject controls
- Write review — New file creation also flows through the diff viewer
- Read-before-edit cache — Files are cached when Claude reads them, so the interceptor can revert to the pre-edit state before routing through ACP. Cache is updated after each edit for consecutive edits without re-reading.
- Subagent compatibility — Works for both the main session and subagents (Task tool). The previous MCP-based approach failed silently for subagents.
- No tool redirection — Claude uses its built-in Edit/Write tools naturally. The PostToolUse hook intercepts after execution — no system prompt or PreToolUse hook needed.
- Project-scoped — Only files within the project directory are intercepted. Files outside the project (e.g.,
~/.claude/settings.json) are written directly by the built-in tools. - Safe fallback — If ACP routing fails, the new content is restored to disk so the edit isn't lost. Uncached files (never explicitly Read) skip the revert step.
- Model-aware config options — Tracks model capabilities so the UI only shows options supported by the selected model.
- Fast mode toggle — Adds a
fast_modesession config option when the current model supports it. - Effort level toggle — Adds an
effort_levelsession config option and preserves that public config ID in the ACP surface. - Upstream dependency note — The
effort_levelbehavior depends on Ben Brandt's upstream PR #464.
Everything else works unchanged:
- Context @-mentions and images
- Tool calls with permission requests
- Interactive and background terminals
- TODO lists and plan mode
- Custom slash commands
- Client MCP servers
npm run build # TypeScript compilation
npm run test:run # Unit tests
npm run dev # Build + start
npm run test:integration # Integration tests (requires RUN_INTEGRATION_TESTS=true)This fork is designed for easy merges. All changes are additive:
| File | Change | Merge notes |
|---|---|---|
src/acp-agent.ts |
FileEditInterceptor creation + wiring in createSession(), forwarding in toAcpNotifications/streamEventToAcpNotifications |
All changes are purely additive insertion blocks |
src/tools.ts |
fs import, extractReadContent, isToolError, FileEditInterceptor interface + createFileEditInterceptor factory appended at EOF, onFileRead option added to createPostToolUseHook |
Additions at end of file; shouldn't conflict |
src/lib.ts |
2 export lines (createFileEditInterceptor, FileEditInterceptor type) |
Re-add if upstream changes exports |
package.json |
No changes | — |
See CLAUDE.md for detailed merge instructions and architecture documentation.
Apache-2.0 (same as upstream)