Skip to content

fix(pty): detect npm Claude Code through node wrapper - #62

Merged
simota merged 2 commits into
mainfrom
fix/npm-claude-code-detection
Sep 4, 2026
Merged

fix(pty): detect npm Claude Code through node wrapper#62
simota merged 2 commits into
mainfrom
fix/npm-claude-code-detection

Conversation

@simota

@simota simota commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Summary

Claude Code installed via npm (npm i -g @anthropic-ai/claude-code) runs under a node wrapper, so the tty's foreground process name was node and classify_agent returned Generic: no BEL→attention promotion, no Dock attention, sidebar badge "node", and the auto-approve fire gate (classify_agent(process) != signature.agent()) rejected every candidate.

  • Canonicalize node/bun/npx/bunx wrappers to claude the same way they are already canonicalized to codex.
  • Handle the common launch path: npm i -g puts a bin/claude symlink in front of a #!/usr/bin/env node script, and execve passes the unresolved symlink path, so argv is ["node", "/opt/homebrew/bin/claude"] with no package name in it. A basename heuristic (which codex already had) covers this.
  • Fold the per-agent predicates into a WRAPPED_AGENTS table resolved in two passes: an explicit npm package reference wins for any agent, then the executable-basename heuristic runs over the leading positional arguments only. This stops a Claude Code launch with --add-dir ~/codex from being branded Codex, and keeps flag values like --plugin claude-code from branding unrelated scripts.
  • Update the classify_agent doc comment and docs/specs/auto-approve-mode.md, which still described wrapper launches as an accepted Generic limitation.

Native-installer Claude Code (…/claude/versions/2.1.260) was already handled via is_bare_version and is unaffected.

Test plan

  • cargo test -p noa-pty (unsandboxed, 41 passed ×3): new cases for the symlink argv, npx claude, npx @anthropic-ai/claude-code@latest, bun x @anthropic-ai/claude-code, direct cli.js, near misses (claude-code-sdk, claudette, --plugin claude-code), non-wrapper names, and cross-agent ordering for both claude and codex
  • cargo test -p noa-app classify_agent auto_approve
  • cargo clippy -p noa-pty -p noa-app --all-targets: no new warnings
  • Manual: launch npm-installed claude in a noa pane and confirm the sidebar badge shows Claude Code and BEL promotes to attention

Follow-up (out of scope): gemini / @google/gemini-cli is known to classify_agent but not yet in WRAPPED_AGENTS; one table row.

Canonicalize the npm package argv so agent-specific attention and auto-approve gates remain active.
`npm i -g` puts a `bin/claude` symlink in front of a `#!/usr/bin/env node`
script, and execve hands the interpreter the unresolved symlink path, so
the wrapper's argv is `["node", "/opt/homebrew/bin/claude"]` — no package
name in it. The previous commit only matched `@anthropic-ai/claude-code`,
so the most common install still reported `node` and classified Generic.

Fold the per-agent predicates into a `WRAPPED_AGENTS` table and resolve
in two passes: an explicit npm package reference wins outright for any
agent, then the executable-basename heuristic runs over the leading
positional arguments only. That gives claude the basename fallback codex
already had, stops a Claude Code launch with `--add-dir ~/codex` from
being branded Codex, and keeps flag values like `--plugin claude-code`
from branding unrelated scripts.

Tests cover the symlink argv, npx/bunx by package and by bin name, near
misses, and the cross-agent ordering cases. Update the `classify_agent`
doc and the auto-approve spec, which still described wrapper launches as
an accepted Generic limitation.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-04T22:47:22.743414Z 8a849a9 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@simota
simota merged commit 196f2e4 into main Sep 4, 2026
1 check passed
@simota
simota deleted the fix/npm-claude-code-detection branch September 4, 2026 22:47

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8a849a9c28

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/noa-pty/src/pty.rs
Comment on lines +544 to +548
.iter()
.find_map(|arg| {
WRAPPED_AGENTS
.iter()
.find(|agent| arg_mentions_package(arg, agent.package))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restrict package matches to the launched command

This first pass treats an exact package reference anywhere in the wrapper's argv as proof that the wrapper is running that agent. For example, an unrelated node audit-package.js @anthropic-ai/claude-code is canonicalized to claude, causing incorrect branding and BEL escalation and, in an auto-approve-enabled tab, satisfying the agent gate for any matching prompt text. Inspect only the wrapper's actual script/package command position rather than arbitrary operands or option values.

Useful? React with 👍 / 👎.

@simota simota mentioned this pull request Sep 4, 2026
3 tasks
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.

1 participant