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'.
In this repository46 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .cursor/rules/commit-conventions.mdcCursor rule
- .cursor/rules/cross-platform-handoff.mdcCursor rule
- .cursor/rules/dev-files-workspace.mdcCursor rule
- .cursor/rules/documentation-standards.mdcCursor rule
- .cursor/rules/gh-cli-preference.mdcCursor rule
- .cursor/rules/github-repository-policy.mdcCursor rule
- .cursor/rules/git-worktree-agent-workflow.mdcCursor rule
- .cursor/rules/hooks-guide.mdcCursor rule
- .cursor/rules/plugin-structure.mdcCursor rule
- .cursor/rules/plugin-version-bump.mdcCursor rule
- .cursor/rules/skill-frontmatter.mdcCursor rule
- .cursor/rules/skill-quality-standards.mdcCursor rule
- .cursor/rules/skills-guide.mdcCursor rule
- .cursor/rules/user-facing-script-standards.mdcCursor rule
- run-tamirs-superpowersSkill
- field-notebook-uiSkill
- diagnose-refusalSkill
- targeted-debugSkill
- decisionSkill
- deliver-devSkill
- diagnose-objectiveSkill
- orchestrate-devSkill
- plan-devSkill
- pr-devSkill
- start-devSkill
- switch-devSkill
- worker-devSkill
- changelog-reviewSkill
- dark-terminal-docSkill
- docs-reviewSkill
- platform-syncSkill
- mcp-builderSkill
- mcp-paginationSkill
- cleanupSkill
- github-policySkill
- multi-agent-repoSkill
- repo-scaffoldSkill
- repo-standardsSkill
- capture-configSkill
- find-skillSkill
- notify-setupSkill
- retroSkill
- session-reportSkill
- skill-creatorSkill
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
- Very specific: line 108
Every rewrite first saves settings.json.bak.<UTC timestamp> (0600) and reports its path.
- Very specific: line 120
If OTEL_EXPORTER_OTLP_ENDPOINT is already set to something else, the script refuses unless --force.
- Very specific: line 125
Do not add the plugin to this repo's opencode.json.
- Very specific: line 136
Start the collector the same way (collector.py --daemon, or the Claude enable script).
- Very specific: line 149
After a Claude turn, a file named YYYY-MM-DD.jsonl (Israel date) should appear in the log directory.
- Distinctive: line 154
Do not invent numbers. If the file is missing, say capture is not running or no requests landed yet — not "zero usage".
≈ “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.
Files
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
| Target | Status | Why |
| Claude Code | supported | Native OTEL logs + traces → local collector |
| Claude Desktop | partial | Same settings file may apply; not verified here — check for JSONL before claiming it works |
| OpenCode CLI | partial | Optional 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 CLI | unsupported | No 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.shEvery 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 --jsonAfter 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).jsonlTop 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).jsonlSlowest 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).jsonl5. Disable
bash scripts/usage-capture/enable.sh --disableThe 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-reportor parse~/.claude/projectshere. - Claim OpenCode
supporteduntil a live fire is recorded. - Enable managed/org OTEL settings in v1.
- Bind the collector anywhere but
127.0.0.1.
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
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.

