Compare commits

..

3 Commits

Author SHA1 Message Date
Morgan Lunt
8ef7f78869 receipts: trim the README to what a user needs
It had grown into an argument with a reviewer — three sections of
rationale for decisions a reader doesn't have to agree with to use the
thing. Install command up top, then how to run it and what comes out.

The reasoning is still in the code comments and SKILL.md, where whoever
maintains this next will look for it.
2026-07-17 16:18:35 -07:00
Morgan Lunt
3b93169856 receipts: count only work that can be checked
The first cut measured the agent's activity and reported it as the
developer's. Rewrites the attribution so every number is one you could
defend to someone who pushed back on it.

What a number now means:

- Projects resolve to a git root, or to the directory the work happened
  in when there isn't one. Not basename(cwd), which turned a home
  directory into a 49% "project" and split one repo across several rows.
- A session's spend follows the files it touched, reads included, split
  across projects. Subagents share their parent's session, so their work
  lands on the same project with no special case.
- Claude Code's own machinery — scratchpad, tool-results, ~/.claude, and
  this report's own past output — is excluded. It was 82% of the reported
  line count.
- Commits are joined against git: authored under the identity git uses in
  that repo, AND touching a file Claude Code touched. The old identity
  grep counted a snapshot cron's 2,209 commits and claimed the developer
  committed on every active day they worked.
- Work with no project — web search, chat tools, dashboards — is named as
  research rather than filed under whatever directory the shell sat in.

What's gone, and why:

- The activity/spend breakdown. A turn's cost is ~90% context handling,
  half of it re-reading what earlier turns added, so charging it to
  whichever tool fired is a modeling choice rather than a measurement —
  and the choice decides the answer. On one real month three defensible
  weightings put web search at 11%, 28% or 51%. Per-project spend
  survives the same test and stays.
- The `git commit` counter. A Bash call carries no working directory, so
  a commit in a throwaway fixture repo can't be told from a real one.
  Measured 33 against 4.

Also: local calendar arithmetic (active days could exceed the window),
paths normalized so Windows doesn't silently count the scratchpad as the
user's work, HTML written 0600 and refusing symlinks, a CSV export with
formula injection neutralized, print output that stays vector text, and
perforated edges.

The report says which columns sum and which don't, and distinguishes "no
commits" from "git couldn't be read" — unknown is not zero.
2026-07-17 11:47:45 -07:00
Morgan Lunt
78cb97b3e6 Add receipts plugin
A personal Claude Code impact report built from the session transcripts
already on disk at ~/.claude/projects, for the conversation where a dev
has to explain what their usage bought. Produces a markdown report and a
self-contained HTML receipt in the home directory.

Complements session-report, which reads the same transcripts to drive
usage down; this reads them to explain what the usage produced, and
cross-references local git history to tie spend to shipped work.

Two design rules the report is built around: no dollar figures, since a
cost inferred from local token counts won't match anyone's real bill and
inviting "that can't be right" discredits everything next to it; and no
invented "hours saved", since there's no baseline in local data to derive
a counterfactual from.

Mining is local — file I/O and git, no network. Tool calls are grouped
into five activity categories during mining so raw tool names, which
enumerate the dev's connected MCP servers, never leave the script. The
report is published nowhere unless the user asks.
2026-07-16 11:22:16 -07:00
5 changed files with 63 additions and 328 deletions

View File

