agentleFS
Tamircohen28Tamircohen28/tamirs-superpowers/skills/toolkit/usage-capture/SKILL.md

usage-capture

Skill2 starsChanged 3 months agoMITView on GitHub

Use when local Claude Code or OpenCode LLM requests should be recorded or inspected on this machine — daily JSONL usage logs, API body sidecars, latency bottlenecks. Triggers: 'usage capture', 'enable usage capture', 'local usage log', 'record LLM requests', 'LLM latency', 'which model was used', 'request duration', 'usage metrics'.

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 1 is distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Every rewrite first saves settings.json.bak.<UTC timestamp> (0600) and reports its path.

    line 108
  2. Very specific:

    If OTEL_EXPORTER_OTLP_ENDPOINT is already set to something else, the script refuses unless --force.

    line 120
  3. Very specific:

    Do not add the plugin to this repo's opencode.json.

    line 125
  4. Very specific:

    Start the collector the same way (collector.py --daemon, or the Claude enable script).

    line 136
  5. Very specific:

    After a Claude turn, a file named YYYY-MM-DD.jsonl (Israel date) should appear in the log directory.

    line 149
  6. Distinctive:

    Do not invent numbers. If the file is missing, say capture is not running or no requests landed yet — not "zero usage".

    line 154

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Usage Capture

Opt-in, local-only recorder for per-request LLM metrics. One JSONL file per Asia/Jerusalem calendar day under ~/.local/share/tamirs-superpowers/usage/. Nothing is sent to a collector in the cloud, to GitHub, or to Anthropic beyond the LLM call the user already configured.

Claude Code is captured through its native OpenTelemetry export (including a custom ANTHROPIC_BASE_URL). LiteLLM is supported as an explicitly labelled gateway; its URL and raw request IDs are never persisted. OpenCode is captured by an optional JS plugin that is not on by default. Cursor, Codex, and Gemini CLI are out of scope.

This is not /session-report. That skill post-parses Claude Code transcripts under ~/.claude/projects for token/cache rollups. This skill records live request timing, model, endpoint, and skill/command inventory. Point at session-report when the user wants historical Claude transcript spend.

Compatibility

TargetStatusWhy
Claude CodesupportedNative OTEL logs + traces → local collector
Claude DesktoppartialSame settings file may apply; not verified here — check for JSONL before claiming it works
OpenCode CLIpartialOptional opencode-plugin.mjs (OpenCode 2 Plugin.define, ctx.event.subscribe); not loaded by this repo's opencode.json; a live fire has not been recorded
Codex, Cursor, Gemini CLIunsupportedNo capture path shipped

Before enabling, confirm shell is available. The hooks capability is optional: without it, start the collector with collector.py --daemon yourself instead of relying on SessionStart.

Privacy default

Metadata only: model, Israel timestamps, duration / TTFT, tokens, skill and command names, session id, custom-endpoint label. No prompt text and no API JSON unless the user passes --bodies. Bodies are secret-bearing (conversation history, tool results, code). Say so before turning them on.

Workflow

0. Resolve the plugin / repo root

Try in order: $CLAUDE_PLUGIN_ROOT, $CLAUDE_SKILL_DIR/../../../.. (skill is skills/toolkit/usage-capture), then the current git toplevel. The collector lives at scripts/usage-capture/collector.py and the enabler at scripts/usage-capture/enable.sh.

1. Enable (Claude Code)

bash scripts/usage-capture/enable.sh

Every rewrite first saves settings.json.bak.<UTC timestamp> (0600) and reports its path.

Useful flags: --dry-run --json, --bodies, --disable, --dir DIR, --port PORT. For LiteLLM use --gateway-kind litellm --endpoint-label <opaque-label>; do not put a gateway URL in the label. The client collector sees end-to-end latency, not LiteLLM's internal retries/fallbacks or backend timing.

