Skip to content

Document the Claude wrapper / PATH shim and hook injection behavior #2140

Description

@suzuke

Summary

cmux ships a wrapper script at Resources/bin/claude that intercepts claude invocations inside cmux terminals. This wrapper automatically injects 6 hooks via --settings and a generated --session-id before passing through to the real Claude binary. This behavior is currently undocumented.

I understand this is a pragmatic design choice to deliver a zero-config experience — and it works. The seamless out-of-the-box integration is genuinely one of cmux's strengths. The implementation itself is well-designed (environment checks, socket validation, passthrough fallback, opt-out via CMUX_CLAUDE_HOOKS_DISABLED=1). This issue is not about removing the feature, but about disclosing it.

What the wrapper does

When a user runs claude inside a cmux terminal (CMUX_SURFACE_ID is set):

  1. cmux's bin/ directory takes PATH precedence over the real claude binary
  2. The wrapper injects --settings with hooks for: SessionStart, Stop, SessionEnd, Notification, UserPromptSubmit, PreToolUse
  3. A UUID is generated and passed as --session-id
  4. The real claude binary is then exec'd with these additional flags

Outside cmux, the wrapper passes through to the real binary unchanged.

Current documentation gap

  • README: No mention of the wrapper, PATH shim, or automatic hook injection
  • docs/notifications.md: Only documents the manual approach (user configures hooks in settings.json themselves)
  • CONTRIBUTING.md: No mention
  • CHANGELOG: A single bugfix entry references "claude shim" in passing — not a disclosure

The only way to discover this behavior is to read the source code.

Why this matters

Claude Code is an AI agent with broad system permissions (file I/O, code execution, network access). The UserPromptSubmit and PreToolUse hooks observe every prompt and tool invocation within a session. While the current hooks only perform notification/status updates, the interception surface itself warrants explicit disclosure — users should know that a third-party layer sits between their input and the official binary.

PATH shims are an established pattern (nvm, pyenv, rbenv, direnv), but those tools clearly document their shim behavior. Transparency is especially important when the intercepted tool operates with elevated trust.

Suggestions

  • Add a section to the README explaining the Claude wrapper, what it injects, and why
  • Show a first-launch notice or log line when the wrapper activates (e.g., [cmux] Using Claude wrapper with session hooks — disable with CMUX_CLAUDE_HOOKS_DISABLED=1)
  • Have the wrapper append a line like (cmux wrapped) to claude --version or claude --help output, so users can easily tell when they're running through the shim
  • Consider an opt-in prompt on first use

Thanks for building cmux — the UX is genuinely great. Just hoping to see the trust layer match the engineering quality.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions