Skip to content

feat(cli): add PostHog telemetry to all CLI commands#44

Merged
k-taro56 merged 4 commits intomainfrom
eng-472
Apr 28, 2026
Merged

feat(cli): add PostHog telemetry to all CLI commands#44
k-taro56 merged 4 commits intomainfrom
eng-472

Conversation

@soleil-colza
Copy link
Copy Markdown
Contributor

Summary

  • Adds PostHog tracking to every CLI command (init, login, logout, whoami, build, start, dev) via a shared withTelemetry() wrapper, emitting cli_command_started, cli_command_completed, and cli_command_failed events.
  • Distinct ID is resolved from ~/.arkor/credentials.json (Auth0 sub or anonymousId), with a UUID fallback at ~/.arkor/telemetry-id when not signed in.
  • Hard opt-out: DO_NOT_TRACK=1 or ARKOR_TELEMETRY_DISABLED=1 short-circuits before the PostHog client is instantiated. The project key is injected at build time via tsdown's define, so local dev builds (no ARKOR_POSTHOG_KEY) ship with telemetry effectively disabled.

Event schema

Event Properties
cli_command_started command, sdk_version, node_version, platform, auth_mode
cli_command_completed above + duration_ms
cli_command_failed above + duration_ms, error_name, error_message (trimmed to 200 chars)

Test plan

  • pnpm --filter arkor typecheck
  • pnpm --filter arkor build (clean build with no ARKOR_POSTHOG_KEY produces a bundle that contains no key literal)
  • pnpm --filter arkor build with ARKOR_POSTHOG_KEY=phc_fake_key_for_test injects the key once
  • pnpm --filter arkor test (16 new telemetry tests, 106 total pass)
  • DO_NOT_TRACK=1 dist/bin.mjs whoami runs cleanly with no PostHog activity even under ARKOR_TELEMETRY_DEBUG=1
  • Wire ARKOR_POSTHOG_KEY into the release workflow before the next published build
  • After release, confirm a real arkor whoami invocation produces cli_command_started + cli_command_completed in the PostHog project, and that an intentionally failing command produces cli_command_failed

Wraps every command (init/login/logout/whoami/build/start/dev) with a
shared telemetry helper that emits cli_command_started, _completed, and
_failed events. Distinct ID is derived from credentials.json (Auth0 sub
or anonymousId), falling back to a locally generated UUID at
~/.arkor/telemetry-id when not signed in.

Opt-out is honored unconditionally via DO_NOT_TRACK=1 or
ARKOR_TELEMETRY_DISABLED=1: when set, the PostHog client is not
instantiated and no network request is made. The PostHog project key is
inlined at build time via tsdown's define, so local dev builds without
ARKOR_POSTHOG_KEY ship with telemetry effectively disabled.
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 28, 2026

Greptile Summary

