Attribute CLI telemetry to Claude Code and Codex command trees - #480
Merged
Conversation
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.
Problem
Telemetry cannot tell a
neonrun started by a coding agent from one a person typed. Agents drive the CLI through a shell they own, so the process the agent launches is often a wrapper and the CLI turns up several levels down the tree. Checking the immediate caller answers the wrong question.What decides attribution
getCliAgent(env)inpackages/cli/src/env.tsreads the environment a launched command tree inherits, so it identifies aneonprocess anywhere under a Claude Code or Codex launch rather than only a direct child.CLAUDE_CODE_CHILD_SESSION=1CODEX_CI=1and a non-emptyCODEX_THREAD_IDorCODEX_SESSION_IDCodex ids on their own mark a command the user typed in the Codex shell, so those runs stay unattributed.
CLAUDECODE,CLAUDE_CODE,CLAUDE_CLI,CODEX,CODEX_SANDBOXandCODEX_SANDBOX_NETWORK_DISABLEDare ambient or sandbox utility markers and never attribute on their own. When a Claude session and a Codex session both look active, the markers are nested and the property is omitted.The property
agentrides onCLI Started,cli_command_successandCLI Error.Claude Code:
{ "command": "branches list", "ci": false, "agent": "claude-code" }Codex:
{ "command": "branches list", "ci": false, "agent": "codex" }Unattributed:
{ "command": "branches list", "ci": false }Three outcomes:
claude-code,codex, or the property absent. Absent covers the human case and the conflicting-marker case.How the CLI is invoked and what it prints are unchanged, and
neon initbehaves the same. No changeset: nothing a package consumer can call or see moved.Also in here
src/init/agent_snapshot.test.tsandsrc/init/auth.test.tsspawn the real built CLI. Both setNEON_NO_ANALYTICS=1, which is read nowhere in the repo, so those runs were live. Both now pass--no-analytics, the flag the CLI honors.src/analytics.test.tsclearsCODEX_CI,CODEX_THREAD_IDandCODEX_SESSION_IDbefore asserting the Claude Code case, and unstubs env after each test. Run the suite inside a Codex session and the inherited markers would otherwise make it a conflict and omit the property.Verification
pnpm --filter neon test- 4470 passed, 6 skipped; 168 files passed, 3 skippedpnpm lint:ci- cleanCODEX_CI=1 CODEX_THREAD_ID=review-repro pnpm --filter neon exec vitest run src/analytics.test.ts- 17 passed, which is the isolation the plain run cannot catchCases covered: Claude child session; Codex thread id; Codex session id; Codex ids with no
CODEX_CI;CLAUDE_CODE_CHILD_SESSION=falsewith whitespace-only ids; the ambient and sandbox marker set; a Claude-inside-Codex conflict;agentpresent on the error event context.Not verified: no event was sent to a live endpoint. Assertions sit at the property builders rather than at the wire.
For your attention
agentyet. Events carry it from the next release and it stays invisible in reporting until ingestion is updated.