feat: external agent detection, worktree agents, and macOS fixes#141
Open
noam971 wants to merge 7 commits intopablodelucca:devfrom
Open
feat: external agent detection, worktree agents, and macOS fixes#141noam971 wants to merge 7 commits intopablodelucca:devfrom
noam971 wants to merge 7 commits intopablodelucca:devfrom
Conversation
- Detect Claude sessions started outside VS Code (Ghostty, iTerm2, etc.)
and create headless pixel agents for them
- Walk process tree to distinguish VS Code/Cursor sessions (ignored) from
external terminal sessions (adopted as headless agents)
- Fix agent jumping: use stat.size as initialOffset for scan-detected sessions
- Fix sendCurrentAgentStatuses timing: send after layoutLoaded so characters
exist when status messages arrive
- Fix subagent spawning: pass toolName in agentToolStart message and check
toolName === 'Task' instead of status.startsWith('Subtask:') so tasks with
no description also spawn subagent characters
- Fix terminal agent status refresh: call readNewLines on onDidChangeActiveTerminal
so JSONL events missed while terminal was unfocused are processed immediately
- Reduce permission timer delay from 7s to 3s for faster ... bubble appearance
- Fix worktree path: use .worktrees/ inside repo instead of .pixel-worktrees/ outside
- Add Worktree Agent button to BottomToolbar (git repos only)
- Restore agent statuses correctly after VS Code reload
Co-Authored-By: noam971 <noam971@users.noreply.github.com>
When lsof returns a PID for a JSONL file that belongs to a Claude Code extension session, that PID is the extension host reading the file, not the claude writer. Code Helper (Plugin) has 'plugin' in its own comm, so checking the PID's own comm before walking its parents correctly returns null (ignore) for extension sessions. Co-Authored-By: noam971 <noam971@users.noreply.github.com>
…for all headless Key fixes: - null now only returned for --session-id (+button) agents already tracked - extension (--output-format) and plugin-parent sessions return EXTERNAL_AGENT_FOLDER_NAME instead of null, so they get a headless 'Ext' agent as the user expects - replace lsof -t -- <file> (returns all readers incl. Pixel Agents own watchers) with lsof -p <pid> (per-process, only that process's open files) - fallback heuristic scans bare/extension claudes via process tree - adoptExistingJsonlFiles treats VSCODE_TERMINAL_SESSION as headless at startup Co-Authored-By: noam971 <noam971@users.noreply.github.com>
…e coexist - ps auxww: prevents --output-format from being truncated in long arg lists - fallback heuristic: when both extension (--output-format) and bare claudes are running simultaneously, return EXTERNAL_AGENT_FOLDER_NAME instead of guessing VSCODE_TERMINAL_SESSION — avoids extension JSONL incorrectly adopting a terminal Co-Authored-By: noam971 <noam971@users.noreply.github.com>
- Use ps args= instead of comm= in walkProcessTree so Code Helper (Plugin) isn't truncated to ~16 chars, preventing false vscode_terminal matches - Add elapsed-time age filter in fallback: skip processes far older than the JSONL file (filters out long-lived extension claude processes) - Persist claudePid in PersistedAgent so it survives webview reloads - Make restoreAgents async; use shell-PID ancestry matching instead of terminal name matching so multiple terminals named "claude" each get the correct terminalRef - Skip already-in-map agents on re-entry to prevent duplicate file watchers (webviewReady fires on every panel focus, re-calling restoreAgents) - findOwningTerminal: use ownedShellPids set (ppid of each agent's claudePid) instead of terminalRef equality, which was stale after name-based restore
bf20faf to
24f291f
Compare
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove bun.lock files (duplicate of package-lock.json) and replace hardcoded local paths in launch.json with generic VS Code variables. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds automatic detection of Claude sessions started outside the extension, a worktree agent launcher, and fixes several macOS bugs that caused agents to point to the wrong terminals.
Type of change
New Features
External agent detection — sessions started outside the "+" button now appear automatically:
claudetyped manually): character created and correctly bound to that terminal, even when multiple terminals share the name "claude"Worktree agents — new "⊕ Worktree" button in the bottom toolbar:
agent-YYYY-MM-DD-HHmm)git worktree add .worktrees/<branch> -b <branch>and launches Claude in the worktree dirmacOS Bug Fixes
ps -o comm=truncation: macOS truncatesCode Helper (Plugin)to ~16 chars, causing the extension host to be misclassified as a VS Code terminal. Fixed by usingps -o args=(full binary path).claudeget renamed to "claude" by VS Code.restoreAgentswas matching every agent to the first one found by name. Fixed by persistingclaudePidand using shell-PID ancestry matching (restoreAgents is now async).lsoffalse positives: fixed by adding-aflag so both conditions are ANDed.webviewReadyfires on every panel focus, re-callingrestoreAgents. Agents already in the map are now skipped.Test plan
devbranchnpm run buildpasses locallysrc/constants.tsorwebview-ui/src/constants.ts)