Skip to content

Update built-in Pi hook integration - #7008

Merged
austinywang merged 19 commits into
mainfrom
issue-5555-update-built-in-pi-hook-integration-for-curre
Jun 29, 2026
Merged

austinywang merged 19 commits into
mainfrom
issue-5555-update-built-in-pi-hook-integration-for-curre

Conversation

@austinywang

@austinywang austinywang commented Jun 27, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #5555

Summary

  • update the generated Pi extension for @earendil-works/pi-coding-agent and current lifecycle/tool events
  • add explicit resume binding get/set/verify/clear, turn ids, Feed telemetry, notification routing, and structured hook failure warnings
  • add a behavioral regression test for the installed generated extension and update docs/localized CLI output

Validation

  • python3 scripts/normalize-pbxproj.py && scripts/check-pbxproj.sh
  • python3 scripts/check-workspace-package-groups.py --check
  • python3 scripts/check-package-resolved-policy.py
  • python3 scripts/swift_file_length_budget.py --budget .github/swift-file-length-budget.tsv
  • python3 -m json.tool Resources/Localizable.xcstrings >/dev/null
  • python3 -m py_compile tests/test_pi_extension_install.py
  • ./scripts/lint-pbxproj-test-wiring.sh
  • extracted generated Pi extension imported and ran fake-cmux event harness with bun

No local dev build was run per task instructions.


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Updates the built-in Pi hook to the current @earendil-works/pi-coding-agent for better reliability, telemetry, and safety. Adds non-blocking tool telemetry, routed notifications with fallback, localized CLI output, and a disable flag; completes #5555.

  • New Features

    • Generates v2 ~/.pi/agent/extensions/cmux-session.ts with session lifecycle, per-turn IDs, and a non-blocking Feed bridge for tool_execution_start / tool_execution_end.
    • Adds resume binding get/set/verify/clear scoped to the current surface/workspace, sanitizes argv, stores launch argv/cwd, and clears the binding on shutdown.
    • Routes completions via hooks pi notification, guards against duplicates, and preserves native fallback on failures.
    • Hardens env filtering (explicit allowlists; blocks secrets; only passes the socket when needed) and emits structured warnings on hook failures.
    • Honors CMUX_PI_HOOKS_DISABLED to fully disable the integration.
  • Refactors

    • Moves the Pi hook generator into CLI/CMUXCLI+PiExtension*.swift, removes the old inline v1 from cmux.swift, and localizes new CLI strings; updates docs.
    • Tightens stop-notification dedupe, stabilizes the CLI socket harness (shorter /tmp paths, timeouts), and expands tests for Feed payloads, turn-id reuse, resume binding flows, env sanitization, argv normalization, notification routing/fallback, the disable flag, and install safety checks.

Written for commit 303f8c6. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added Pi hook installation/removal via a generated per-agent CLI extension, including resume checkpoint binding and tool activity telemetry (tool_execution_start / tool_execution_end).
    • Added interactive install/uninstall flow with install previews, --yes/-y bypass, and refusal to modify unexpected non-Pi content.
  • Bug Fixes
    • Improved stop-notification deduplication by detecting already-routed stop payloads in additional input locations.
  • Documentation
    • Updated agent-hooks and feed docs to reflect Pi’s generated telemetry bridge and troubleshooting changes.
  • Tests
    • Expanded Pi extension install tests with stricter end-to-end lifecycle, payload, and safety checks.

@vercel

vercel Bot commented Jun 27, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jun 29, 2026 8:23pm
cmux-staging Building Building Preview, Comment Jun 29, 2026 8:23pm

@coderabbitai

coderabbitai Bot commented Jun 27, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a managed Pi extension installer and uninstaller, splits the embedded Pi hook source into new Swift files, updates stop-notification deduping, refreshes Pi docs and localization strings, and expands Pi integration test coverage.

Changes

Pi hook extension parity

Layer / File(s) Summary
Installer, uninstall, and wiring
CLI/CMUXCLI+PiExtension.swift, CLI/cmux.swift, CLI/CMUXCLI+PiExtensionSource.swift, Resources/Localizable.xcstrings, cmux.xcodeproj/project.pbxproj
The new Swift helpers install or remove the managed extension, the old embedded implementation is removed, Pi hook strings are added, and the new source is wired into the cmux-cli target.
Pi source helpers
CLI/CMUXCLI+PiExtensionSourcePart1.swift
The embedded Pi extension source adds environment filtering, launch-argument normalization, session state tracking, payload parsing, turn lifecycle helpers, structured warnings, and cmux command execution helpers.
Pi hook handlers
CLI/CMUXCLI+PiExtensionSourcePart2.swift, docs/agent-hooks.md, docs/feed.md
The embedded Pi extension source adds hook dispatch, resume binding management, tool feed forwarding, and the exported Pi session extension handler registration; the docs describe the updated Pi feed bridge behavior.
Stop notification dedupe
CLI/cmux.swift
Stop-notification publishing now treats cmux_notification_routed as set when it appears in either input.rawObject or input.object.
Integration test coverage
tests/test_pi_extension_install.py
The Pi extension install test now uses fake pi and cmux binaries, parses hook logs, exercises tool and shutdown handlers, verifies resume binding and env sanitization, and checks notification and argv handling.

