@kerrshift/agentdiff 0.0.0-stage → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +27 -2
  2. package/bin/agentdiff.js +113 -0
  3. package/package.json +35 -4
package/README.md CHANGED
@@ -1,3 +1,28 @@
1
- # Temporary Holding Version
1
+ # @kerrshift/agentdiff
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **See what your AI coding agent actually did, and what it cost.**
4
+
5
+ ```bash
6
+ npx @kerrshift/agentdiff
7
+ ```
8
+
9
+ Reads the Claude Code session logs already on your machine and shows where the
10
+ money went and what was avoidable: long context re-sent every turn, prompt
11
+ caches rebuilt after breaks, stuck retries. No config, no API key, nothing
12
+ uploaded.
13
+
14
+ ```bash
15
+ npx @kerrshift/agentdiff --since 30d # 24h, 7d, 30d, 12w … or all
16
+ npx @kerrshift/agentdiff --project api # only projects whose name contains "api"
17
+ npx @kerrshift/agentdiff --json # machine-readable
18
+ ```
19
+
20
+ Install it with `npm i -g @kerrshift/agentdiff`; the command is `agentdiff`.
21
+
22
+ This npm package is a thin launcher for the Python CLI
23
+ ([`agent-trajectory-diff`](https://pypi.org/project/agent-trajectory-diff/))
24
+ at the same version. It uses `uvx` if you have uv, else `pipx`, else builds a
25
+ private virtualenv once with any Python 3.10+.
26
+
27
+ Docs and the Claude Code plugin: [agentdiff.app](https://agentdiff.app) ·
28
+ [GitHub](https://github.com/kerrshift/agentdiff). MIT licensed.
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env node
2
+ // `npx @kerrshift/agentdiff` — runs the AgentDiff Python CLI (PyPI: agent-trajectory-diff)
3
+ // at the same version as this npm package, using whichever Python runner the
4
+ // machine already has: uvx, then pipx, then a private virtualenv built once
5
+ // with any Python 3.10+. No runtime dependencies.
6
+ "use strict";
7
+
8
+ const { spawnSync } = require("node:child_process");
9
+ const fs = require("node:fs");
10
+ const os = require("node:os");
11
+ const path = require("node:path");
12
+
13
+ const { version } = require("../package.json");
14
+
15
+ const SPEC = `agent-trajectory-diff==${version}`;
16
+ const IS_WIN = process.platform === "win32";
17
+
18
+ function which(cmd) {
19
+ const exts = IS_WIN ? (process.env.PATHEXT || ".EXE;.CMD;.BAT").split(";") : [""];
20
+ for (const dir of (process.env.PATH || "").split(path.delimiter)) {
21
+ if (!dir) continue;
22
+ for (const ext of exts) {
23
+ const candidate = path.join(dir, cmd + ext);
24
+ try {
25
+ if (fs.statSync(candidate).isFile()) {
26
+ fs.accessSync(candidate, fs.constants.X_OK);
27
+ return candidate;
28
+ }
29
+ } catch {
30
+ // not here
31
+ }
32
+ }
33
+ }
34
+ return null;
35
+ }
36
+
37
+ function run(cmd, args) {
38
+ const result = spawnSync(cmd, args, { stdio: "inherit" });
39
+ if (result.error) {
40
+ console.error(`agentdiff: could not start ${cmd}: ${result.error.message}`);
41
+ return 1;
42
+ }
43
+ if (result.signal) process.kill(process.pid, result.signal);
44
+ return result.status ?? 1;
45
+ }
46
+
47
+ function quiet(cmd, args) {
48
+ const result = spawnSync(cmd, args, { stdio: "ignore" });
49
+ return result.error ? 1 : result.status ?? 1;
50
+ }
51
+
52
+ function findPython() {
53
+ for (const name of ["python3", "python"]) {
54
+ const exe = which(name);
55
+ if (exe && quiet(exe, ["-c", "import sys; sys.exit(sys.version_info < (3, 10))"]) === 0) {
56
+ return exe;
57
+ }
58
+ }
59
+ return null;
60
+ }
61
+
62
+ function cacheDir() {
63
+ if (process.env.AGENTDIFF_CACHE_DIR) return process.env.AGENTDIFF_CACHE_DIR;
64
+ if (IS_WIN) {
65
+ return path.join(process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local"), "agentdiff");
66
+ }
67
+ return path.join(process.env.XDG_CACHE_HOME || path.join(os.homedir(), ".cache"), "agentdiff");
68
+ }
69
+
70
+ function viaVirtualenv(python, args) {
71
+ const venv = path.join(cacheDir(), `venv-${version}`);
72
+ const binDir = path.join(venv, IS_WIN ? "Scripts" : "bin");
73
+ const agentdiff = path.join(binDir, IS_WIN ? "agentdiff.exe" : "agentdiff");
74
+ if (!fs.existsSync(agentdiff)) {
75
+ console.error(`Setting up AgentDiff ${version} in ${venv} (first run only)...`);
76
+ const venvPython = path.join(binDir, IS_WIN ? "python.exe" : "python");
77
+ if (
78
+ quiet(python, ["-m", "venv", venv]) !== 0 ||
79
+ quiet(venvPython, ["-m", "pip", "install", "--quiet", SPEC]) !== 0
80
+ ) {
81
+ console.error(`agentdiff: could not install ${SPEC} with ${python}.`);
82
+ console.error(`Try: pip install "${SPEC}"`);
83
+ return 1;
84
+ }
85
+ }
86
+ return run(agentdiff, args);
87
+ }
88
+
89
+ function main(args) {
90
+ const uvx = which("uvx");
91
+ if (uvx) return run(uvx, ["-q", "--from", SPEC, "agentdiff", ...args]);
92
+
93
+ const pipx = which("pipx");
94
+ if (pipx) {
95
+ // Warm pipx's cache silently so its setup chatter stays out of the output.
96
+ quiet(pipx, ["run", "--spec", SPEC, "agentdiff", "--help"]);
97
+ return run(pipx, ["run", "--spec", SPEC, "agentdiff", ...args]);
98
+ }
99
+
100
+ const python = findPython();
101
+ if (python) return viaVirtualenv(python, args);
102
+
103
+ console.error(
104
+ [
105
+ "agentdiff needs Python 3.10+ (or uv) and none was found.",
106
+ " uv: https://docs.astral.sh/uv/getting-started/installation/",
107
+ " Python: https://www.python.org/downloads/",
108
+ ].join("\n"),
109
+ );
110
+ return 1;
111
+ }
112
+
113
+ process.exitCode = main(process.argv.slice(2));
package/package.json CHANGED
@@ -1,6 +1,37 @@
1
1
  {
2
2
  "name": "@kerrshift/agentdiff",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.7.0",
4
+ "description": "See what your AI coding agent actually did, and what it cost. Local spend report for Claude Code sessions.",
5
+ "keywords": [
6
+ "claude-code",
7
+ "cost",
8
+ "usage",
9
+ "tokens",
10
+ "prompt-caching",
11
+ "ai-agents",
12
+ "cli"
13
+ ],
14
+ "homepage": "https://agentdiff.app",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/kerrshift/agentdiff.git",
18
+ "directory": "npm"
19
+ },
20
+ "bugs": "https://github.com/kerrshift/agentdiff/issues",
21
+ "license": "MIT",
22
+ "bin": {
23
+ "agentdiff": "bin/agentdiff.js"
24
+ },
25
+ "files": [
26
+ "bin"
27
+ ],
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "engines": {
32
+ "node": ">=18"
33
+ },
34
+ "scripts": {
35
+ "test": "node --test test/*.test.js"
36
+ }
37
+ }