Then restart Claude Code so ~/.claude/settings.json env is picked up. Expect TAMIRS_USAGE_CAPTURE=1 plus OTEL pointing at http://127.0.0.1:17431 with http/json. OTEL_LOG_USER_PROMPTS stays unset. OTEL_LOG_TOOL_DETAILS=1 so skill/command names appear.

If OTEL_EXPORTER_OTLP_ENDPOINT is already set to something else, the script refuses unless --force.

2. Enable (OpenCode) — optional plugin

Do not add the plugin to this repo's opencode.json. In the user's ~/.config/opencode/opencode.json (or project config), add an absolute path under the OpenCode 2 plugins key (the plugin is an OpenCode 2 Plugin.define module since 5.0.0; OpenCode 1 does not run it):

{
  "plugins": ["/absolute/path/to/tamirs-superpowers/skills/toolkit/usage-capture/opencode-plugin.mjs"]
}

Start the collector the same way (collector.py --daemon, or the Claude enable script). Restart OpenCode. Mark this row partial in any report: the module loads on 2.0.32 (opencode plugin list); a live fire of its event subscription has not been recorded.

Bodies: TAMIRS_USAGE_CAPTURE_BODIES=1.

3. Confirm it is up

python3 scripts/usage-capture/collector.py --status --json

After a Claude turn, a file named YYYY-MM-DD.jsonl (Israel date) should appear in the log directory. Mode 0700 on the directory, 0600 on files.

4. Query a day

Do not invent numbers. If the file is missing, say capture is not running or no requests landed yet — not "zero usage".

p95 duration by model:

jq -s 'map(select(.event=="api_request" and .duration_ms!=null))
  | group_by(.model)
  | map({model: .[0].model, n: length, p95: (sort_by(.duration_ms) | .[(length*0.95|floor)].duration_ms)})' \
  ~/.local/share/tamirs-superpowers/usage/$(TZ=Asia/Jerusalem date +%Y-%m-%d).jsonl

Top skills by input tokens:

jq -s 'map(select(.skill_name and .input_tokens))
  | group_by(.skill_name)
  | map({skill: .[0].skill_name, input_tokens: (map(.input_tokens)|add)})
  | sort_by(-.input_tokens)' \
  ~/.local/share/tamirs-superpowers/usage/$(TZ=Asia/Jerusalem date +%Y-%m-%d).jsonl

Slowest custom-endpoint calls:

jq -s 'map(select(.event=="api_request")) | sort_by(-.duration_ms) | .[:10]
  | map({ts, model, endpoint, duration_ms, ttft_ms, skill_name})' \
  ~/.local/share/tamirs-superpowers/usage/$(TZ=Asia/Jerusalem date +%Y-%m-%d).jsonl

5. Disable

bash scripts/usage-capture/enable.sh --disable

The same backup applies. --stop signals only a PID whose command line is the collector. A stale pid file naming another process is removed, and that process is left running. Restart Claude Code. Remove the OpenCode plugin path if it was added. Logs on disk are left in place — ask before deleting.

JSONL fields (omit rather than invent)

ts, harness (claude_code | opencode), event (api_request | api_error | user_prompt | skill_activated | tool_result | session_start | llm_request), session_id, prompt_id, request_id, model, query_source, duration_ms, ttft_ms, token fields, request_bytes, skill_name, command_name, plugin_name, agent_name, mcp_server, mcp_tool, endpoint, success, status_code, stop_reason, cost_usd, body_ref (only with --bodies).

Fallback when hooks is missing

usage-capture-ensure.sh is env-gated SessionStart. On a surface without that event, run python3 scripts/usage-capture/collector.py --daemon yourself. The skill still enables Claude settings and still documents the OpenCode plugin.

Do not

  • Merge this into session-report or parse ~/.claude/projects here.
  • Claim OpenCode supported until a live fire is recorded.
  • Enable managed/org OTEL settings in v1.
  • Bind the collector anywhere but 127.0.0.1.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.