@@ -64,7 +64,7 @@
"source": {
"source": "url",
"url": "https://github.com/SalesforceAIResearch/agentforce-adlc.git",
"sha": "3d70dc3e2188c6cbb536422ef2bc1b52a1f53c2f"
"sha": "f7630726ddce5c2c171cfb9d18ce435fab862ae7"
},
"homepage": "https://github.com/SalesforceAIResearch/agentforce-adlc"
},
@@ -161,29 +161,6 @@
},
"homepage": "https://github.com/awslabs/agent-plugins"
},
{
"name": "amd-skills",
"description": "AMD's verified Agent Skills in one plugin: route image/audio through local AI on Ryzen AI, serve LLMs on AMD Instinct GPUs with vLLM, and analyze GPU kernel and PyTorch trace performance.",
"author": {
"name": "AMD"
},
"category": "development",
"source": {
"source": "git-subdir",
"url": "https://github.com/amd/skills.git",
"path": "skills",
"ref": "main",
"sha": "228980933abd97a8aa4a2656c8ea3ae9e8b590c7"
},
"strict": false,
"skills": [
"./local-ai-use",
"./local-ai-app-integration",
"./serving-llms-on-instinct",
"./tracelens-analysis-orchestrator"
],
"homepage": "https://developer.amd.com/"
},
{
"name": "amplitude",
"source": {
@@ -207,7 +184,7 @@
"source": {
"source": "url",
"url": "https://github.com/apolloio/apollo-mcp-plugin.git",
"sha": "2adde980e45f421b7e9383d92870455627936bce"
"sha": "d0676ea9bba52b0f97d810dade775de059ccd2bd"
},
"homepage": "https://www.apollo.io/"
},
@@ -253,7 +230,7 @@
"source": {
"source": "url",
"url": "https://github.com/astronomer/agents.git",
"sha": "87d780cd5dc85a25c7ceb1f1720031fa4e48f781"
"sha": "5432198caa8ef9ec33218124bcd44016db2d31bf"
},
"homepage": "https://github.com/astronomer/agents"
},
@@ -286,7 +263,7 @@
"source": "url",
"url": "https://github.com/BrainBlend-AI/atomic-agents.git",
"path": "claude-plugin/atomic-agents",
"sha": "b15ca449a81278b1c92666bdf9a2e57a817dcacd"
"sha": "7fb0741f52ae7312b6e00bf1ad2c80aab4a2709e"
},
"homepage": "https://github.com/BrainBlend-AI/atomic-agents",
"tags": [
@@ -306,7 +283,7 @@
"url": "https://github.com/auth0/agent-skills.git",
"path": "plugins/auth0",
"ref": "main",
"sha": "d1b19854e60c6dfde048df91e4d97e536dba2491"
"sha": "ec605c397aab905c25871c791e9777dbbb633db5"
},
"homepage": "https://auth0.com"
},
@@ -367,7 +344,7 @@
"url": "https://github.com/aws/agent-toolkit-for-aws.git",
"path": "plugins/aws-core",
"ref": "main",
"sha": "493b45323dd3163fb561792b9e091de3d4966709"
"sha": "b3cc4c4f8473a8e4b7209ff735af2aa90cae76eb"
},
"homepage": "https://github.com/aws/agent-toolkit-for-aws"
},
@@ -477,7 +454,7 @@
"source": {
"source": "url",
"url": "https://github.com/base44/skills.git",
"sha": "40e548021670ed409d3bae15601726cf652d846f"
"sha": "58a183b6e912fe8ae2827c603d485a37b7d00e1b"
},
"homepage": "https://docs.base44.com"
},
@@ -565,7 +542,7 @@
"source": {
"source": "url",
"url": "https://github.com/buildkite/skills.git",
"sha": "e854e111766e9494d742fe6836d5b6ecefd10b68"
"sha": "24242e53c688546fb39e40a7f1f769dbbcd77400"
},
"homepage": "https://buildkite.com"
},
@@ -597,7 +574,7 @@
"url": "https://github.com/carta/plugins.git",
"path": "plugins/carta-cap-table",
"ref": "main",
"sha": "a007723c7149acab9f9357eaa74b98635bb63934"
"sha": "1f99da852c903c97349b39132101e9cf9145f883"
},
"homepage": "https://carta.com"
},
@@ -613,7 +590,7 @@
"url": "https://github.com/carta/plugins.git",
"path": "plugins/carta-crm",
"ref": "main",
"sha": "62e9f9a00ba06ab54f9f8896fb8becdbfd6dd46a"
"sha": "fdc57d653abf38cc0a70ddd9e4f23c273af86a7b"
},
"homepage": "https://carta.com"
},
@@ -629,7 +606,7 @@
"url": "https://github.com/carta/plugins.git",
"path": "plugins/carta-investors",
"ref": "main",
"sha": "80da56af79af8779f0dd1a08b8eaaf372fa48c9c"
"sha": "1f99da852c903c97349b39132101e9cf9145f883"
},
"homepage": "https://carta.com"
},
@@ -656,7 +633,7 @@
"source": {
"source": "url",
"url": "https://github.com/ChromeDevTools/chrome-devtools-mcp.git",
"sha": "b4546ef86b86e8733f88f075169d2124f436dd1e"
"sha": "9a7e04daa2cd031afe469d4503d6baf58b9b2cea"
},
"homepage": "https://github.com/ChromeDevTools/chrome-devtools-mcp"
},
@@ -750,7 +727,7 @@
"source": {
"source": "url",
"url": "https://github.com/ClickHouse/clickhouse-claude-code-plugin.git",
"sha": "4c60200bf523342b68d5935b53f4dd0acb53e6b8"
"sha": "0b64ebd82240c14639c55c6f800bcad4626e3224"
},
"homepage": "https://github.com/ClickHouse/clickhouse-claude-code-plugin"
},
@@ -841,7 +818,7 @@
"source": {
"source": "url",
"url": "https://github.com/cockroachdb/claude-plugin.git",
"sha": "fb845eda90ab894f26df7b084f3652e5cef49dd4"
"sha": "c511ba806b1797b1737fc4cbffbe3dba8697b1f2"
},
"homepage": "https://github.com/cockroachdb/claude-plugin"
},
@@ -885,7 +862,7 @@
"source": {
"source": "url",
"url": "https://github.com/coderabbitai/skills.git",
"sha": "c61c4908d36dda6fb08a343cc8b19c59fbb47de3"
"sha": "2fd091d9582deccf19929e21f934921d0e8f686e"
},
"homepage": "https://github.com/coderabbitai/skills"
},
@@ -899,7 +876,7 @@
"source": {
"source": "url",
"url": "https://github.com/CodSpeedHQ/codspeed.git",
"sha": "26fb4b598f08faee386a8fa4212b8350c33dc013"
"sha": "705245d4c1ca91181a6fb705d9c222868fd8c2a8"
},
"homepage": "https://codspeed.io"
},
@@ -924,7 +901,7 @@
"source": {
"source": "url",
"url": "https://github.com/spotify/confidence-ai-plugins.git",
"sha": "a6e3760e5c274dd273e6e4677235422f98f01f4a"
"sha": "042f3259a3bdf85c0a2d1727f2218cfa68a4ed71"
},
"homepage": "https://confidence.spotify.com"
},
@@ -1027,7 +1004,7 @@
"source": {
"source": "url",
"url": "https://github.com/dash0hq/dash0-agent-plugin.git",
"sha": "d7d95883b2e65290c6c08bf4404696afae4b26be"
"sha": "539977ef0ae039146012b1dac3624e394faa0af9"
},
"homepage": "https://dash0.com/"
},
@@ -1038,7 +1015,7 @@
"source": {
"source": "url",
"url": "https://github.com/astronomer/agents.git",
"sha": "87d780cd5dc85a25c7ceb1f1720031fa4e48f781"
"sha": "5432198caa8ef9ec33218124bcd44016db2d31bf"
},
"homepage": "https://github.com/astronomer/agents"
},
@@ -1062,7 +1039,7 @@
"source": {
"source": "url",
"url": "https://github.com/astronomer/agents.git",
"sha": "87d780cd5dc85a25c7ceb1f1720031fa4e48f781"
"sha": "5432198caa8ef9ec33218124bcd44016db2d31bf"
},
"homepage": "https://github.com/astronomer/agents"
},
@@ -1075,7 +1052,7 @@
"url": "https://github.com/awslabs/agent-plugins.git",
"path": "plugins/databases-on-aws",
"ref": "main",
"sha": "d2822e9483fd03aed5556d4e03dfad6d60eac91b"
"sha": "efe040ab66ed7eb4bccc0a94133181da5bc57567"
},
"homepage": "https://github.com/awslabs/agent-plugins"
},
@@ -1147,7 +1124,7 @@
"source": {
"source": "url",
"url": "https://github.com/datarobot-oss/datarobot-agent-skills.git",
"sha": "d438bb71a6d9cf58bef69cf286966bb218dc386f"
"sha": "c6e70363e41bac72470f755952b04eb7504a0ab0"
},
"homepage": "https://datarobot.com"
},
@@ -1175,7 +1152,7 @@
"source": {
"source": "url",
"url": "https://github.com/confident-ai/deepeval.git",
"sha": "c6293c1201515293541d515a2da1b4de387e2c01"
"sha": "b11bd0e116973b9cf67845bd9f28a1969586f2c7"
},
"homepage": "https://github.com/confident-ai/deepeval"
},
@@ -1306,7 +1283,7 @@
"url": "https://github.com/expo/skills.git",
"path": "plugins/expo",
"ref": "main",
"sha": "8bd359f8a44d2446de12f1fe6e6316daf043056e"
"sha": "dba2a34f0db6aeba1af440da0f93aff916c765bb"
},
"homepage": "https://github.com/expo/skills/blob/main/plugins/expo/README.md"
},
@@ -1343,7 +1320,7 @@
"source": {
"source": "url",
"url": "https://github.com/voxel51/fiftyone-skills.git",
"sha": "8d0ddac468a77314f4f2507c266abcd6bd48c8db"
"sha": "9168c379e357b72ec4f0189359736c8ac5392d17"
},
"homepage": "https://docs.voxel51.com/"
},
@@ -1492,7 +1469,7 @@
"url": "https://github.com/grafana/ai-marketplace.git",
"path": "plugins/grafana-cloud-mcp",
"ref": "main",
"sha": "12be5634a492f73c189d466c5449d09b853ad7a4"
"sha": "a5c72f2d74c640e9675eb0249526447968535015"
},
"homepage": "https://grafana.com"
},
@@ -1531,7 +1508,7 @@
"url": "https://github.com/honeycombio/agent-skill.git",
"path": "honeycomb",
"ref": "main",
"sha": "189553c8a879cfaaf206ba9cc68c1b2117d12a76"
"sha": "53e6bb80242d4667dd730e7cc2150a4a2f9a83bf"
},
"homepage": "https://www.honeycomb.io"
},
@@ -1568,7 +1545,7 @@
"source": {
"source": "url",
"url": "https://github.com/huggingface/skills.git",
"sha": "86cdeee824b73e504198b6005bb113552cdfa7ba"
"sha": "9c8c3e1c96111298bffff71b7ac363524742b76f"
},
"homepage": "https://github.com/huggingface/skills.git"
},
@@ -1582,7 +1559,7 @@
"source": {
"source": "url",
"url": "https://github.com/hunter-io/claude-plugin.git",
"sha": "2a89a5ec3821eb0a4c2eb3412729b154f2ac8ebb"
"sha": "e56a94b2903a7deeb0f4a988700a4015dbf15d42"
},
"homepage": "https://hunter.io"
},
@@ -1596,7 +1573,7 @@
"source": {
"source": "url",
"url": "https://github.com/heygen-com/hyperframes.git",
"sha": "696cbdbbd0e5c83faf72c767126d4a153110f130"
"sha": "b0bb4688777892b27e8c94df964c1699c7a118db"
},
"homepage": "https://hyperframes.heygen.com"
},
@@ -1667,7 +1644,7 @@
"source": "github",
"repo": "jfrog/claude-plugin",
"commit": "259c8e718266c16e99b4f30ae9b1ed0f9f00d98d",
"sha": "11177f6698405976ee0eecbbfb4857ed9657f19f"
"sha": "427d2e68848b2d04df586bd6be4904a5934828fb"
},
"homepage": "https://jfrog.com"
},
@@ -1856,7 +1833,7 @@
"source": {
"source": "url",
"url": "https://github.com/gemini-cli-extensions/looker.git",
"sha": "8ca746f8d6b0079d1f872c96bd3e0530bf4571d3"
"sha": "e05aac7d0287e337ff13cfa3183f39675d67dd97"
},
"homepage": "https://github.com/gemini-cli-extensions/looker"
},
@@ -2069,20 +2046,6 @@
},
"homepage": "https://miro.com"
},
{
"name": "mlflow",
"description": "Skills for tracing, evaluating, and improving AI agents with MLflow. Supports the full agent improvement loop: instrument → trace → evaluate → iterate → validate.",
"author": {
"name": "MLflow Team"
},
"category": "monitoring",
"source": {
"source": "url",
"url": "https://github.com/mlflow/skills.git",
"sha": "c33bb3d303a2c6113bbaed6dbfe756e88e80f1df"
},
"homepage": "https://mlflow.org/"
},
{
"name": "monday-crm",
"description": "Run your monday CRM in plain language. Build a pipeline from scratch, start the day with a ranked deal briefing, spin up a forecast dashboard, audit board health, clean up messy data in bulk, and turn meeting notes into deal updates. Every skill writes back into monday as a real update, doc, or dashboard. Built on the official monday MCP connector.",
@@ -2130,7 +2093,7 @@
"source": {
"source": "url",
"url": "https://github.com/netlify/context-and-tools.git",
"sha": "b4ac277e6795f90e6a1d163c001c0d7667ff9143"
"sha": "48de7a41e3ab0e0381d63d6ad26f78b063754a7b"
},
"homepage": "https://github.com/netlify/context-and-tools"
},
@@ -2160,27 +2123,13 @@
],
"homepage": "https://github.com/oracle/netsuite-suitecloud-sdk"
},
{
"name": "newrelic",
"description": "New Relic observability intelligence for Claude Code. Investigate APM performance, analyze cloud costs, debug Kubernetes, write NRQL queries, and respond to alerts — all from your terminal using New Relic telemetry data.",
"author": {
"name": "New Relic"
},
"category": "monitoring",
"source": {
"source": "url",
"url": "https://github.com/newrelic/claude-code-plugin.git",
"sha": "f8e5f8b62139072a22153ec92de1c0cc1af2f56a"
},
"homepage": "https://newrelic.com"
},
{
"name": "nightvision",
"description": "Skills for working with NightVision, a DAST and API Discovery platform that finds exploitable vulnerabilities in web applications and REST APIs",
"source": {
"source": "url",
"url": "https://github.com/nvsecurity/nightvision-skills.git",
"sha": "928d334e24354161a20f91de39ca60029338ba47"
"sha": "97c72cbcddf51ab2d8387b61c68d5d999fec645e"
},
"homepage": "https://github.com/nvsecurity/nightvision-skills"
},
@@ -2217,7 +2166,7 @@
"url": "https://github.com/NVIDIA/skills.git",
"path": "plugins/nvidia-skills",
"ref": "main",
"sha": "ab94cb3e51d0dcbaffbfb88cbd3e42cae9795dc2"
"sha": "061d42ccc84cdcb64473a43e5f669986a9683bfc"
},
"homepage": "https://github.com/NVIDIA/skills"
},
@@ -2419,7 +2368,7 @@
"source": {
"source": "url",
"url": "https://github.com/PostHog/ai-plugin.git",
"sha": "4bdfca8c6d58b8c9a303374f5f93485b8d9281fa"
"sha": "ffbb25314cb3ee5c998aa6eca0e308bc70f66b85"
},
"homepage": "https://posthog.com/docs/model-context-protocol"
},
@@ -2440,7 +2389,7 @@
"source": {
"source": "url",
"url": "https://github.com/Postman-Devrel/postman-claude-code-plugin.git",
"sha": "b7b3c7a83486ee088844a96278411690523d389f"
"sha": "1c47a9b10170316c4eced15777ab2ac45ffdac80"
},
"homepage": "https://learning.postman.com/docs/developer/postman-mcp-server/"
},
@@ -2501,7 +2450,7 @@
"url": "https://github.com/pydantic/skills.git",
"path": "plugins/ai",
"ref": "main",
"sha": "97f67e13e353a9370b208c7b259dbe7c3768a80b"
"sha": "2ca99fef84cb8603a425bccb1f1456b01e6b1c52"
},
"homepage": "https://github.com/pydantic/skills/tree/main/plugins/ai"
},
@@ -2539,7 +2488,7 @@
"source": {
"source": "url",
"url": "https://github.com/qdrant/skills.git",
"sha": "240854b3068b6a9cd1ebf75ab008b5758071052b"
"sha": "db1dde70ebe3e936d68d64e4f5d801a24362c4d7"
},
"homepage": "https://skills.qdrant.tech"
},
@@ -2578,7 +2527,7 @@
"source": {
"source": "url",
"url": "https://github.com/quarkusio/quarkus-agent-mcp.git",
"sha": "fc71cc709e3262e603c3413cdc243ba78cbd6b5f"
"sha": "82fcfb3d8cdc1663d5151420e1c4f543b99cf275"
},
"homepage": "https://quarkus.io"
},
@@ -2591,7 +2540,7 @@
"url": "https://github.com/railwayapp/railway-skills.git",
"path": "plugins/railway",
"ref": "main",
"sha": "191601b4954527a87f4f004eaa355c8f30a855bf"
"sha": "2405547f2044071c9d43bf6782edeb5d93e5bb4e"
},
"homepage": "https://docs.railway.com/ai/claude-code-plugin"
},
@@ -2620,7 +2569,7 @@
},
{
"name": "receipts",
"description": "A personal Claude Code impact report for justifying your usage to a manager or a self-review: what you shipped, which projects it went to, and each project's share of your usage. Reads your ~/.claude/projects transcripts and runs read-only git locally; only counts and project names are sent to write it up, and the report stays on your machine.",
"description": "Generate a personal Claude Code impact report from your local ~/.claude/projects transcripts, cross-referenced against your local git history — what you shipped, which projects it went to, and each project's share of your usage — for justifying usage to a manager or a self-review. Reads your session transcripts and runs read-only git commands in the projects they mention; mining is local and only a small aggregate summary (counts and project names) is sent to write the report, which is saved to your home directory and published nowhere.",
"author": {
"name": "Anthropic",
"email": "support@anthropic.com"
@@ -2705,7 +2654,7 @@
"source": {
"source": "url",
"url": "https://github.com/rilldata/agent-skills.git",
"sha": "6e5df00631875bc9f1119d5f08194596ad02e8f1"
"sha": "6dffeeee8617aceb796edb744e3c52a7c0ee88ac"
},
"homepage": "https://docs.rilldata.com/developers/build/ai-configuration"
},
@@ -2790,7 +2739,7 @@
"url": "https://github.com/awslabs/agent-plugins.git",
"path": "plugins/sagemaker-ai",
"ref": "main",
"sha": "153b28e3c10de3661b8744b80d72c3a96fcdb0ab"
"sha": "c65ee436b0db77bb75d380aef6fbdc9b114edf2a"
},
"homepage": "https://github.com/awslabs/agent-plugins"
},
@@ -2838,7 +2787,7 @@
"url": "https://github.com/SAP/open-ux-tools.git",
"path": "packages/fiori-mcp-server",
"ref": "main",
"sha": "98cd40f91ba943df42382e5216af9f6f17a1c215"
"sha": "c288dadb279a9bb928f1e5246aac7a62efee1f6f"
},
"homepage": "https://github.com/SAP/open-ux-tools/tree/main/packages/fiori-mcp-server"
},
@@ -2870,7 +2819,7 @@
"source": {
"source": "url",
"url": "https://github.com/SAP/mdk-mcp-server.git",
"sha": "1a42cfc38a2f12cb2be2a98c6604074446b1639e"
"sha": "20f6b5714e9cbd9919622e2bd1211ec956e48e59"
},
"homepage": "https://help.sap.com/docs/MDK"
},
@@ -2886,7 +2835,7 @@
"url": "https://github.com/spotify/save-to-spotify.git",
"path": "plugin",
"ref": "main",
"sha": "9d05c8cd8c8559552f84e27fe30f46b7693ce69a"
"sha": "527321ef64fe04273629f26cee1e9f18805b81ff"
},
"homepage": "https://github.com/spotify/save-to-spotify"
},
@@ -2910,7 +2859,7 @@
"source": "git-subdir",
"url": "https://github.com/semgrep/mcp-marketplace.git",
"path": "plugin",
"sha": "7ae38e4bec51877cec71fcacc5857d746fb8b468"
"sha": "63fac121296f3f102651de6beb7c15649c8b11d3"
},
"homepage": "https://github.com/semgrep/mcp-marketplace.git"
},
@@ -2988,7 +2937,7 @@
"source": {
"source": "url",
"url": "https://github.com/Shopify/Shopify-AI-Toolkit.git",
"sha": "556811e94dd45c795abe5c0b1bf6b5a4b098149d"
"sha": "6980909f2e0eaaf59b4801077fe7e3731bad1b71"
},
"homepage": "https://shopify.dev"
},
@@ -3010,7 +2959,7 @@
"source": {
"source": "url",
"url": "https://github.com/slackapi/slack-mcp-plugin.git",
"sha": "e75b0cf18f1a19f3fd629e3af9565ee84b8c2ce0"
"sha": "46f5c53bf3d37a4b4a3e307edc056bb3572f563e"
},
"homepage": "https://github.com/slackapi/slack-mcp-plugin/tree/main"
},
@@ -3040,7 +2989,7 @@
"source": {
"source": "url",
"url": "https://github.com/SonarSource/sonarqube-agent-plugins.git",
"sha": "0e502ceb9a2083a586ad2b5ad14cd10174243626"
"sha": "5e89beacfb725b547c3a9e4bfdc2380ec1809361"
},
"homepage": "https://www.sonarsource.com"
},
@@ -3087,26 +3036,10 @@
"source": {
"source": "url",
"url": "https://github.com/spotify/ads-claude-plugin.git",
"sha": "9407475a5cd2a3986c48a58020fd47e23f9735e5"
"sha": "aedf7ed87312891ef2e357c02b9c22fcca8907b4"
},
"homepage": "https://github.com/spotify/ads-claude-plugin"
},
{
"name": "stackhawk-api",
"description": "Query the StackHawk platform API for security posture reporting, findings analysis, and app management. Guides agents through authentication, data retrieval, and result presentation.",
"author": {
"name": "StackHawk"
},
"category": "security",
"source": {
"source": "git-subdir",
"url": "https://github.com/stackhawk/agent-skills.git",
"path": "plugins/api",
"ref": "main",
"sha": "248e3fedba8ff80fadfd17f72a0454aa02b66a0b"
},
"homepage": "https://docs.stackhawk.com/ai-security/"
},
{
"name": "stripe",
"description": "Stripe development plugin for Claude",
@@ -3116,7 +3049,7 @@
"url": "https://github.com/stripe/ai.git",
"path": "providers/claude/plugin",
"ref": "main",
"sha": "a3267712f2268975e4ecc5912634d900ae4cb8e6"
"sha": "e238b951665cba5260d70aa80e5021def27a61d3"
},
"homepage": "https://github.com/stripe/ai/tree/main/providers/claude/plugin"
},
@@ -3139,7 +3072,7 @@
"source": {
"source": "url",
"url": "https://github.com/supabase-community/supabase-plugin.git",
"sha": "5d74232687a0a82184ecd4266ea07372edb43f4b"
"sha": "3b3184501844df3d2e0accac129fdcae73f4bf95"
},
"homepage": "https://github.com/supabase-community/supabase-plugin"
},
@@ -3198,7 +3131,7 @@
"source": {
"source": "url",
"url": "https://github.com/JetBrains/teamcity-cli.git",
"sha": "e9bbb01fe7c5b96790f7a60de9c2ee60138a9a6c"
"sha": "880cabdcac732e5f0accfe8f0af37dbd5829ca1b"
},
"homepage": "https://www.jetbrains.com/teamcity/"
},
@@ -3229,7 +3162,7 @@
"source": {
"source": "url",
"url": "https://github.com/togethercomputer/skills.git",
"sha": "7e8626a7d18a3697d5530aa2707abae4134839c5"
"sha": "d53c5f424904d715d27e4dc1bdd64169edb089e7"
},
"homepage": "https://www.together.ai"
},
@@ -3291,7 +3224,7 @@
"url": "https://github.com/UI5/plugins-coding-agents.git",
"path": "plugins/ui5",
"ref": "main",
"sha": "6b2d7f95a739857082fa9cb50bfd5ce8b1163fdc"
"sha": "c61e0b7fc7e38168f1df4f705f54c57e59d44c98"
},
"homepage": "https://github.com/UI5/plugins-coding-agents"
},
@@ -3309,7 +3242,7 @@
"url": "https://github.com/UI5/plugins-coding-agents.git",
"path": "plugins/ui5-modernization",
"ref": "main",
"sha": "6b2d7f95a739857082fa9cb50bfd5ce8b1163fdc"
"sha": "d1e3a43fa80ef160cb42689b88d665e25a5a81a1"
},
"homepage": "https://github.com/UI5/plugins-coding-agents"
},
@@ -3327,7 +3260,7 @@
"url": "https://github.com/UI5/plugins-coding-agents.git",
"path": "plugins/ui5-typescript-conversion",
"ref": "main",
"sha": "6b2d7f95a739857082fa9cb50bfd5ce8b1163fdc"
"sha": "d1e3a43fa80ef160cb42689b88d665e25a5a81a1"
},
"homepage": "https://github.com/UI5/plugins-coding-agents"
},
@@ -3410,7 +3343,7 @@
"source": {
"source": "url",
"url": "https://github.com/explorium-ai/vibeprospecting-plugin.git",
"sha": "1eb655845e2b30a5478747803f364286d60c6332"
"sha": "fcbbd20ca679a776a461d7e5aea3688320dbd63c"
},
"homepage": "https://www.vibeprospecting.ai/product/claude-plugin"
},
@@ -3449,7 +3382,7 @@
"source": {
"source": "url",
"url": "https://github.com/wix/skills.git",
"sha": "bef043f07972401e14fc4b129cf3895417f09352"
"sha": "c54241783c1b9f6d96b81e2c7278b8349d703703"
},
"homepage": "https://dev.wix.com/docs/wix-cli/guides/development/about-wix-skills"
},
@@ -3556,7 +3489,7 @@
"source": {
"source": "url",
"url": "https://github.com/zscaler/zscaler-mcp-server.git",
"sha": "47fe874551023bf8d138c24612aa4ea0f16aaa56"
"sha": "23912913f8588c650b104d3bd30c0c755d6962cd"
},
"homepage": "https://github.com/zscaler/zscaler-mcp-server"
},
@@ -3570,7 +3503,7 @@
"source": {
"source": "url",
"url": "https://github.com/langfuse/skills.git",
"sha": "abe69fac6b0e0df94605dc5ae162da4726d0fb78"
"sha": "02636d5bbe0cbcc8d1392203dfba9c60595a2e93"
},
"homepage": "https://langfuse.com"
},

