refactor: migrate CLI off the v1 socket protocol#74
Merged
Conversation
Rewires the last v1 socket call sites in the CLI (window/surface commands, notifications, sidebar-metadata family, Claude/Codex hook helpers) onto v2 JSON-RPC, and adds the handful of v2 methods that were still missing for full parity. CLI flags, output text, and exit codes are unchanged for users — only the wire protocol underneath changed. - sendV1Command / forwardSidebarMetadataCommand are deleted; every dispatch case now calls client.sendV2(method:params:) and reconstructs the old plain-text output from the v2 JSON result client-side. - Added workspace.set_agent_pid, workspace.report_meta_block, workspace.clear_meta_block, workspace.list_meta_blocks, and workspace.reset_sidebar to TerminalController.swift (v1 handlers untouched). report_meta/clear_meta/list_meta needed no new method — they're v1 aliases of set_status/clear_status/list_status. read_screen needed no new method — surface.read_text already covers it. - notification.clear gained an optional workspace_id so clear-notifications (and the Claude/Codex hook cleanup paths) can still scope to one workspace instead of clearing everyone's notifications. Part of the v1-deletion sequence (see docs/v2-api-migration.md); v1 handlers in TerminalController.swift are untouched and still serve tests/ and shell integration, which migrate in a follow-up PR.
5 tasks
arzafran
added a commit
that referenced
this pull request
Jul 8, 2026
v2 JSON-RPC is now the only socket protocol. All consumers were migrated first (CLI in #74, shell integration in #72, tests in #71/#73; the remote daemon was already v2-only), so this deletes the v1 line dispatch itself and everything that only existed to serve it. - TerminalController.processCommand now dispatches JSON unconditionally; a non-JSON line gets a terse v1_removed error instead of being routed to the old space-delimited command switch. - Deletes the v1 switch (~90 cases) and every handler function that becomes unreferenced, plus their v1-only parsing helpers (parseOptions/parseOptionsNoStop, resolveTabForReport, withReportTargetSurface, upsertSidebarMetadata/clearSidebarMetadata/ listSidebarMetadata, schedulePanelMetadataMutation, parseReadScreenArgs). Debug handlers that v2's debug.* methods reuse as their implementation core (setShortcut, simulateShortcut, activateApp, isTerminalFocused, readTerminalText, renderStats, layoutDebug, bonsplit/empty-panel/flash counters, focusFromNotification, panelSnapshot(Reset), captureScreenshot) are kept, since they're still live v2 entry points, not v1 relics. Self.socketFastPathState and tailTerminalLines/ readTerminalTextBase64(terminalPanel:) stay too - v2 surface-telemetry and screen-read methods depend on them directly. - auth was already a connection-level preamble (authResponseIfNeeded, handled before any protocol dispatch) supporting both a raw auth-plus-password line and v2 auth.login; only the CLI's raw-line call needed migrating, which this does (auth.login now). - Removes the now-unreachable isV2:false focus-intent allowlist (focusIntentV1Commands) and updates the one unit test that exercised it directly to cover the v2 equivalent instead. - Docs: v2-api-migration.md collapses to a short removal note plus the v1->v2 name mapping (kept for reference); socket-focus-steal-audit.todo.md and agent-browser-port-spec.md get historical annotations; CLAUDE.md's socket-threading-policy examples are reworded to v2 method names. TerminalController.swift: 12834 -> 9615 lines (-3219). Net repo diff: +156/-3410 across 7 files. Breaking change: any external script or tool that still speaks the old space-delimited socket protocol directly (rather than through the CLI) will now get a v1_removed JSON error instead of a response. Use the CLI or the v2 JSON-RPC protocol described in docs/v2-api-migration.md.
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.
What this does
The CLI (
programacommand) was still talking v1 (a plain-text line protocol) for about 20 commands, while the rest of it already speaks v2 (JSON-RPC). This finishes that migration: every remaining CLI dispatch case, plus the internal Claude/Codex hook helpers, now goes through v2. Nothing changes for users — same flags, same printed output, same exit codes — only the wire protocol underneath. This is step 2 of the v1-deletion sequence (v1 handlers themselves are untouched and still servetests/and shell integration until they migrate too).Summary
sendV1Command/forwardSidebarMetadataCommandinCLI/programa.swift. Every call site now builds aclient.sendV2(method:params:)request and reconstructs the old plain-text output from the v2 JSON result, so CLI output stays byte-identical.Sources/TerminalController.swift(additive only — v1 handlers untouched):workspace.set_agent_pidworkspace.report_meta_block/workspace.clear_meta_block/workspace.list_meta_blocksworkspace.reset_sidebarnotification.cleargained an optionalworkspace_idparam (previously global-only) soclear-notifications --workspace Xand the Claude/Codex hook cleanup paths can scope to one workspace instead of wiping every workspace's notifications.report_meta/clear_meta/list_metaneeded no new v2 method — their v1 handlers are themselves aliases ofset_status/clear_status/list_status.read_screenneeded no new method —surface.read_text(added in an earlier PR) already covers its scrollback/lines semantics.docs/v2-api-migration.md's parity checklist and status log.CLI command → v2 method
pingsystem.pinglist-windowswindow.listcurrent-windowwindow.currentnew-windowwindow.createfocus-windowwindow.focusclose-windowwindow.closedrag-surface-to-splitsurface.drag_to_splitrefresh-surfacessurface.refreshreload-configapp.reload_confignotifynotification.create_for_targetlist-notificationsnotification.listclear-notificationsnotification.clearset-app-focusapp.focus_override.setsimulate-app-activeapp.simulate_activeset-statusworkspace.set_statusclear-statusworkspace.clear_statuslist-statusworkspace.list_statusset-progressworkspace.set_progressclear-progressworkspace.clear_progresslogworkspace.logclear-logworkspace.clear_loglist-logworkspace.list_logsidebar-stateworkspace.sidebar_stateclaude-hook/codex-hookinternals (status/pid/notify helpers)workspace.set_status/clear_status,workspace.set_agent_pid/clear_agent_pid,notification.create_for_target,notification.clearNew v2 methods added
workspace.set_agent_pidworkspace.report_meta_blockworkspace.clear_meta_blockworkspace.list_meta_blocksworkspace.reset_sidebarnotification.clearextended with an optionalworkspace_id, not new but changed)Couldn't / didn't migrate
client.send(command: "auth ...")(password auth) is untouched — it wasn't part of the inventoried verb list and touching auth felt out of scope for a "same behavior, different wire protocol" PR.TerminalController.swiftare intentionally untouched (per the task's off-limits list) —tests/andResources/shell-integration/still call v1 directly and migrate in a follow-up PR, at which point v1 removal becomes safe.Test Plan
xcodebuild -scheme programa -configuration Debug build→ BUILD SUCCEEDEDxcodebuild -scheme programa-cli -configuration Debug build→ BUILD SUCCEEDEDxcodebuild -scheme programa-unit -configuration Debug build-for-testing→ TEST BUILD SUCCEEDEDtests_v2/suites exercise the CLI's v2-backed commands end-to-end)