Adds PostHog telemetry to all CLI commands via a withTelemetry() wrapper that emits cli_command_started and either cli_command_completed or cli_command_failed. Identity is resolved from credentials or a fallback UUID file, with hard opt-out via DO_NOT_TRACK / ARKOR_TELEMETRY_DISABLED and the PostHog key baked in at build time so local dev builds ship with telemetry effectively disabled. The implementation is well-guarded (errors swallowed at every capture site, flushAt: 1 for immediate sends, clean shutdown in main()'s finally block) and is backed by 16 new tests.

Confidence Score: 5/5

Safe to merge; all remaining findings are P2 style/documentation issues that do not affect correctness.

The telemetry implementation is solid: opt-out flags work correctly, errors are safely swallowed, the PostHog client is cleanly shut down, and test coverage is thorough. The only open findings are a minor README wording inaccuracy and a theoretical (low-probability) event-loss window for dev on Ctrl+C — neither blocks merge.

No files require special attention for merge.

Important Files Changed

Filename Overview
packages/arkor/src/core/telemetry.ts New telemetry module: well-structured, all env-flag checks use the consistent envFlag() helper, errors are swallowed safely, PostHog client is lazy-initialised and cleanly shut down. No blocking issues found.
packages/arkor/src/cli/main.ts All commands wrapped with withTelemetry; shutdownTelemetry() called in finally block. Works for all commands except dev which exits via process.exit(0) in its signal handler, bypassing the finally block.
packages/arkor/src/core/telemetry.test.ts 16 new tests with good coverage: opt-out flags, identity resolution branches (auth0/anon/none), success/failure events, longRunning flag, error trimming, and PostHog error isolation. Environment variables are properly saved and restored.
packages/arkor/tsdown.config.ts Adds build-time injection of ARKOR_POSTHOG_KEY and ARKOR_POSTHOG_HOST via define; defaults to empty string / official PostHog endpoint, correctly disabling telemetry in local dev builds without the key.
packages/arkor/README.md New Telemetry section is clear and includes opt-out instructions; minor inaccuracy: claims "three events are emitted per invocation" when only two fire per run (started + completed/failed).
packages/arkor/package.json Adds posthog-node@^5.30.6 as a dependency (engine constraint issue was flagged in a previous review thread).

Sequence Diagram

sequenceDiagram
    participant CLI as CLI (main.ts)
    participant WT as withTelemetry wrapper
    participant GI as getIdentity()
    participant PH as PostHog client
    participant CMD as Command handler

    CLI->>WT: call wrapped action
    WT->>WT: isEnabled()? (checks env flags + POSTHOG_KEY)
    alt telemetry disabled
        WT->>CMD: handler(...args) directly
    else telemetry enabled
        WT->>GI: getIdentity()
        GI-->>WT: { distinctId, authMode }
        WT->>PH: capture cli_command_started
        WT->>CMD: await handler(...args)
        alt success + not longRunning
            WT->>PH: capture cli_command_completed
        else longRunning (dev)
            Note over WT,PH: cli_command_completed skipped
        else handler throws
            WT->>PH: capture cli_command_failed
            WT-->>CLI: rethrow error
        end
    end
    CLI->>PH: shutdownTelemetry() [in finally block]
Loading

Fix All in Claude Code

Reviews (3): Last reviewed commit: "feat(telemetry): enhance withTelemetry t..." | Re-trigger Greptile

Comment thread packages/arkor/package.json
Comment thread packages/arkor/src/core/telemetry.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

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: d89b33234c

ℹ️ 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".

"esbuild": "^0.28.0",
"hono": "^4.7.0",
"open": "^10.0.0",
"posthog-node": "^5.30.6",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Use a PostHog SDK version compatible with supported Node versions

Adding posthog-node@^5.30.6 introduces an engine floor (^20.20.0 || >=22.22.0 in the lockfile) that is higher than this package’s declared support ("node": ">=22.6"), so users on Node 22.6–22.21 are now in an unsupported/install-failing state (hard failure with engine-strict, and undefined runtime support otherwise). Please either bump the package engine requirement to >=22.22 or pin a PostHog version that supports the advertised Node range.

Useful? React with 👍 / 👎.

Comment on lines +176 to +180
await handler(...args);
if (identity) {
safeCapture(identity.distinctId, "cli_command_completed", {
...baseProps,
duration_ms: Date.now() - start,
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 Delay cli_command_completed until long-running commands actually stop

This emits cli_command_completed immediately after the command handler resolves, which misreports long-lived commands like arkor dev: runDev() starts the server and returns, so telemetry records a very short duration_ms and a completed state while the process is still serving (and before late failures can surface). This skews command-duration analytics and completion/failure rates for long-running sessions.

Useful? React with 👍 / 👎.

soleil-colza and others added 2 commits April 28, 2026 23:10
…loor

posthog-node 5.22.0 tightened its engines field to
"^20.20.0 || >=22.22.0", which excludes Node 22.6 to 22.21.x even
though arkor itself targets >=22.6. Pin to the last 5.21.x release so
the dependency's supported Node range fully covers arkor's.
@soleil-colza soleil-colza requested a review from k-taro56 April 28, 2026 14:18
Added an option to the withTelemetry function to handle long-running commands, which skips the cli_command_completed event on success while still emitting cli_command_started. Updated related tests to verify this behavior.
Copy link
Copy Markdown
Contributor

@k-taro56 k-taro56 left a comment

Choose a reason for hiding this comment

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

エンジニアを褒めるネコ_LGTM

@k-taro56 k-taro56 merged commit ddeb327 into main Apr 28, 2026
6 checks passed
@k-taro56 k-taro56 deleted the eng-472 branch April 28, 2026 14:20
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

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: 82ca1705d0

ℹ️ 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".

// under vitest, where this transform doesn't run.
define: {
__SDK_VERSION__: JSON.stringify(pkg.version),
__ARKOR_POSTHOG_KEY__: JSON.stringify(process.env.ARKOR_POSTHOG_KEY ?? ""),
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 Pass ARKOR_POSTHOG_KEY into release builds

__ARKOR_POSTHOG_KEY__ is compiled to "" whenever ARKOR_POSTHOG_KEY is unset at build time, and isEnabled() hard-disables telemetry when that value is empty, so the published CLI will never emit telemetry unless the release build injects this env var. I checked .github/workflows/release.yaml and its Build step (pnpm run build) does not set ARKOR_POSTHOG_KEY, so this commit’s telemetry feature is effectively off in production packages.

Useful? React with 👍 / 👎.

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.

2 participants