Estimated review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 I hopped through hooks with ears held high,
And watched new Pi-turns bounce by.
Feed bells rang soft, resume logs gleamed,
cmux kept secrets well-beseemed.
Now docs and tests join in the play,
And carrot-stars light up the way.


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (2 errors, 2 warnings)

Check name Status Explanation Resolution
Cmux User-Facing Error Privacy ❌ Error Pi install preview dumps raw generated source with vendor/env var names, and one warning emits session_id in console/UI output. Sanitize user-visible previews/warnings: omit package/env names from install output and remove session_id from warning payloads.
Cmux Full Internationalization ❌ Error The new Swift UI strings are localized, but the PR also changes user-facing markdown docs (docs/agent-hooks.md, docs/feed.md) without locale-specific copies for the 20 supported locales. Translate the changed docs into locale-specific sources or exclude them from user-facing surfaces, and add matching entries for every locale in web/i18n/routing.ts.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The PR has a solid summary and validation list, but it misses required template sections like Demo Video, Review Trigger, and the checklist. Add the missing template sections, include any required demo link, and complete the checklist with local testing and review-trigger confirmation.
✅ Passed checks (21 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main Pi hook integration update.
Linked Issues check ✅ Passed The changes address the linked issue: current Pi import, shutdown cleanup, resume binding handling, turn IDs, Feed telemetry, notification routing, and tests/docs.
Out of Scope Changes check ✅ Passed The additional docs, localization, tests, and project wiring all support the Pi integration work and do not appear unrelated.
Cmux Swift Actor Isolation ✅ Passed PASS: The Swift diff adds plain CLI helpers/string constants and a Bool dedupe guard; no new MainActor, Sendable, or UI-store isolation debt appears.
Cmux Swift Blocking Runtime ✅ Passed New Pi Swift files only add file I/O/readLine prompts; no semaphores, sleeps, asyncAfter, main-queue sync, polling, or locks were introduced.
Cmux Browser Automation Off-Main ✅ Passed The PR only changes Pi-hook install/docs/tests; no browser.*, WebKit/AppKit, or socket-worker routing code is touched.
Cmux Expensive Synchronous Load ✅ Passed The touched Swift files only add Pi installer/source code; no new agent-history/session-store loads, @MainActor paths, or other expensive sync loaders were introduced.
Cmux Cache Substitution Correctness ✅ Passed PASS: the PR keeps fresh on-disk/session-store reads (loadUnlocked/resume get) and only adds transient in-memory turn state; no persistence/snapshot path now trusts a stale cache.
Cmux No Hacky Sleeps ✅ Passed PASS: The only polling/sleep is test-only wait_for_text; the runtime JS uses a bounded command timeout, not a coordination delay.
Cmux Algorithmic Complexity ✅ Passed No new nested scans or per-target rescans on scalable user data; added loops are linear over env/argv/messages or tiny fixed option sets.
Cmux Swift Concurrency ✅ Passed PASS: the new Swift additions are synchronous FileManager/print helpers; no new DispatchQueue/Combine/Task APIs appear in touched Swift code.
Cmux Swift @Concurrent ✅ Passed No changed Swift function is async or actor-isolated; the new Pi installer methods are synchronous CLI file ops, so no @concurrent annotation issue was introduced.
Cmux Swift File And Package Boundaries ✅ Passed PASS: The new Swift files are 114/3/293/287 lines; the only logic file is focused CLI glue, and the large extension files are generated-source constants, which the rule allows.
Cmux Swiftpm Lockfiles ✅ Passed The PR adds Swift sources to the Xcode project but no SwiftPM package references or dependency pins, and no .gitignore ignores Package.resolved.
Cmux Swift Logging ✅ Passed Only new prints are user-facing CLI install/uninstall messages; no new Logger/NSLog/debugPrint/dump or secret-bearing diagnostics were added.
Cmux Swiftui State Layout ✅ Passed The PR only changes CLI/docs/tests; the added Swift files are non-SwiftUI and contain no state/layout patterns from the rule.
Cmux Architecture Rethink ✅ Passed PASS: The PR adds one dedicated Pi installer/uninstaller owner and a required extension bridge; no sleep/poll/observer or duplicate-wiring patterns were introduced in touched Swift files.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed Touched Swift files only add CLI Pi-extension generation/source; no NSWindow/NSPanel/NSWindowController/WindowGroup code or cmuxAuxiliaryWindowIdentifiers changes were introduced.
Cmux Source Artifacts ✅ Passed Changed paths are intentional source, docs, tests, config, and localization files; no temp/log/cache/DerivedData or other stray artifact paths appear.
Cmux No Test Or Debug Seam In Production Source ✅ Passed No changed Swift file is under a production Sources/ path; the new CLI Swift files also contain no debug/test-seam markers.
Cmux No Ambient Global State ✅ Passed The new Swift code only adds extension methods and static constants on CMUXCLI; no new top-level free funcs, mutable globals, or singleton state were introduced.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-5555-update-built-in-pi-hook-integration-for-curre

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…lt-in-pi-hook-integration-for-curre

# Conflicts:
#	.github/swift-file-length-budget.tsv
@austinywang

Copy link
Copy Markdown
Contributor Author

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Rate Limit Exceeded

@austinywang have exceeded the limit for the number of chat messages per hour. Please wait 7 minutes and 1 seconds before sending another message.

@cubic-dev-ai

cubic-dev-ai Bot commented Jun 27, 2026

Copy link
Copy Markdown

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@austinywang I can't start this review because your workspace has reached its free monthly review limit. cubic has reviewed 241,260 of the 240,000 allowed lines of code this month. Reviews resume on 1 July 2026 (in 4 days). Paid plans include much higher monthly review limits. Upgrade now to resume reviews.

To help optimise your usage, you can tune cubic to get the most out of your usage limits:

Learn more →

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@greptile-apps

greptile-apps Bot commented Jun 27, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR upgrades the built-in Pi hook integration from the old @mariozechner/pi-coding-agent v1 extension to the current @earendil-works/pi-coding-agent v2 API, extracting the generated TypeScript source from cmux.swift into dedicated split files and adding substantial new behaviour.

  • Adds per-turn ID tracking, non-blocking Feed telemetry for tool_execution_start/tool_execution_end, verified resume binding set/get/clear scoped to the current surface/workspace, a CMUX_PI_HOOKS_DISABLED escape hatch, completion notification routing via hooks pi notification with native-notification fallback, structured hook-failure warnings via ui.notify, and a proper env allowlist in hookEnvironment.
  • Refactors the Swift install/uninstall logic into CMUXCLI+PiExtension.swift with full i18n (20 locales) for every new CLI string; expands the Python regression harness to cover Feed payloads, turn-ID reuse, resume-binding round-trip, env sanitization, notification-routing/fallback, the disable flag, and ungraceful-shutdown paths; and updates agent-hooks and feed docs to reflect Pi's new Feed telemetry.

Confidence Score: 4/5

Mergeable after the lifecycle concerns flagged in earlier threads are confirmed addressed; the new env allowlist and error-message cleanups look correct in the current diff.

The env filter is now a genuine allowlist (ends with return false), the warning messages no longer expose internal cmux terminology, and the file-read error wrapping is clean. The Pi extension generator's session-state cleanup (only deleting from the sessionStates Map when clearResumeBinding succeeds) and the two-step notification-then-stop design in agent_end that sets suppression before confirming delivery are real correctness concerns that prior review threads flagged and that remain in the current code; those threads should be resolved before merging.

CLI/CMUXCLI+PiExtensionSourcePart1.swift and CLI/CMUXCLI+PiExtensionSourcePart2.swift contain the generated TypeScript that drives Pi session state, resume bindings, and notification routing — the areas where prior threads flagged the most significant concerns.

Important Files Changed

Filename Overview
CLI/CMUXCLI+PiExtension.swift New Swift file for Pi install/uninstall; uses String(localized:) for all output and wraps file-read errors in a localized CLIError without leaking Foundation error internals. The file-write and directory-creation paths propagate raw Foundation errors on failure, which is consistent with the rest of the CLI but slightly inconsistent with the read path's explicit wrapping.
CLI/CMUXCLI+PiExtensionSourcePart1.swift Generated TypeScript source part 1 (session state management, env allowlist, argv normalisation, runCmux helper). The env filter now correctly returns false as its catch-all, making it a proper allowlist. The looksLikePiScript/normalizedLaunchArgv heuristics on the correctness-critical resume-argv path are the primary concern flagged in prior review threads.
CLI/CMUXCLI+PiExtensionSourcePart2.swift Generated TypeScript source part 2 (sendHook, resume binding set/verify/clear, sendFeed, event handlers). The agent_end two-step notification-then-stop design and the sessionStates cleanup-on-clear-failure paths are the concerns flagged in prior review threads and remain in the current code.
CLI/cmux.swift Removes the inline v1 Pi extension (215 lines) and adds stopNotificationAlreadyRouted detection that checks both input.rawObject and input.object. The dedup guard correctly fires only when a prior notification hook has successfully set the flag.
Resources/Localizable.xcstrings Adds 9 new CLI string keys for the Pi install/uninstall flow, each translated into all 20 supported locales (ar, bs, da, de, en, es, fr, it, ja, km, ko, nb, pl, pt-BR, ru, th, tr, uk, zh-Hans, zh-Hant). All locales use [y/N] in the confirmProceed string, consistent with the hardcoded y-prefix check in Swift.
tests/test_pi_extension_install.py Expanded regression harness covering Feed payloads, turn-ID reuse, resume binding round-trip (set→verify→clear for each session), env sanitization, notification routing/fallback, disable flag, and ungraceful shutdown. Uses wait_for_text with 50 ms polling (test-only, acceptable). Hardcoded line-count thresholds for wait_for_text are fragile to future event additions.
cmuxTests/CLINotifyProcessTestSupport.swift Fixes pipe-read deadlock risk by draining stdout/stderr on background queues before waiting for process exit; shortens socket paths to avoid macOS 104-char AF_UNIX limit; adds CI-aware timeout inflation. All changes are test-scaffolding and structurally sound.
cmuxTests/CLIGenericHookPersistenceTests.swift Switches to startDetachedMockServer with connectionCount:128 to handle parallel sendFeed spawns; updates Codex-hook assertions to search command file bodies in addition to command strings; corrects the OMP resume command assertion to match the format the production code actually produces (brace-group removal).
cmuxTests/VMSSHCommandTests.swift Adds surface.list and workspace.close mock handlers so the SSH command test no longer fails on unexpected methods; updates expected RPC sequence accordingly.
cmux.xcodeproj/project.pbxproj Adds four new Swift source files to the Xcode project and updates the swift-file-length-budget. Functionally correct.
.github/swift-file-length-budget.tsv Correctly reduces the CLI/cmux.swift budget by 211 lines (the removed Pi extension source) and the test file budget by 1 line.
docs/agent-hooks.md Updates Pi row to reflect tool execution telemetry; corrects the troubleshooting paragraph to mention the generated extension bridge. Accurate.
docs/feed.md Updates Pi's Feed column from 'lifecycle only' to the new tool-execution telemetry description; consistent with agent-hooks.md.
CLI/CMUXCLI+PiExtensionSource.swift Three-line join file that concatenates the two source parts; straightforward.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Pi as Pi Agent
    participant Ext as cmux-session.ts (Generated Extension)
    participant Cmux as cmux CLI
    participant SW as cmux.swift (Stop Notification)

    Pi->>Ext: session_start
    Ext->>Cmux: hooks pi session-start (sync)
    Ext->>Cmux: surface resume set --checkpoint-id sessionId
    Ext->>Cmux: surface resume get (verify)

    Pi->>Ext: before_agent_start
    Ext->>Cmux: hooks pi prompt-submit + turn_id (sync)

    Pi->>Ext: tool_execution_start
    Ext->>Cmux: hooks feed PreToolUse (detached, non-blocking)

    Pi->>Ext: tool_execution_end
    Ext->>Cmux: hooks feed PostToolUse (detached, non-blocking)

    Pi->>Ext: agent_end
    Ext->>Cmux: hooks pi notification (sync)
    alt "notificationRouted = true"
        Ext->>Cmux: "hooks pi stop + cmux_notification_routed=true"
        Cmux->>SW: "stopNotificationAlreadyRouted = true"
        Note over SW: Native macOS notification suppressed
    else "notificationRouted = false"
        Ext->>Cmux: hooks pi stop (no flag)
        Note over SW: Native macOS notification fires as fallback
    end

    Pi->>Ext: session_shutdown
    alt "state.stopped = false (ungraceful exit)"
        Ext->>Cmux: hooks pi stop + terminationReason (no notification flag)
        Note over SW: Native macOS notification fires
    end
    Ext->>Cmux: surface resume clear --checkpoint-id sessionId
    Note over Ext: sessionStates.delete only if clear succeeds
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Pi as Pi Agent
    participant Ext as cmux-session.ts (Generated Extension)
    participant Cmux as cmux CLI
    participant SW as cmux.swift (Stop Notification)

    Pi->>Ext: session_start
    Ext->>Cmux: hooks pi session-start (sync)
    Ext->>Cmux: surface resume set --checkpoint-id sessionId
    Ext->>Cmux: surface resume get (verify)

    Pi->>Ext: before_agent_start
    Ext->>Cmux: hooks pi prompt-submit + turn_id (sync)

    Pi->>Ext: tool_execution_start
    Ext->>Cmux: hooks feed PreToolUse (detached, non-blocking)

    Pi->>Ext: tool_execution_end
    Ext->>Cmux: hooks feed PostToolUse (detached, non-blocking)

    Pi->>Ext: agent_end
    Ext->>Cmux: hooks pi notification (sync)
    alt "notificationRouted = true"
        Ext->>Cmux: "hooks pi stop + cmux_notification_routed=true"
        Cmux->>SW: "stopNotificationAlreadyRouted = true"
        Note over SW: Native macOS notification suppressed
    else "notificationRouted = false"
        Ext->>Cmux: hooks pi stop (no flag)
        Note over SW: Native macOS notification fires as fallback
    end

    Pi->>Ext: session_shutdown
    alt "state.stopped = false (ungraceful exit)"
        Ext->>Cmux: hooks pi stop + terminationReason (no notification flag)
        Note over SW: Native macOS notification fires
    end
    Ext->>Cmux: surface resume clear --checkpoint-id sessionId
    Note over Ext: sessionStates.delete only if clear succeeds
Loading

Reviews (15): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

Comment thread CLI/CMUXCLI+PiExtension.swift Outdated
Comment thread CLI/CMUXCLI+PiExtension.swift Outdated
Comment thread CLI/CMUXCLI+PiExtension.swift Outdated
Comment thread CLI/CMUXCLI+PiExtension.swift Outdated
@greptile-apps

greptile-apps Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Upgrades the built-in Pi hook integration from the legacy @mariozechner/pi-coding-agent API to the current @earendil-works/pi-coding-agent API, extracts the generated TypeScript extension into its own CMUXCLI+PiExtension.swift file, and substantially expands what the extension does. All new user-facing CLI strings are fully translated across the 20 supported locales.

  • The generated cmux-session.ts extension gains explicit resume binding management (get/set/verify/clear), turn-ID threading, async Feed telemetry via detached spawn, and notification routing through hooks pi notification.
  • A cmux_notification_routed flag in the stop-hook payload lets the Swift side skip its built-in stop notification when the extension has already dispatched one, preventing duplicates.
  • Environment filtering is overhauled from "pass everything minus AMP_API_KEY" to an allowlist that explicitly blocks keys matching TOKEN|SECRET|PASSWORD|API_KEY etc., verified by a new env-leakage assertion in the regression test.

Confidence Score: 4/5

The change is self-contained; the generated TypeScript is behaviorally verified by the expanded regression test, and the deduplication flag in cmux.swift is narrowly scoped. The main rough edge is a raw Foundation error description surfacing in CLI output on the file-read failure path.

The env sanitization, resume binding flow, Feed telemetry, and notification deduplication all work correctly and are covered by the regression test. One concrete defect: existingPiExtensionContents appends String(describing: error) to the user-facing CLIError, injecting NSCocoaErrorDomain/NSPOSIXErrorDomain domain names and numeric codes into CLI output whenever the extension file can't be read.

CLI/CMUXCLI+PiExtension.swift — specifically the existingPiExtensionContents error-throw on line 617 and the warn()/ui.notify() message strings inside the embedded TypeScript literal.

Important Files Changed

Filename Overview
CLI/CMUXCLI+PiExtension.swift New 700-line file extracting Pi extension generator from cmux.swift. Two issues: raw Foundation error description leaks internal NSCocoaErrorDomain details into user-visible CLI output; warn()'s ui.notify() exposes internal "resume binding"/"hook command" terminology in the Pi UI.
CLI/cmux.swift Removes the legacy v1 Pi extension generator and adds the cmux_notification_routed deduplication guard to the stop-notification path.
Resources/Localizable.xcstrings Adds 8 new string keys for the Pi install/uninstall flow, each fully translated across all 20 supported locales.
tests/test_pi_extension_install.py Substantially expanded regression test covering resume binding, Feed payloads, notification routing, env sanitization, and turn-ID threading.
cmux.xcodeproj/project.pbxproj Adds CMUXCLI+PiExtension.swift to both the file reference list and the Sources build phase.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Pi as Pi Agent (Node/Bun)
    participant Ext as cmux-session.ts extension
    participant cmuxCLI as cmux CLI (hook subprocess)
    participant cmuxApp as cmux App (Swift)

    Pi->>Ext: session_start
    Ext->>cmuxCLI: hooks pi session-start (spawnSync)
    cmuxCLI->>cmuxApp: SessionStart event
    Ext->>cmuxCLI: surface resume get (spawnSync)
    cmuxCLI-->>Ext: "{resume_binding: null}"
    Ext->>cmuxCLI: surface resume set --kind pi (spawnSync)
    cmuxCLI-->>Ext: "{ok: true}"
    Ext->>cmuxCLI: surface resume get (verify, spawnSync)

    Pi->>Ext: before_agent_start
    Ext->>cmuxCLI: hooks pi prompt-submit + turn_id (spawnSync)
    cmuxCLI->>cmuxApp: UserPromptSubmit

    Pi->>Ext: tool_execution_start
    Ext->>cmuxCLI: hooks feed --event PreToolUse (spawn, detached)

    Pi->>Ext: tool_execution_end
    Ext->>cmuxCLI: hooks feed --event PostToolUse (spawn, detached)

    Pi->>Ext: agent_end
    Ext->>cmuxCLI: hooks pi stop + cmux_notification_routed:true (spawnSync)
    Note over cmuxApp: cmux_notification_routed=true → skip built-in notification
    Ext->>cmuxCLI: hooks pi notification (spawnSync)
    cmuxCLI->>cmuxApp: show completion notification

    Pi->>Ext: session_shutdown
    Note over Ext: state.stopped==true → skip duplicate stop hook
    Ext->>cmuxCLI: surface resume clear (spawnSync)
    cmuxCLI->>cmuxApp: clear resume binding
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Pi as Pi Agent (Node/Bun)
    participant Ext as cmux-session.ts extension
    participant cmuxCLI as cmux CLI (hook subprocess)
    participant cmuxApp as cmux App (Swift)

    Pi->>Ext: session_start
    Ext->>cmuxCLI: hooks pi session-start (spawnSync)
    cmuxCLI->>cmuxApp: SessionStart event
    Ext->>cmuxCLI: surface resume get (spawnSync)
    cmuxCLI-->>Ext: "{resume_binding: null}"
    Ext->>cmuxCLI: surface resume set --kind pi (spawnSync)
    cmuxCLI-->>Ext: "{ok: true}"
    Ext->>cmuxCLI: surface resume get (verify, spawnSync)

    Pi->>Ext: before_agent_start
    Ext->>cmuxCLI: hooks pi prompt-submit + turn_id (spawnSync)
    cmuxCLI->>cmuxApp: UserPromptSubmit

    Pi->>Ext: tool_execution_start
    Ext->>cmuxCLI: hooks feed --event PreToolUse (spawn, detached)

    Pi->>Ext: tool_execution_end
    Ext->>cmuxCLI: hooks feed --event PostToolUse (spawn, detached)

    Pi->>Ext: agent_end
    Ext->>cmuxCLI: hooks pi stop + cmux_notification_routed:true (spawnSync)
    Note over cmuxApp: cmux_notification_routed=true → skip built-in notification
    Ext->>cmuxCLI: hooks pi notification (spawnSync)
    cmuxCLI->>cmuxApp: show completion notification

    Pi->>Ext: session_shutdown
    Note over Ext: state.stopped==true → skip duplicate stop hook
    Ext->>cmuxCLI: surface resume clear (spawnSync)
    cmuxCLI->>cmuxApp: clear resume binding
Loading

Reviews (2): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

Comment thread CLI/CMUXCLI+PiExtension.swift
Comment thread CLI/CMUXCLI+PiExtension.swift Outdated
@greptile-apps

greptile-apps Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR refactors the built-in Pi hook integration by extracting the generated TypeScript extension into its own Swift file (CLI/CMUXCLI+PiExtension.swift), upgrading it from the legacy @mariozechner/pi-coding-agent API to @earendil-works/pi-coding-agent, and adding resume binding management, turn IDs, Feed telemetry (tool_execution_start/tool_execution_end), notification routing with deduplication, and a regex-based env sanitizer for hook subprocesses.

  • Moves the Pi extension generator and Swift install/uninstall methods out of cmux.swift into a dedicated 700-line extension file; the cmux_notification_routed flag is wired into the app-side stop-notification path to prevent duplicate alerts.
  • Adds explicit resume binding get/set/verify/clear lifecycle, turn IDs threaded through prompt-submit/stop/tool events, and non-blocking spawn+unref Feed telemetry for tool calls.
  • All new CLI output strings are fully localized across 20 locales in Localizable.xcstrings; the regression test now covers resume binding flow, env sanitization, Feed payloads, and notification routing.

Confidence Score: 3/5

The env sanitizer and Feed turn-ID wiring in the new Pi extension file have correctness gaps that need resolution before this ships to users.

The env-filter fallthrough is a real, demonstrable gap: any env var whose name doesn't match the deny-list regex (e.g. GH_PAT, CLOUDFLARE_AUTH_KEY) leaks to every hook subprocess. The turn-ID lookup via generic ["id", "request_id"] fields is a logic hazard that will silently corrupt Feed correlation if Pi's tool events carry those fields. Both issues are in the newly introduced TypeScript extension that runs in users' live Pi sessions. The localization, notification deduplication, and Xcode wiring changes look solid.

CLI/CMUXCLI+PiExtension.swift — specifically the shouldPreserveEnvKey fallthrough, the eventTurnId field list used by currentTurnId, and the normalizedLaunchArgv runtime-detection branch.

Security Review

  • Env-filter deny-list gap (CLI/CMUXCLI+PiExtension.swift — shouldPreserveEnvKey): The function ends with return !secretLikeEnvKey(key), making it a regex deny-list rather than an allowlist. Secret env vars with non-standard names — e.g. GH_PAT, CLOUDFLARE_AUTH_KEY, STRIPE_SK — pass through to hook subprocesses because their names don't match TOKEN|SECRET|PASSWORD|API_KEY|ACCESS_KEY|PRIVATE_KEY|CREDENTIAL|AUTHORIZATION|COOKIE. The regression test only probes the explicitly listed patterns.
  • CMUX_SOCKET_PASSWORD is deliberately allowed through safeCmuxEnvKey; intentional for socket authentication but means at least one PASSWORD-containing key always reaches hook subprocesses by design.

Important Files Changed

Filename Overview
CLI/CMUXCLI+PiExtension.swift New 700-line file housing the generated Pi extension (TypeScript embedded in a Swift raw string literal) and the Swift install/uninstall methods. Contains env-filter fallthrough that leaks non-pattern-matched secrets, a generic id-field lookup that can corrupt turn IDs in Feed, and a heuristic-only launch-argv normalizer that silently drops script paths for non-standard Pi installations.
CLI/cmux.swift Removes the old inline Pi extension (~220 lines) and adds the cmux_notification_routed deduplication guard to the stop-notification path; the guard logic looks correct.
Resources/Localizable.xcstrings Adds 7 new CLI string keys for Pi hook install/uninstall messages with full translations across all supported locales (ar, bs, da, de, en, es, fr, it, ja, km, ko, nb, pl, pt-BR, ru, th, tr, uk, zh-Hans, zh-Hant).
tests/test_pi_extension_install.py Expands regression harness to cover resume binding flow, Feed telemetry events, notification routing, env sanitization, and turn-ID consistency. Uses time.sleep polling via wait_for_text for the detached Feed spawn — acceptable as test-only scaffolding.
cmux.xcodeproj/project.pbxproj Adds CMUXCLI+PiExtension.swift to the Xcode project under PBXBuildFile and PBXFileReference sections; wiring looks correct.
docs/agent-hooks.md Updates Pi's telemetry column from 'none' to 'tool_execution_start / tool_execution_end telemetry' and clarifies the Feed troubleshooting note.
docs/feed.md Updates Pi row in the Feed integration table to reflect tool-execution telemetry instead of 'lifecycle only'.
.github/swift-file-length-budget.tsv Reduces CLI/cmux.swift budget by ~210 lines (matching the removed Pi extension block) and adds CLI/CMUXCLI+PiExtension.swift at 700 lines.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Pi as Pi Agent
    participant Ext as cmux-session.ts (Extension)
    participant cmux as cmux CLI

    Pi->>Ext: session_start
    Ext->>cmux: hooks pi session-start
    Ext->>cmux: surface resume get
    cmux-->>Ext: "{resume_binding}"
    Ext->>cmux: surface resume set (if stale)
    cmux-->>Ext: "{ok}"
    Ext->>cmux: surface resume get (verify)

    Pi->>Ext: before_agent_start
    Ext->>cmux: hooks pi prompt-submit (turn_id)

    Pi->>Ext: tool_execution_start
    Ext->>cmux: hooks feed --source pi --event PreToolUse (async)

    Pi->>Ext: tool_execution_end
    Ext->>cmux: hooks feed --source pi --event PostToolUse (async)

    Pi->>Ext: agent_end
    Ext->>cmux: "hooks pi stop (cmux_notification_routed=true)"
    Ext->>cmux: hooks pi notification

    Pi->>Ext: session_shutdown
    alt not already stopped
        Ext->>cmux: hooks pi stop
    end
    Ext->>cmux: surface resume clear
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Pi as Pi Agent
    participant Ext as cmux-session.ts (Extension)
    participant cmux as cmux CLI

    Pi->>Ext: session_start
    Ext->>cmux: hooks pi session-start
    Ext->>cmux: surface resume get
    cmux-->>Ext: "{resume_binding}"
    Ext->>cmux: surface resume set (if stale)
    cmux-->>Ext: "{ok}"
    Ext->>cmux: surface resume get (verify)

    Pi->>Ext: before_agent_start
    Ext->>cmux: hooks pi prompt-submit (turn_id)

    Pi->>Ext: tool_execution_start
    Ext->>cmux: hooks feed --source pi --event PreToolUse (async)

    Pi->>Ext: tool_execution_end
    Ext->>cmux: hooks feed --source pi --event PostToolUse (async)

    Pi->>Ext: agent_end
    Ext->>cmux: "hooks pi stop (cmux_notification_routed=true)"
    Ext->>cmux: hooks pi notification

    Pi->>Ext: session_shutdown
    alt not already stopped
        Ext->>cmux: hooks pi stop
    end
    Ext->>cmux: surface resume clear
Loading

Reviews (3): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

Comment thread CLI/CMUXCLI+PiExtension.swift Outdated
Comment thread CLI/CMUXCLI+PiExtension.swift Outdated
Comment thread CLI/CMUXCLI+PiExtension.swift Outdated
Comment thread CLI/CMUXCLI+PiExtension.swift
Comment thread CLI/CMUXCLI+PiExtension.swift Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLI/CMUXCLI`+PiExtension.swift:
- Around line 345-350: The resume binding check in resumeBindingMatches() is too
permissive because it only compares kind and checkpoint_id, which allows
session_start to reuse a stale persisted Pi binding even when the command
context has changed. Update the session_start flow that decides whether to call
surface resume set so it also compares the stored command context fields (such
as cwd and sanitized argv) against the current session, or always rewrite the
resume_binding when a session starts. Keep resumeBindingMatches() and the
surrounding resume-state update logic as the key places to adjust so the
persisted binding is refreshed whenever the launch context differs.
- Around line 600-610: The read failure handling in CMUXCLI+PiExtension’s
file-loading path drops the underlying error, so update the catch block to
preserve diagnostics when throwing CLIError. In the String(contentsOf:encoding:)
error path, keep the existing localized “Failed to read %@” message but append
String(describing: error) to the wrapped CLIError rather than using
error.localizedDescription. Make this change in the same helper/method that
reads the URL so permission, encoding, and missing-file failures retain their
original details.

In `@docs/feed.md`:
- Line 87: The Feed docs prose is inconsistent with the updated Pi row: the
later paragraph still describes Pi as only providing lifecycle/session-restore
hooks. Update that paragraph to match the new Pi Feed support and reference the
same Pi extension behavior shown in the table so the documentation stays
consistent throughout.

In `@tests/test_pi_extension_install.py`:
- Around line 253-266: The resume verification in this test is too loose because
it only checks that `surface resume get/set/clear` appear somewhere in the logs.
Tighten the assertions around the `session_start` path by validating the exact
read-after-write sequence in the resume flow, or by asserting the exact number
of `surface resume get` calls so the post-`set` verification read is required.
Use the existing `wait_for_text` checks and the hook log expectations in
`test_pi_extension_install.py` to pin the ordered `get -> set -> get -> clear`
behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0c9298ec-ce3b-4dc4-81bc-edf85e41046d

📥 Commits

Reviewing files that changed from the base of the PR and between 58830db and d3b1d7f.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (7)
  • CLI/CMUXCLI+PiExtension.swift
  • CLI/cmux.swift
  • Resources/Localizable.xcstrings
  • cmux.xcodeproj/project.pbxproj
  • docs/agent-hooks.md
  • docs/feed.md
  • tests/test_pi_extension_install.py

Comment thread CLI/CMUXCLI+PiExtension.swift Outdated
Comment thread CLI/CMUXCLI+PiExtension.swift
Comment thread docs/feed.md
Comment thread tests/test_pi_extension_install.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLI/CMUXCLI`+PiExtensionSourcePart2.swift:
- Around line 136-143: The pre-write `runCmux(["--json", "surface", "resume",
"get", ...target], cwd)` call in `CMUXCLI+PiExtensionSourcePart2` is redundant
because its `stdout` is never used and the subsequent `set` plus post-write
verification already handle success/failure. Remove this initial `get`/warning
block from the `session_start` path, and keep the existing post-write check
after the `set` so failures are still surfaced via `runCmux` and `warn`.
- Around line 132-134: The resume-binding paths ignore the
CMUX_PI_HOOKS_DISABLED kill switch, so both ensureResumeBinding and
clearResumeBinding should short-circuit the same way sendHook and sendFeed do.
Add the environment check near the start of ensureResumeBinding and
clearResumeBinding so session_start and session_shutdown stop spawning cmux
surface resume subprocesses and stop mutating surface bindings when the flag is
set.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d5794112-bf9a-41ab-abcd-b20475d72818

📥 Commits

Reviewing files that changed from the base of the PR and between 075626c and de059cf.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (5)
  • CLI/CMUXCLI+PiExtension.swift
  • CLI/CMUXCLI+PiExtensionSource.swift
  • CLI/CMUXCLI+PiExtensionSourcePart1.swift
  • CLI/CMUXCLI+PiExtensionSourcePart2.swift
  • cmux.xcodeproj/project.pbxproj
💤 Files with no reviewable changes (1)
  • CLI/CMUXCLI+PiExtension.swift

Comment thread CLI/CMUXCLI+PiExtensionSourcePart2.swift
Comment thread CLI/CMUXCLI+PiExtensionSourcePart2.swift Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/test_pi_extension_install.py (1)

141-143: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the fake resume binding reflect the requested checkpoint.

The test now exercises both pi-session-test and pi-session-interrupted, but the fake surface resume set always persists checkpoint_id: "pi-session-test". That means the interrupted session’s read-after-write verification is testing a fake mismatch, and regressions that pass the wrong --checkpoint-id for non-primary sessions can slip through. Parse the --checkpoint-id argument from $@ and write that value into fake-surface-binding.json.

As per path instructions, correctness-critical session/resume identity should come from explicit IDs, not a fallback or constant.

Proposed test harness tightening
   *"surface resume set"*)
