packages/omo-codex/plugin/components/telemetry/README.md
Codex plugin component that emits a single anonymous daily-active event (omo_codex_daily_active) to PostHog whenever a Codex session starts.
The event is sent at most once per UTC day per machine. It uses a SHA256-hashed installation identifier derived from omo-codex:${hostname} and never sends the raw hostname. PostHog person profiles are explicitly disabled.
The component registers a single SessionStart hook:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook session-start",
"timeout": 5
}
]
}
]
}
}
The aggregate plugin/hooks/hooks.json mounts this hook alongside rules and ultrawork so all three fire in parallel at the start of every Codex session.
A single PostHog capture call with:
event: "omo_codex_daily_active"distinctId: sha256("omo-codex:" + hostname)properties:
platform, product_name, package_name, package_versionruntime ("node"), runtime_versionsource: "plugin", reason: "session_start"$os, $os_version, os_arch, os_typecpu_count, cpu_model, total_memory_gblocale, timezone, shell, ci, terminalday_utc (today's UTC date)$process_person_profile: falseThe component never sends prompt contents, file contents, API keys, raw hostnames, or any user-identifying data.
Set any of the following environment variables before launching Codex:
# Codex-only opt-out
export OMO_CODEX_DISABLE_POSTHOG=1
export OMO_CODEX_SEND_ANONYMOUS_TELEMETRY=0
# Global opt-out (covers both omo and omo-codex)
export OMO_DISABLE_POSTHOG=1
export OMO_SEND_ANONYMOUS_TELEMETRY=0
When any of these is set the component creates a no-op PostHog client and exits without any network call.
The component writes a small JSON state file at:
$XDG_DATA_HOME/omo-codex/posthog-activity.json
# or, when XDG_DATA_HOME is unset:
~/.local/share/omo-codex/posthog-activity.json
containing { "lastActiveDayUTC": "YYYY-MM-DD" }. If the stored day matches today (UTC), the hook returns without sending anything. The file is written atomically via rename(2).
Every telemetry path is wrapped in try/catch. The hook always exits 0 with no stdout or stderr output, even when PostHog construction, capture, or shutdown fails. Codex session startup is never blocked or slowed by telemetry failures.
Handled telemetry failures are written only to a local diagnostics file:
$XDG_DATA_HOME/omo-codex/telemetry-diagnostics.jsonl
# or, when XDG_DATA_HOME is unset:
~/.local/share/omo-codex/telemetry-diagnostics.jsonl
The diagnostics file keeps JSONL rows for recent telemetry failures, prunes stale rows during writes, and caps itself at 256 KiB by dropping the oldest complete rows. Diagnostics are never sent to PostHog and do not include prompt contents, transcript contents, raw hostnames, API keys, tokens, or full hook payloads.
| Variable | Default |
|---|---|
POSTHOG_HOST | https://us.i.posthog.com |
POSTHOG_API_KEY | shared omo-codex project key |
npm install
npm test # vitest (in-process + subprocess CLI smoke)
npm run typecheck
npm run build # tsc -> dist/
npm run check # typecheck + biome + build
The component shares its product identity constants with the @oh-my-opencode/omo-codex CLI installer. Drift between the two implementations is guarded by packages/omo-codex/src/telemetry/cross-package-equivalence.test.ts.
See the omo Privacy Policy for the full disclosure.