@traice/codex-collector
v0.1.3
Published
Local Codex usage collector for trAIce Internal Spend.
Readme
Internal Spend Codex Collector
This installs a local bridge from Codex developer-agent usage into trAIce Internal Spend.
Internal Spend is intentionally separate from product-runtime LLM attribution:
collector data goes to /api/v1/internal-usage, not /api/v1/events.
What It Collects
- Codex token-count rows from
~/.codex/sessions/**/*.jsonl - Codex OTel
response.completedtoken events from127.0.0.1:4318/v1/logs - local install identity: employee email/name, team name, device principal
- Codex context metadata: repo/cwd, model, thread id, sandbox/approval mode
- optional monthly seat/subscription commitment, e.g.
--seat-monthly-usd 100
Prompts are not sent. Codex OTel is configured with log_user_prompt = false.
For an overview of OTel, the collector data path, and how Codex differs from the planned Claude Code collector, see Coding-agent collectors.
Install On This Device
Published install shape:
printf "trAIce API key: "
stty -echo
IFS= read -r TRAICE_API_KEY
stty echo
printf "\n"
export TRAICE_API_KEY
npx @traice/codex-collector@latest install \
--server-url https://www.runtraice.com \
--employee-email [email protected] \
--employee-name "Your Name" \
--team-name Engineering \
--seat-monthly-usd 100 \
--backfill-hours all \
--patch-codex-config
unset TRAICE_API_KEYPowerShell on Windows:
$secureKey = Read-Host "trAIce API key" -AsSecureString
$plainKey = [Net.NetworkCredential]::new("", $secureKey).Password
$plainKey | npx @traice/codex-collector@latest install --api-key-stdin `
--server-url 'https://www.runtraice.com' `
--employee-email '[email protected]' `
--team-name 'Engineering' `
--seat-monthly-usd 100 `
--backfill-hours all `
--patch-codex-config
Remove-Variable plainKey, secureKeyLocal repo development can still run:
node tools/internal-spend-codex/install.mjs \
--employee-email [email protected] \
--employee-name "Your Name" \
--team-name Engineering \
--seat-monthly-usd 100The installer:
- creates or reuses the
internal-spend-pocworkspace in local dev - enables the workspace
internalSpendEnabledflag - creates a real API key for
/api/v1/internal-usage - stores the API key in macOS Keychain, Windows Credential Manager, or Linux
Secret Service and writes only its reference to
~/.traice/internal-spend-codex/install.json - appends an idempotent trAIce
[otel]block to user-level~/.codex/config.toml
Codex ignores telemetry settings in project .codex/config.toml, so the user
config patch is intentional.
Start The Collector
Foreground:
npx @traice/codex-collector@latest collectLocal repo development can use node tools/internal-spend-codex/collector.mjs.
macOS LaunchAgent:
printf "trAIce API key: "
stty -echo
IFS= read -r TRAICE_API_KEY
stty echo
printf "\n"
export TRAICE_API_KEY
npx @traice/codex-collector@latest install \
--server-url https://www.runtraice.com \
--employee-email [email protected] \
--team-name Engineering \
--seat-monthly-usd 100 \
--backfill-hours all \
--launch-agent
unset TRAICE_API_KEYThe collector listens on:
http://127.0.0.1:4318/v1/logsand forwards normalized internal usage rows to:
http://127.0.0.1:3003/api/v1/internal-usageView the module at:
http://127.0.0.1:3003/dashboard?tab=internalEmployee And Team Mapping
For this local collector, identity comes from install flags:
--employee-email--employee-name--team-name--source-principal--seat-monthly-usd
If omitted, the installer falls back to global git identity and local OS user.
Future org-wide installs should feed the same fields from MDM/SSO/directory
data. CSV and vendor connectors should use the same /api/v1/internal-usage
contract and fill employee/team fields directly or via identity mapping.
The API key can be provided with TRAICE_API_KEY, --api-key-stdin, or
--api-key. Prefer TRAICE_API_KEY or --api-key-stdin for user installs so
keys do not end up in shell history. A later install reuses the saved key, and
collect resolves it from secure storage, so neither command prompts again.
Credential storage defaults to --credential-store auto. It uses the native OS
credential manager when available. On headless systems it falls back explicitly
to ~/.traice/internal-spend-codex/credentials.json with a user-only directory
and file (0700/0600 on POSIX); that fallback is not encrypted at rest. Use
--credential-store keyring to require native secure storage and fail rather
than fall back, or --credential-store file for an externally encrypted or
managed environment. Existing plaintext install.json credentials migrate on
the next install or collect.
For containers, CI, MDM, or an external secret manager, inject
TRAICE_API_KEY only into the collect process. That override is used without
being persisted.
Private config and collector state default to ~/.traice/internal-spend-codex.
Use --out /path/to/private-dir only when an org installer manages that
directory and permissions explicitly.
--seat-monthly-usd records a monthly subscription commitment for the
employee/source pair. It is shown separately from per-request usage cost because
Codex token logs do not include provider invoice amounts.
Current Open Codex Agents
Existing Codex processes usually will not reload new user-level OTel config in
place. To cover already-open agents, the collector tails
~/.codex/sessions/**/*.jsonl and ingests token_count events appended by
running Codex sessions.
New or restarted Codex agents use native OTel export through the installed
[otel] config. Already-open agents are covered by session JSONL token-count
tailing where those files are available.
By default the first session scan imports all available Codex history. To limit
history, pass --backfill-hours N to install or collect; use
--backfill-hours all explicitly for a full import. Collector state is scoped
to the configured trAIce destination and source event IDs dedupe later restarts.
One-Shot Backfill
Run a single session-file scan without opening the OTel listener:
npx @traice/codex-collector@latest collect --once --backfill-hours 6The collector keeps local dedupe state in:
~/.traice/internal-spend-codex/collector-state.jsonso restarting it should not intentionally duplicate historical rows.
Releasing
Do not run npm publish locally. From the platform repository, run:
npm run release:prepareThis opens a version PR. Merging the reviewed PR triggers GitHub Actions and npm
trusted publishing (OIDC), so publishing never requires an npm token or an
interactive npm login. Pass minor, major, or an explicit version after --
when the default patch bump is not appropriate.
