session-audit
Skill4 starsChanged 4 days agoMITView on GitHub
Audit pi agent session logs (~/.pi/agent/sessions) for token/cost waste and produce a ranked, attributed efficiency report (habit / skill_file / config). Use when the user asks to audit session efficiency, analyze token waste or cost blowups, review usage cost, or asks "where are my tokens going".
9 other projects use a version of this.
Adopted by
Most recently taken up by
- 5hirish/ducttheir own version, first seen Nov 8, 2026
- ethosagent/ethostheir own version, first seen Nov 3, 2026
- zanellig/skillstheir own version, first seen Nov 1, 2026
- iceberggymnast/skillstheir own version, first seen Oct 17, 2026
- GRIDLOCK-NYC/claude-skillstheir own version, first seen Oct 8, 2026
- t1merickson/skillstheir own version, first seen Sep 4, 2026
Used with
Projects with it also use handoff.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
MicrosoftSkillhandoff
Compact the current conversation into a handoff document for another agent to pick up.
Also in 3 projects that use this
Other versions9 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 9
- ethosagent/ethos★ 22same name
- 5hirish/duct★ 8same name
- t1merickson/skills★ 1same name
- zanellig/skills★ 1same name
- dylanmoo/workos-plugin★ 0same name
- GRIDLOCK-NYC/claude-skills★ 0same name
- iceberggymnast/skills★ 0same name
- Lucioway/way-stack★ 0same name
- meggiepham06-smile/session-audit-skill★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository25 other files it gives its agents.
- AGENTS.mdAGENTS.md
- archifySkill
- authSkill
- brainstormingSkill
- browser-toolsSkill
- code-reviewerSkill
- documentation-writerSkill
- fallow-auditSkill
- frontend-designSkill
- github-actionsSkill
- grill-meSkill
- harness-engineerSkill
- impeccableSkill
- linkedinSkill
- map-integrationSkill
- pidocSkill
- playwright-testerSkill
- ponytailSkill
- refactoring-uiSkill
- rust-skillsSkill
- sdk-developmentSkill
- self-learnSkill
- skill-managerSkill
- systematic-debuggingSkill
- web-searchSkill
The file
We split this skill into the rules it gives an agent
3 rules. 0 are common, 0 are distinctive, and 3 are very specific to this project.
0
Common
Most of the 8 edited versions we read keep these.
0
Distinctive
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 75
Never read overview.json/l1_findings.json wholesale (>100KB).
- Very specific: line 81
Finding counts ≠ population counts: Every rule has entry gates — CACHE_MISS_RATE needs ratio < 0.5 *and* ≥5 turns — so "1 finding" never …
- Very specific: line 129
Write ~/.pi/agent/audit-reports/<YYYY-MM-DDTHHMMSSZ>.md (create dir if absent).
“Common” is measured: kept by at least 6 in 10 of the 8 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Session-Audit (pi)
You = reasoning layer (L2/L3) of layered audit engine. Deterministic scripts (L0/L1) digest raw session logs into metadata-only artifacts; you reason over aggregates, escalate to content only via budget-capped fetch interface.
<skill-dir> = this skill's directory (location attribute on injected skill tag; normally ~/.pi/agent/skills/session-audit). Set workdir once:
export AUDIT_WORKDIR=<session scratchpad>/audit_workdir # working artifacts — ephemeralTwo lifetimes
JSON artifacts = intermediates, ephemeral workdir. Report = deliverable, must outlive session — dated file in stable archive:
mkdir -p ~/.pi/agent/audit-reports
# final report -> ~/.pi/agent/audit-reports/<YYYY-MM-DDTHHMMSSZ>.mdPast reports = only way to answer "am I improving?": trend comes from comparing today's report to archive, not data layer.
Invariants (non-negotiable)
- (I1) Never read raw session JSONL directly (no read/cat/grep on
~/.pi/agent/sessions/**/*.jsonl). All access viarun+fetch. - (I2) Metadata by default; fetch content only to resolve specific hypothesis,
--max-bytes ≤ 2000, ≤~10 fetches/audit. - (I3) Waste math never trusts raw
inputtoken sums (streaming placeholders). Anchor oncacheRead,cacheWrite, content bytes. - (I4) All aggregation deduped by
responseId(scripts do it — never hand-roll parsing). - (I5) No side effects outside
$AUDIT_WORKDIRand the report path. - (I6) Log every fetch to
$AUDIT_WORKDIR/fetch_log.jsonl— self-cost is part of the report. - (I7) Scripts are read-only over sessions; never edit them mid-audit (running from installed bundle).
Relative target words ("current repo", "previous session", "recent") ambiguous: each retarget orphans every call spent on prior reading (measured: ~25% of audit 2026-10-10T121209Z). Relative request → ask once, wait:
- Target — which repo/project, or session id?
- Window — last 1 / last N / date range / whole project?
- Depth — numbers only (L0/L1, no verdicts) or full audit (L2/L3 + report)?
- Output — archived report or chat summary?
One cheap ask beats rerun. Bare "yes" ≠ scope — re-ask. Confirmed → run cheap: run --max 50 when target recent (single session/last day), views --project <name> directly instead of global view (capped global output forces spill-file re-reads).
Phase 0 — Digest (L0 + L1, zero LLM)
node <skill-dir>/scripts/audit.mjs run # full directory
node <skill-dir>/scripts/audit.mjs run --max 50 # quick pass, newest 50 sessionsWrites to $AUDIT_WORKDIR: manifest.json (thresholds + pricing: per-model input rates derived from logged usage.cost, unpriced models, priced waste share), l1_findings.json (rule findings: {rule, severity, sessionId, turnPointers, evidenceStats, estWasteTokens, project}), overview.json (aggregates: projects, tools, models, gapBuckets, dates, skills, sessions by waste). Per-session/per-project rollups carry wasteUsd + wasteTokens, models, usdPerMTok, pricedShare, compactions.
Rules: CACHE_TTL_EXPIRY, DUP_TOOL_CALL, BIG_TOOL_OUTPUT, RETRY_STORM, CACHE_MISS_RATE, CONTEXT_GROWTH.
Phase 1 — Aggregate landscape
User names target (project/path/session) absent from digest → stop, ask. Never substitute closest match; wrong-target audit wastes entire run, reports confidently about wrong code. Includes targets excluded as active: report exclusion, ask inspect-via-fetch / audit-after-close / different target — user decides, not auditor.
node <skill-dir>/scripts/audit.mjs views
node <skill-dir>/scripts/audit.mjs views --project <name> # per-project slice: sessions, finding detail, per-date trendConfirmed scope = single project/session → slice with views --project <name> first; global view only for directory-wide questions.
One bounded block: totals (tokens + dollars), findings-by-rule with sessions-affected count, cache hit-ratio distribution, projects + worst sessions by waste (full session ids + fetch command to inspect one), idle-gap cost curve, tools by bytes, dup-read targets, BIG_TOOL_OUTPUT by tool, peak-context + compactions, per-date trend, skill usage.
Never read overview.json/l1_findings.json wholesale (>100KB); never hand-roll node one-liners for anything views prints — every query + output lands in transcript = audit's real self-cost.
Missing stat → say so in report — never add to views.mjs. Running from installed bundle (I7). Record gap under "stats this report wanted and could not get"; human ports it to repo. Missing stat blocks specific claim → single narrow query acceptable — state in report you ran it; transcript cost real + unlogged.
Two traps the view prevents:
- Finding counts ≠ population counts. Every rule has entry gates —
CACHE_MISS_RATEneeds ratio < 0.5 and ≥5 turns — so "1 finding" never means "1 session with that property". Read distribution block, never rule count. - Raw vs cost-equivalent tokens.
gapBuckets.cacheCreationraw; rule waste cost-equivalent (creation × (write − read)). View prints gap curve in both units. Compare like with like before claiming corroboration.
Phase 2 — L2 hypothesis loop
- From landscape, form candidate patterns. Recurring high-value:
- TTL expiry after idle gaps (check
gapBuckets— cost per resume vslt_1mbaseline) - large-file re-read loops (DUP + BIG on
read/bashsame sessions) - marathon sessions near context ceiling
- compaction-heavy sessions
- unbatched round-trips (many single-tool turns)
- image-heavy low-cache sessions.
- TTL expiry after idle gaps (check
- Confirm/dismiss with narrower queries over per-session
findingsByRule+ finding details. - Metadata can't resolve intent → escalate with fetch:
node <skill-dir>/scripts/audit.mjs fetch <session-id> --kind <kind> [--limit N] [--max-bytes B] [--uuid U] [--radius K]| kind | returns | judge |
user_text | user messages (skill injections excluded) | intent vs agent behavior |
error_head | head of errored tool results | transient vs deterministic failure |
tool_input | tool call params | which file/command duplicated |
assistant_head | head of assistant text | verbosity / narration |
turn_window | metadata around --uuid responseId | sequence reconstruction |
- Write
$AUDIT_WORKDIR/l2_hypotheses.json:
[{ "pattern": "NAME", "evidence": ["stat or fetch ref", "..."], "confidence": "high|medium|low",
"escalation_fetches": ["..."], "resolution": "resolved|escalate", "interpretation": "one sentence" }]Phase 3 — L3 attribution
Reason over hypotheses + fetched snippets only. Write $AUDIT_WORKDIR/attribution.json, ranked by waste:
[{ "rank": 1, "finding": "...", "attribution": "habit|skill_file|config",
"estWasteShare": "~N% (xK of yK)", "trend": "improving|worsening|steady",
"fix": "concrete behavior change, named skill edit, or config change" }]Attribution guide: habit = working style (resuming big sessions after breaks, inline scanning, whole-file re-reads, unbatched commands); skill_file = named skill drives pattern (which SKILL.md + what to change — instructions made agent read too much, or description fires it on wrong tasks); config = model default, thinking level, AGENTS.md/skill-catalog bloat (permanently re-sent prefix), provider cache behavior.
Phase 4 — Report
Write ~/.pi/agent/audit-reports/<YYYY-MM-DDTHHMMSSZ>.md (create dir if absent). Timestamp: date -u +%Y-%m-%dT%H%M%SZ (UTC, second-precision).
Required content (header, totals, findings-by-rule with sessions-affected, per-project breakdown, ranked fixes, do-this-first pick, trend, self-cost) + two-version ASCII chart format: references/report-format.md.
Then summarize top 3 changes in chat, in user's own context, say where report saved.
Interpretation notes
CONTEXT_GROWTHcarries zero direct waste — amplifier of everything else in session. Compaction counts same way: compaction re-sends summary in place of prefix; cost not separately priced.CACHE_TTL_EXPIRYfindings carryevidenceStats.gapKind. Onlyuser_idlegaps priced as waste;tool_runtimegaps reported zero by design — wait was long-running command, not habit. CheckgapKindbefore calling TTL finding a habit.- Rank by prefix persistence: early, long-riding costs beat late one-offs same size.
- Dollars priced per session from own model mix (rates derived from sessions' own logged
usage.cost) — token ranking + dollar ranking can legitimately disagree. When they do, dollar order = one to act on; call it out. DUP_TOOL_CALLonreadwas path-keyed in pre-2026-10-10 digests (normalizer droppedoffset/limit) — before attributing read dup as waste, fetchtool_input, compare windows: disjoint windows = continuation reads, not dups. Keying fixed forread2026-10-10 (same class as 2026-09-14editfix); old reports + archived digests still carry false positives.- Peak context can exceed 200K on large-context models; not a bug.
- Count-based sweeps self-pollute: subagent prompts carrying the search strings and extension source echoed into toolResults both match — classify by record role (toolResult vs assistant text), exclude audit-session ids and repro fixtures before counting.
- Healthy directory (hit ratio >0.95, near-linear growth) → short report saying so; never manufacture findings.
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.

