A beautiful web UI for unified usage/cost analysis across:
- Claude Code JSONL usage files
- Codex CLI session JSONL files
- OpenClaw usage snapshots (via
profilex usage exportingestion) - ProfileX profile mappings (
state.json)
Built with Svelte + Vite + Tailwind CSS + TypeScript.
- Imports ProfileX
state.json - Imports usage files (multiple JSONL files)
- Imports ProfileX unified usage bundle JSON files (great for multi-machine aggregation)
- Detects Claude vs Codex event formats
- Normalizes events into one schema
- Maps each event to profile:
- ProfileX-managed profile if matched
default-<counter>fallback if not matched
- Pulls latest LiteLLM model pricing
- Computes costs in configurable mode:
auto(observed if available, else calculated)calculatedisplay
- Produces tabular breakdowns:
- Daily × Profile
- Profile Summary
- Tool Totals
- Grand Totals
pnpm install
pnpm devOpen the local URL Vite prints (usually http://localhost:5173).
pnpm dev now preflights public/local-unified-usage.json before Vite starts:
- If the report exists, it is reused.
- If missing, it runs
pnpm generate:local:deepfirst. - Pass
--force-reportto regenerate even when it exists. - Pass
--skip-reportto skip preflight generation.
Examples:
pnpm dev -- --force-report
pnpm dev -- --skip-reportpnpm build
pnpm previewIf you want this UI to auto-load local data on startup (without manual file picking), run:
pnpm generate:localBy default this uses the ProfileX CLI bridge:
profilex usage export --out ./public/local-unified-usage.jsonIf profilex is unavailable or fails, it falls back to the local parser/scanner logic.
- Use
--no-profilex-clito force fallback scanner mode. - Set
PROFILEX_UI_SKIP_PROFILEX_CLI=1to skip the bridge.
It writes:
public/local-unified-usage.json
You can run a broader home-directory scan with:
pnpm generate:local:deepOn app boot, the UI checks for public/local-unified-usage.json:
- If present: it auto-loads events and profile mappings.
- If missing: it stays in manual upload mode and shows a command hint.
- On each machine, run:
profilex usage export --out ./local-unified-usage.<machine>.json --deep- Move those JSON files to your main machine.
- In ProfileX-UI, use Import ProfileX usage bundle(s) (.json) and select all of them.
The UI merges events and profile metadata across bundles.
Upload ~/.profilex/state.json (or PROFILEX_HOME/state.json) so the UI can map events to named profiles.
Typically under:
~/.config/claude/projects/**/*.jsonl~/.claude/projects/**/*.jsonl- or profile-specific
CLAUDE_CONFIG_DIR/projects/**/*.jsonl
Typically under:
~/.codex/sessions/**/*.jsonl- or profile-specific
CODEX_HOME/sessions/**/*.jsonl
- Pricing source: LiteLLM model pricing catalog.
- Browser sandbox means path matching depends on uploaded filenames/relative paths.
- For strongest profile mapping, upload files with meaningful relative paths (e.g. from profile directories).
MIT