-    printf '{"resume_binding":{"kind":"pi","checkpoint_id":"pi-session-test","source":"agent-hook","command":"pi --session pi-session-test"}}\n' > "$CMUX_TEST_PI_BINDING_FILE"
+    checkpoint_id=""
+    previous=""
+    for token in "$@"; do
+      if [ "$previous" = "--checkpoint-id" ]; then
+        checkpoint_id="$token"
+        break
+      fi
+      previous="$token"
+    done
+    printf '{"resume_binding":{"kind":"pi","checkpoint_id":"%s","source":"agent-hook","command":"pi --session %s"}}\n' "$checkpoint_id" "$checkpoint_id" > "$CMUX_TEST_PI_BINDING_FILE"
     printf '{"ok":true}\n'
     ;;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_pi_extension_install.py` around lines 141 - 143, The fake surface
resume binding in the test harness is hardcoded to a single checkpoint ID, which
can hide incorrect checkpoint handling for non-primary sessions. Update the
`surface resume set` case in the test setup to read the `--checkpoint-id` value
from the command arguments (`$@`) and persist that exact value into
`fake-surface-binding.json`, so the binding produced by the `surface resume set`
path matches the requested session in the test.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@tests/test_pi_extension_install.py`:
- Around line 141-143: The fake surface resume binding in the test harness is
hardcoded to a single checkpoint ID, which can hide incorrect checkpoint
handling for non-primary sessions. Update the `surface resume set` case in the
test setup to read the `--checkpoint-id` value from the command arguments (`$@`)
and persist that exact value into `fake-surface-binding.json`, so the binding
produced by the `surface resume set` path matches the requested session in the
test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e200f358-78a6-446e-975d-44d4e73a846c

