Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

Codex skill for uploading sanitized local Codex Desktop or CLI usage metadata to an ingest API. It scans local Codex JSONL session logs incrementally, filters private content, sends metadata batches with Bearer authentication, and stores local progress state.

This repository contains two skill paths:

- `skills/codex-usage-uploader`: original uploader.
- `skills/codex-usage-uploader-v2`: V2 uploader with token snapshot de-duplication. Use this when dashboards sum uploaded token fields and must avoid over-counting Codex cumulative `total_token_usage` or re-emitted `token_count` snapshots.

## Install

Install with Codex's built-in skill installer:
Expand All @@ -14,6 +19,15 @@ python C:\Users\<user>\.codex\skills\.system\skill-installer\scripts\install-ski

Restart Codex after installation so the skill is discovered.

Install the V2 skill:

```powershell
python C:\Users\<user>\.codex\skills\.system\skill-installer\scripts\install-skill-from-github.py `
--repo HardToFd/codex-usage-uploader-skill `
--path skills/codex-usage-uploader-v2 `
--branch develop
```

## Configure

The uploader needs three values:
Expand All @@ -30,6 +44,12 @@ Run a dry-run first:
python C:\Users\<user>\.codex\skills\codex-usage-uploader\scripts\codex_usage_uploader.py --dry-run
```

For V2, use the V2 skill directory:

```powershell
python C:\Users\<user>\.codex\skills\codex-usage-uploader-v2\scripts\codex_usage_uploader.py --dry-run
```

Then run the upload:

```powershell
Expand All @@ -53,3 +73,5 @@ The uploader does not send raw user messages, assistant replies, reasoning conte

See [skills/codex-usage-uploader/references/ingest_api.md](skills/codex-usage-uploader/references/ingest_api.md).

For V2 token snapshot de-duplication semantics, see [skills/codex-usage-uploader-v2/references/ingest_api.md](skills/codex-usage-uploader-v2/references/ingest_api.md).

76 changes: 76 additions & 0 deletions skills/codex-usage-uploader-v2/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
name: codex-usage-uploader-v2
description: Upload sanitized Codex Desktop or CLI usage metadata to a configured ingest API using the V2 token snapshot de-duplication contract. Use when Codex needs to configure, run, backfill, troubleshoot, or automate local Codex session JSONL collection while avoiding duplicate token usage from cumulative `total_token_usage` and re-emitted `token_count` events.
---

# Codex Usage Uploader V2

## Overview

Use this skill to collect local Codex session JSONL usage metadata and upload it to a dashboard ingest API. V2 keeps the original privacy boundary and adds a strict token snapshot de-duplication contract so dashboards can safely sum uploaded `token` fields without counting cumulative Codex snapshots twice.

## Quick Start

Run from the skill directory or pass the absolute script path:

```bash
python scripts/codex_usage_uploader.py --endpoint https://collector.example.com/api/codex/usage-v2 --source-name alice --token <bearer-token>
```

Environment variables are supported:

```bash
set CODEX_USAGE_INGEST_URL=https://collector.example.com/api/codex/usage-v2
set CODEX_USAGE_SOURCE_NAME=alice
set CODEX_USAGE_BEARER_TOKEN=<bearer-token>
python scripts/codex_usage_uploader.py
```

Useful options:

```bash
python scripts/codex_usage_uploader.py --dry-run --endpoint https://collector.example.com/api/codex/usage-v2 --source-name alice
python scripts/codex_usage_uploader.py --since 2026-05-01 --endpoint https://collector.example.com/api/codex/usage-v2 --source-name alice --token <bearer-token>
python scripts/codex_usage_uploader.py --codex-home C:\Users\admin\.codex --timezone Asia/Shanghai --batch-size 500 --endpoint https://collector.example.com/api/codex/usage-v2 --source-name alice --token <bearer-token>
```

If `python` is not on PATH, use the bundled Codex runtime if available.

## Automation

When the user asks to keep the dashboard updated, create a Codex cron automation that runs hourly and executes this skill's script with the configured environment variables. The default schedule is hourly in `Asia/Shanghai`.

The automation prompt should be self-contained:

```text
Use $codex-usage-uploader-v2 to run the Codex usage uploader with the configured CODEX_USAGE_INGEST_URL, CODEX_USAGE_SOURCE_NAME, and CODEX_USAGE_BEARER_TOKEN environment variables. Upload new local Codex usage metadata only with V2 token snapshot de-duplication.
```

## Privacy Boundary

Do not upload raw message text, agent replies, reasoning content, shell stdout/stderr, full commands, tool output, or unified diffs. The script uploads counts, IDs, timestamps, status, durations, token fields, rate-limit fields, cwd/model/git context, command program summaries, and patch change-type statistics only.

Accuracy tiers:

- Exact: token fields, session ID, timestamp, event type, line number, rate limits, explicit duration/status fields.
- Context linked: cwd, model, effort, git, and turn context attached from the latest same-session context event.
- External: `source_name` is supplied by configuration. If it represents a person, configure a stable person or account label.

Token counting contract:

- Codex `token_count` log entries can include both `last_token_usage` and `total_token_usage`.
- `total_token_usage` is cumulative within the session and must not be summed across log entries.
- Codex can re-emit `token_count` when rate-limit state changes, sometimes with the same token usage snapshot.
- The uploader sends `token` from `last_token_usage` only for the first observed `total_token_usage` snapshot; repeated snapshots are skipped so dashboards can sum uploaded `token` fields as per-call increments.

## API Reference

Read `references/ingest_api.md` when implementing or validating the server-side ingest API. The server must treat `event_id` as an idempotency key and should return `accepted`, `duplicates`, and `errors` counts.

## Troubleshooting

- Missing endpoint: set `CODEX_USAGE_INGEST_URL` or pass `--endpoint`.
- Missing source: set `CODEX_USAGE_SOURCE_NAME` or pass `--source-name`.
- Missing token: set `CODEX_USAGE_BEARER_TOKEN` or pass `--token`; `--dry-run` does not require a token.
- Duplicate data: expected during file moves or re-scans; de-duplicate by `event_id`. Token usage snapshots are also filtered client-side when Codex re-emits the same cumulative usage with new rate-limit metadata.
- No events found: verify `$CODEX_HOME\sessions` or `$CODEX_HOME\archived_sessions` contains JSONL logs.
4 changes: 4 additions & 0 deletions skills/codex-usage-uploader-v2/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "Codex Usage Uploader V2"
short_description: "Upload Codex usage with token de-duplication."
default_prompt: "Use $codex-usage-uploader-v2 to upload sanitized Codex usage metadata with token snapshot de-duplication."
73 changes: 73 additions & 0 deletions skills/codex-usage-uploader-v2/references/ingest_api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Codex Usage Ingest API V2

## Endpoint

`POST <configured endpoint>`

Required headers:

```http
Authorization: Bearer <token>
Content-Type: application/json
```

## Request Body

```json
{
"source_name": "alice",
"machine_id": "stable-hash",
"codex_home": "C:\\Users\\alice\\.codex",
"collector_version": "2.0.0",
"collected_at": "2026-05-06T12:00:00+08:00",
"timezone": "Asia/Shanghai",
"batch_id": "uuid",
"events": []
}
```

## Event Shape

Every event contains:

```json
{
"event_id": "sha256-prefix",
"session_id": "uuid",
"timestamp": "2026-05-06T12:00:00.000Z",
"event_type": "token_count",
"line_no": 42,
"accuracy": "token_exact_context_linked",
"context": {}
}
```

Optional event sections:

- `token`: de-duplicated per-call `last_token_usage` fields: `input_tokens`, `cached_input_tokens`, `output_tokens`, `reasoning_output_tokens`, `total_tokens`.
- `rate_limits`: sanitized Codex rate-limit metadata.
- `session`: sanitized session metadata.
- `task`: task lifecycle, duration, TTFT, abort, or error metadata.
- `tool`: tool name, namespace/server, call ID, duration, status, argument keys/counts, and output lengths only.
- `shell`: cwd, exit code, duration, status, command count, command types, and executable names only.
- `patch`: changed file count, change type counts, and file extension counts only.

## Privacy Contract

Clients must not send raw user messages, agent messages, reasoning content, shell stdout/stderr, full shell commands, tool output, API arguments with values, or unified diffs.

## Response Body

The server should return JSON:

```json
{
"accepted": 10,
"duplicates": 2,
"errors": []
}
```

The server must de-duplicate by `event_id`. A repeated `event_id` from the same source should not increment usage totals twice.

For token dashboards, sum only the uploaded `token` fields. Do not ingest or sum Codex log `total_token_usage`; it is cumulative within a session. Codex can also re-emit a `token_count` event when only rate-limit state changes, so clients filter repeated cumulative token snapshots before upload.
Loading
Loading