Setup Cost Tracking
SkillMonitoring & opsInstall genuine per-session cost tracking for Claude Code by wiring bundled logger scripts into the user's statusline — preserving any existing statusline and hooks. Use when the user asks to set up, install, enable, or repair cost tracking / cost logging / session cost capture. Idempotent; safe to re-run.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Setup Cost Tracking skill
What this skill tells your AI
The instructions your AI receives, as published by foyzulkarim/skills in dev-pipeline/skills/setup-cost-tracking/SKILL.md and read by ahel’s review.
Installs genuine cost capture for every Claude Code session on this machine. Cost data
(cost.total_cost_usd etc.) is computed by Claude Code itself and is available only
in the statusline payload — hooks never receive it. So this skill wires a logger into the
statusline path while preserving whatever statusline and hooks the user already has.
What gets installed
Bundled in this skill's scripts/ directory, copied to ~/.claude/scripts/:
| Script | Role |
|---|---|
cost-logger.js | Capture engine. Silent, crash-proof. Writes the log files below. |
statusline-wrapper.js | Used when the user already has a statusline: logs cost, then delegates the payload to their original command and passes its output through untouched. |
statusline-command.js | Used when the user has no statusline: full display (model, context bar, cost, cache stats) that also logs. |
turn-logger.js | Stop hook: stamps turn boundaries so cost samples can later be grouped into turns for analytics. No cost data itself. |
Log outputs (created lazily, no setup needed):
~/.claude/cost-log.jsonl— one row per session, exact cumulative totals (upserted).~/.claude/projects/<mapped-dir>/<session>.cost.jsonl— cost samples at ~5s resolution during activity.~/.claude/projects/<mapped-dir>/<session>.turn-boundaries.jsonl— one row per turn end, withtranscript_pathfor deep-dive analytics.
Installation procedure
Follow these steps exactly. Use real JSON manipulation (a node -e script or jq) for
every settings edit — never string/regex edits on settings files.
Step 0 — Preflight
command -v node— if Node.js is missing, stop and tell the user it's required. Record the absolute path (call it$NODE). Use$NODEin every command you write into settings, not barenode(statusline/hook commands don't always get the user's full shell PATH).- Read
~/.claude/settings.json(treat as{}if absent) and~/.claude/settings.local.json(if present). The effectivestatusLineis the local one if defined there, else the user one. Remember which file defines it — edits must go to that same file.
Step 1 — Copy scripts
mkdir -p ~/.claude/scripts- Copy the four
.jsfiles from this skill'sscripts/directory into~/.claude/scripts/andchmod +xthem. Overwriting previous versions of these four files is fine (that's how upgrades work). Never overwrite~/.claude/scripts/statusline-original.jsonif it exists.
Step 2 — Wire the statusline (the load-bearing step)
Decide by the effective statusLine:
- Case A — already ours: its command contains
statusline-wrapper.jsorstatusline-command.js. Nothing to change; report "already installed" and continue to Step 3. - Case B — none configured: set in
~/.claude/settings.json:
(expand"statusLine": { "type": "command", "command": "$NODE /Users/<user>/.claude/scripts/statusline-command.js", "padding": 0 }$NODEand the home directory to absolute paths). - Case C — user has their own statusline: preserve it.
- Write
~/.claude/scripts/statusline-original.jsoncontaining exactly{ "command": "<their current statusLine.command>" }. - In the file that defines
statusLine, replace only thecommandvalue with$NODE /Users/<user>/.claude/scripts/statusline-wrapper.js. Keeptype,padding,refreshInterval, and any other sibling keys untouched.
- Write
Before the first edit to any settings file, back it up:
cp settings.json settings.json.bak-cost-tracking (same pattern for the local file).
One backup per run is enough.
Step 3 — Add the turn-boundary hook (additive, never replaces)
If no existing hooks.Stop entry's command mentions turn-logger.js, append this entry to
the hooks.Stop array (create the array/path if missing), leaving every existing hook alone:
{ "matcher": "", "hooks": [ { "type": "command", "command": "$NODE /Users/<user>/.claude/scripts/turn-logger.js" } ] }
This hook carries no cost data — it only stamps turn boundaries and the idle timer. If the user objects to hooks, skipping this step still leaves session cost capture fully working.
Step 4 — Verify
- Build a fake statusline payload with
session_id"cost-setup-verify", aworkspace.current_dirof/tmp/cost-setup-verify, and nonzerocost.total_cost_usd/cost.total_api_duration_ms/model.display_namevalues. - Pipe it via stdin into the exact
statusLine.commandnow in settings (run throughsh -c).- Case B: expect the rendered multi-line statusline.
- Case C: expect the original statusline's output (the wrapper delegates). If their original command errors on the synthetic payload, that's their script's quirk — check instead that the log file below was written.
- Confirm
~/.claude/projects/-tmp-cost-setup-verify/cost-setup-verify.cost.jsonlnow exists and contains the fake cost. - Clean up all verification artifacts: that projects subdirectory, the
cost-setup-verifyline in~/.claude/cost-log.jsonl, and/tmp/statusline-*-cost-setup-verifystate files.
Step 5 — Report
Tell the user, concretely:
- which case applied (fresh install / wrapped their existing statusline / already installed),
- every file created or modified (settings edits, backups, copied scripts),
- where their cost data will accumulate (the three log paths above),
- that changes take effect in new sessions,
- how to uninstall: restore the
.bak-cost-trackingsettings backup (or, by hand: pointstatusLine.commandback to the command saved in~/.claude/scripts/statusline-original.jsonand remove the turn-logger Stop hook entry), then delete the four scripts.
Invariants
- Never delete or rewrite the user's hooks, statusline command, or unrelated settings keys. All changes are additive or a single-value swap that is recorded for reversal.
- Idempotent: re-running on an installed machine must change nothing and say so.
- If any step fails midway, restore the settings backup and report what happened.
Signals
- GitHub stars
- 42
- Forks
- 14
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
setup-cost-tracking- Source
- github.com/foyzulkarim/skills