View File

@@ -19,15 +19,6 @@ on:
# pull_request and the required check would sit "Expected" forever (a dispatch
# check run isn't associated with the PR, so it can't satisfy the gate either).
- '.github/policy/**'
# And once more for a plugin's own docs: a PR that only edits a README or
# adds a screenshot matches nothing above, so the required check never
# reports and the PR can't be merged. Spelled out per level because `*`
# doesn't cross a `/` — plugins live at plugins/<name>/, so `*/README.md`
# would not match one.
- 'plugins/*/README.md'
- 'plugins/*/assets/**'
- 'external_plugins/*/README.md'
- 'external_plugins/*/assets/**'
push:
branches: [main]
paths:

View File

@@ -4,12 +4,6 @@ Generate a personal Claude Code impact report — "receipts" — from your own
session transcripts, for the conversation where someone asks what all this
Claude Code usage is actually buying.
<img src="assets/sample-receipt.png" width="400"
alt="A printed-receipt-styled report headed 'Claude Code — usage receipt, Morgan Lunt', covering 2026-06-21 to 2026-07-20, active on 28 of 30 days. It lists 40 sessions, 64 prompts, 14 files touched, 3,120 lines touched, 12 commits carrying that work and 7 PRs opened, headlined as 19 commits and PRs shipped. A by-project table gives 'Research and investigation (no project)' 53% of spend with no files touched, then acme-api 29%, acme-web 10%, billing-service 5%, infra-terraform 3%, and a plain ~/notes directory 1%. Footnotes explain which columns do not sum, and an Export CSV button sits above a barcode.">
*Sample output — the projects and numbers are invented. It's rendered from a
synthetic corpus, not from anyone's real usage.*
## Install
```

View File

@@ -1,183 +0,0 @@
// make-sample.mjs — regenerate assets/sample-receipt.png for the README.
//
// The README's sample must never contain anyone's real projects, so it isn't a
// screenshot of a real run. This builds a throwaway HOME with invented repos,
// invented files and invented sessions, then points the real miner at it — the
// picture is genuinely what the tool produces, from data that never existed.
//
// node assets/make-sample.mjs ~/receipts-sample
// HOME=~/receipts-sample/home node skills/receipts/scripts/mine-transcripts.mjs \
// --days 30 --html /tmp/sample.html
// # screenshot /tmp/sample.html at 620px wide, crop to the receipt
//
// Build it somewhere with no symlink above it — NOT /tmp, which on macOS is a
// symlink to /private/tmp. `git rev-parse --show-toplevel` resolves symlinks
// and these transcripts don't, so under /tmp every repo reports zero commits
// and the sample comes out silently wrong.
//
// Keep the invented names obviously fake (acme-*, example.com).
import fs from 'node:fs';
import path from 'node:path';
import { execFileSync } from 'node:child_process';
const ROOT = process.argv[2];
const HOME = path.join(ROOT, 'home');
fs.rmSync(ROOT, { recursive: true, force: true });
const NAME = 'Morgan Lunt';
const EMAIL = 'morgan@example.com';
const git = (cwd, ...a) => execFileSync('git', ['-C', cwd, ...a], { stdio: ['ignore', 'pipe', 'ignore'] });
// --- invented projects -------------------------------------------------------
const REPOS = {
'acme-api': ['src/routes/orders.ts', 'src/routes/refunds.ts', 'src/db/schema.sql', 'src/lib/auth.ts', 'tests/orders.test.ts'],
'acme-web': ['app/checkout/page.tsx', 'app/cart/state.ts', 'components/PriceTag.tsx'],
'billing-service': ['internal/invoice/render.go', 'internal/tax/rates.go'],
'infra-terraform': ['envs/prod/main.tf', 'modules/rds/variables.tf'],
};
const NOTES = ['migration-plan.md', 'oncall-runbook.md'];
fs.mkdirSync(path.join(HOME, 'notes'), { recursive: true });
fs.writeFileSync(path.join(HOME, '.gitconfig'), `[user]\n\tname = ${NAME}\n\temail = ${EMAIL}\n`);
for (const f of NOTES) fs.writeFileSync(path.join(HOME, 'notes', f), 'note\n'.repeat(40));
for (const [repo, files] of Object.entries(REPOS)) {
const dir = path.join(HOME, 'code', repo);
fs.mkdirSync(dir, { recursive: true });
git(dir, 'init', '-q', '-b', 'main');
git(dir, 'config', 'user.name', NAME);
git(dir, 'config', 'user.email', EMAIL);
git(dir, 'config', 'commit.gpgsign', 'false');
for (const f of files) {
fs.mkdirSync(path.dirname(path.join(dir, f)), { recursive: true });
fs.writeFileSync(path.join(dir, f), 'x\n'.repeat(60));
}
git(dir, 'add', '-A');
git(dir, 'commit', '-qm', 'initial');
}
// --- invented transcripts ----------------------------------------------------
const PROJ = path.join(HOME, '.claude', 'projects', 'sample');
fs.mkdirSync(PROJ, { recursive: true });
let uid = 0;
const U = () => `u${++uid}`;
const day = (back) => {
const d = new Date();
d.setDate(d.getDate() - back);
d.setHours(10 + (back % 6), 15, 0, 0);
return d.toISOString();
};
const usage = (out) => ({
input_tokens: 900,
output_tokens: out,
cache_creation: { ephemeral_5m_input_tokens: 4000, ephemeral_1h_input_tokens: 0 },
cache_read_input_tokens: 30000,
});
const asst = (sid, ts, cwd, blocks, out = 300) => ({
type: 'assistant', sessionId: sid, uuid: U(), requestId: `r${uid}`, timestamp: ts, cwd,
message: { usage: usage(out), content: blocks },
});
const user = (sid, ts, cwd, text) => ({
type: 'user', sessionId: sid, uuid: U(), promptId: `p${uid}`, timestamp: ts, cwd,
message: { content: text },
});
const tool = (name, input) => ({ type: 'tool_use', id: `t${++uid}`, name, input });
// One .jsonl per session, the way Claude Code actually lays them out.
const bySession = new Map();
const emit = (o) => {
const k = o.sessionId;
if (!bySession.has(k)) bySession.set(k, []);
bySession.get(k).push(JSON.stringify(o));
};
// Sessions that build things, spread across the invented repos.
const plan = [
{ repo: 'acme-api', sessions: 9, daysBack: [2, 3, 5, 6, 9, 12, 16, 20, 24], edits: 5, writes: 2 },
{ repo: 'acme-web', sessions: 5, daysBack: [4, 7, 11, 18, 22], edits: 3, writes: 1 },
{ repo: 'billing-service', sessions: 3, daysBack: [8, 15, 26], edits: 2, writes: 1 },
{ repo: 'infra-terraform', sessions: 2, daysBack: [13, 19], edits: 2, writes: 0 },
];
let sid = 0;
for (const p of plan) {
const dir = path.join(HOME, 'code', p.repo);
const files = REPOS[p.repo];
for (let i = 0; i < p.sessions; i++) {
const S = `s-${p.repo}-${++sid}`;
const ts = day(p.daysBack[i % p.daysBack.length]);
emit(user(S, ts, dir, 'add the thing'));
for (let e = 0; e < p.edits; e++) {
const f = path.join(dir, files[e % files.length]);
emit(asst(S, ts, dir, [tool('Read', { file_path: f })], 120));
emit(asst(S, ts, dir, [tool('Edit', { file_path: f, old_string: 'x\n'.repeat(9), new_string: 'y\n'.repeat(14) })], 400));
}
for (let w = 0; w < p.writes; w++) {
const f = path.join(dir, files[(w + 1) % files.length]);
emit(asst(S, ts, dir, [tool('Write', { file_path: f, content: 'z\n'.repeat(70) })], 700));
}
emit(asst(S, ts, dir, [tool('Bash', { command: 'npm test' })], 200));
if (i % 3 === 0) {
emit(user(S, ts, dir, 'open the PR'));
emit(asst(S, ts, dir, [tool('Bash', { command: 'gh pr create --fill' })], 150));
}
}
}
// Work in a plain directory — no repo.
for (let i = 0; i < 4; i++) {
const S = `s-notes-${i}`;
const ts = day([6, 10, 17, 23][i]);
const dir = path.join(HOME, 'notes');
emit(user(S, ts, dir, 'draft the migration plan'));
emit(asst(S, ts, dir, [tool('Write', { file_path: path.join(dir, NOTES[i % 2]), content: 'n\n'.repeat(55) })], 900));
}
// Research: no files touched, not in a repo. The row that surprises people.
for (let i = 0; i < 17; i++) {
const S = `s-res-${i}`;
const ts = day([1, 2, 3, 5, 7, 8, 9, 11, 12, 14, 16, 18, 20, 21, 25, 27, 28][i]);
emit(user(S, ts, HOME, 'what changed in the pricing API?'));
for (let k = 0; k < 6; k++) {
emit(asst(S, ts, HOME, [tool('WebFetch', { url: 'https://example.com/docs' })], 350));
emit(asst(S, ts, HOME, [tool('WebSearch', { query: 'pricing api changelog' })], 250));
}
emit(user(S, ts, HOME, 'and the rate limits?'));
emit(asst(S, ts, HOME, [tool('WebFetch', { url: 'https://example.com/limits' })], 400));
}
for (const [k, ls] of bySession) fs.writeFileSync(path.join(PROJ, `${k}.jsonl`), ls.join('\n') + '\n');
// --- commits carrying that work ---------------------------------------------
const COMMITS = {
'acme-api': [
['src/routes/orders.ts', 'orders: handle partial refunds', 2],
['src/lib/auth.ts', 'auth: rotate signing keys', 5],
['src/db/schema.sql', 'schema: add refund_reason', 9],
['tests/orders.test.ts', 'tests: cover partial refunds', 16],
],
'acme-web': [
['app/checkout/page.tsx', 'checkout: inline tax breakdown', 4],
['app/cart/state.ts', 'cart: fix stale totals', 11],
],
'billing-service': [['internal/invoice/render.go', 'invoice: round to minor units', 8]],
'infra-terraform': [['envs/prod/main.tf', 'prod: bump rds instance class', 13]],
};
// Date each commit to the day the session that produced it ran, so the
// "N of your M active days ended in a commit" line reflects a real rhythm
// rather than a fixture written all at once.
for (const [repo, cs] of Object.entries(COMMITS)) {
const dir = path.join(HOME, 'code', repo);
for (const [f, msg, back] of cs) {
fs.appendFileSync(path.join(dir, f), 'changed\n');
const when = day(back);
execFileSync('git', ['-C', dir, 'add', '-A'], { stdio: 'ignore' });
execFileSync('git', ['-C', dir, 'commit', '-qm', msg], {
stdio: 'ignore',
env: { ...process.env, GIT_AUTHOR_DATE: when, GIT_COMMITTER_DATE: when },
});
}
}
console.log(HOME);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB