Repository navigation
Description
Diff view attaches to the active workspace instead of the agent's workspace
Summary
When a Claude Code agent edits files, the auto-opened diff tab is created in whatever workspace is currently focused, not the workspace where the agent actually runs. If you start Claude in Workspace A and switch to Workspace B, an Edit/Write from A's agent pops a diff tab into B — interrupting whatever you're doing there.
Steps to reproduce
- Open Workspace A, run
claudein a pane, and give it a task that edits files. - Switch to Workspace B and start working there.
- Wait for the agent in A to perform an
EditorWrite. - Observed: a diff tab appears in Workspace B's bottom pane.
- Expected: the diff tab appears in Workspace A (where the agent and its files live).
Root cause
The hook event already carries the originating pane's surfaceId — wmux-hook.ts reads WMUX_SURFACE_ID (set by wmux per pane) and attaches it to the event payload:
// src/cli/wmux-hook.ts:60
if (surfaceId) params.surfaceId = surfaceId;The main process broadcasts HOOK_EVENT to all windows (src/main/index.ts:741-744), which is fine. The bug is in the renderer's handler, which ignores event.surfaceId and uses the active workspace instead:
// src/renderer/App.tsx:442-473
if (!event?.tool) return;
const state = useStore.getState();
const wsId = state.activeWorkspaceId; // ← wrong: focused workspace, not the agent's
if (!wsId) return;
...
// Auto-open diff tab in the BOTTOM pane when Claude edits/writes files
if (event.tool === 'Edit' || event.tool === 'Write') {
const ws = state.workspaces.find(w => w.id === wsId);
if (ws) {
const bottomPaneId = findBottomPane(ws.splitTree);
...
state.addSurface(wsId, bottomPaneId, 'diff');
}
}Because wsId is activeWorkspaceId, the diff tab is added to whichever workspace is currently focused.
The codebase already has the correct helper to resolve the owning workspace from a surface — workspaceForSurface(surfaceId) (src/renderer/App.tsx:72) — and it's used for other surface-scoped events (e.g. the notify handler at line 99 and the metadata handler at line 425). The hook/diff handler simply doesn't use it.
Suggested fix
Resolve the workspace from event.surfaceId, falling back to the active workspace only when no surface is provided:
const state = useStore.getState();
const ws = workspaceForSurface(event.surfaceId)
?? state.workspaces.find(w => w.id === state.activeWorkspaceId);
if (!ws) return;
const wsId = ws.id;Then use this wsId/ws for both the diff-tab creation and the sidebar activity tracking below.
Related secondary bug
The same wsId = state.activeWorkspaceId is used for sidebar hook-activity tracking (App.tsx:448-458, lastTool/toolCount). This is misattributed the same way: an agent's tool activity is recorded against the focused workspace rather than the agent's own workspace, so the sidebar "active tool" indicator lights up on the wrong workspace. The fix above resolves both symptoms.
Affected files
src/renderer/App.tsx(HOOK_EVENT handler, ~line 433-476) — primary fix- Helper already available:
workspaceForSurface()atsrc/renderer/App.tsx:72
Activity
amirlehmam commentedon Jun 28, 2026
Fixed in v0.13.0 (commit 7432593).
Your diagnosis was spot-on. The
HOOK_EVENThandler insrc/renderer/App.tsxnow resolves the owning workspace from the event'ssurfaceIdvia the existingworkspaceForSurface()helper, falling back to the active workspace only when the event carries nosurfaceId(legacy hooks):This
wsIdnow drives both the diff-tab creation and the sidebar hook-activity tracking, so the secondary misattribution you flagged (lastTool/toolCountlighting up the wrong workspace) is fixed by the same change. Agent edits in Workspace A no longer pop a diff tab into Workspace B.Release: https://github.com/amirlehmam/wmux/releases/tag/v0.13.0 — thanks for the detailed report. 🙏
feat(amirlehmam#64,amirlehmam#63): keyboard shortcuts + cheat-sheet; …