📥 Commits

Reviewing files that changed from the base of the PR and between de059cf and 509ddec.

📒 Files selected for processing (2)
  • CLI/CMUXCLI+PiExtensionSourcePart2.swift
  • tests/test_pi_extension_install.py

cmux added 2 commits June 28, 2026 20:20
…lt-in-pi-hook-integration-for-curre

# Conflicts:
#	.github/swift-file-length-budget.tsv
#	Resources/Localizable.xcstrings
…lt-in-pi-hook-integration-for-curre

# Conflicts:
#	.github/swift-file-length-budget.tsv
Comment thread CLI/CMUXCLI+PiExtensionSourcePart2.swift
…lt-in-pi-hook-integration-for-curre

# Conflicts:
#	.github/swift-file-length-budget.tsv
…lt-in-pi-hook-integration-for-curre

# Conflicts:
#	.github/swift-file-length-budget.tsv
@austinywang
austinywang merged commit d268e80 into main Jun 29, 2026
30 checks passed
austinywang added a commit that referenced this pull request Jun 29, 2026
…gents-don

Resolve conflicts from main's #7008 (Pi hook integration rewrite):
- CLI/cmux.swift: take main's side; the Pi extension now lives in
  CMUXCLI+PiExtension*.swift. Branch's OpenCode no-surface gate is preserved.
- CLI/CMUXCLI+PiExtensionSourcePart2.swift: re-port the branch's gate change
  onto main's new Pi extension. sendHook/sendFeed now route when
  CMUX_SOCKET_PATH plus one scoped identity (surface/panel/workspace) is
  present; surface-scoped resume bindings stay gated on CMUX_SURFACE_ID.
- tests/test_pi_extension_install.py: keep main's comprehensive surface-based
  coverage intact and add a self-contained no-surface phase (workspace-only)
  asserting hooks register with a socket, stay silent without one, and skip
  surface-scoped resume bindings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview – cmux — 303f8c6d Deployed Jun 29, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Update built-in Pi hook integration for current Pi APIs and agent parity

1 participant