token-diet-cli 0.1.0__py3-none-any.whl

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.
token_diet/__init__.py ADDED
@@ -0,0 +1,38 @@
1
+ """
2
+ token-diet: Diagnostic tools and methodology to audit and optimize token footprint in AI coding workflows.
3
+ """
4
+
5
+ from token_diet.cli import (
6
+ estimate_tokens,
7
+ audit_file,
8
+ detect_local_prompts,
9
+ audit_git_hooks,
10
+ fix_git_hooks,
11
+ classify_size,
12
+ resolve_target_paths,
13
+ audit_known_prompts,
14
+ summarize_footprint,
15
+ main,
16
+ DEFAULT_PROMPT_PATHS,
17
+ LOCAL_PROMPT_CANDIDATES,
18
+ THRESHOLD_WARN_BYTES,
19
+ THRESHOLD_ALERT_BYTES,
20
+ )
21
+
22
+ __version__ = "0.1.0"
23
+ __all__ = [
24
+ "estimate_tokens",
25
+ "audit_file",
26
+ "detect_local_prompts",
27
+ "audit_git_hooks",
28
+ "fix_git_hooks",
29
+ "classify_size",
30
+ "resolve_target_paths",
31
+ "audit_known_prompts",
32
+ "summarize_footprint",
33
+ "main",
34
+ "DEFAULT_PROMPT_PATHS",
35
+ "LOCAL_PROMPT_CANDIDATES",
36
+ "THRESHOLD_WARN_BYTES",
37
+ "THRESHOLD_ALERT_BYTES",
38
+ ]
token_diet/__main__.py ADDED
@@ -0,0 +1,4 @@
1
+ from token_diet.cli import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
token_diet/cli.py ADDED
@@ -0,0 +1,449 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ cli.py
4
+
5
+ Core diagnostic logic to inspect, quantify, and audit token and byte footprint
6
+ of prompt directives, project files, and system configurations with automated alerts.
7
+ """
8
+
9
+ import os
10
+ import sys
11
+ import json
12
+ import argparse
13
+ from typing import List, Dict, Any, Optional, Tuple
14
+
15
+ DEFAULT_PROMPT_PATHS = [
16
+ os.path.expanduser("~/.codex/AGENTS.md"),
17
+ os.path.expanduser("~/.codex/engram-instructions.md"),
18
+ os.path.expanduser("~/.codex/engram-compact-prompt.md"),
19
+ os.path.expanduser("~/.claude/CLAUDE.md"),
20
+ os.path.expanduser("~/.gemini/GEMINI.md"),
21
+ os.path.expanduser("~/.gemini/system.md"),
22
+ os.path.expanduser("~/.config/opencode/AGENTS.md"),
23
+ ]
24
+
25
+ LOCAL_PROMPT_CANDIDATES = [
26
+ "AGENTS.md",
27
+ "CLAUDE.md",
28
+ "GEMINI.md",
29
+ ".cursorrules",
30
+ ".windsurfrules",
31
+ ".clinerules",
32
+ ".github/copilot-instructions.md",
33
+ ]
34
+
35
+ # Size thresholds in bytes
36
+ THRESHOLD_WARN_BYTES = 4_000 # ~1,000 tokens
37
+ THRESHOLD_ALERT_BYTES = 16_000 # ~4,000 tokens
38
+
39
+
40
+ def supports_color() -> bool:
41
+ """Returns True if the running terminal supports ANSI color codes."""
42
+ if os.environ.get("NO_COLOR") or not sys.stdout.isatty():
43
+ return False
44
+ return True
45
+
46
+
47
+ def colorize(text: str, color_code: str) -> str:
48
+ """Applies ANSI color code if terminal supports color."""
49
+ if not supports_color():
50
+ return text
51
+ return f"\033[{color_code}m{text}\033[0m"
52
+
53
+
54
+ def green(text: str) -> str:
55
+ return colorize(text, "92")
56
+
57
+
58
+ def yellow(text: str) -> str:
59
+ return colorize(text, "93")
60
+
61
+
62
+ def red(text: str) -> str:
63
+ return colorize(text, "91")
64
+
65
+
66
+ def bold(text: str) -> str:
67
+ return colorize(text, "1")
68
+
69
+
70
+ def estimate_tokens(char_count: int) -> int:
71
+ """Estimates tokens based on a conservative heuristic of ~4 characters per token."""
72
+ if char_count <= 0:
73
+ return 0
74
+ return char_count // 4
75
+
76
+
77
+ def classify_size(size_bytes: int) -> Tuple[str, str]:
78
+ """Returns (status_label, severity) based on byte size."""
79
+ if size_bytes > THRESHOLD_ALERT_BYTES:
80
+ return "ALERT", "critical"
81
+ elif size_bytes > THRESHOLD_WARN_BYTES:
82
+ return "WARN", "warning"
83
+ return "OK", "optimal"
84
+
85
+
86
+ def audit_file(filepath: str) -> Dict[str, Any]:
87
+ """Inspects a file and returns its size in bytes, estimated tokens, and health status."""
88
+ if not os.path.exists(filepath):
89
+ return {
90
+ "path": filepath,
91
+ "exists": False,
92
+ "bytes": 0,
93
+ "estimated_tokens": 0,
94
+ "status": "MISSING",
95
+ "severity": "none",
96
+ }
97
+ try:
98
+ size = os.path.getsize(filepath)
99
+ tokens = estimate_tokens(size)
100
+ status, severity = classify_size(size)
101
+ return {
102
+ "path": filepath,
103
+ "exists": True,
104
+ "bytes": size,
105
+ "estimated_tokens": tokens,
106
+ "status": status,
107
+ "severity": severity,
108
+ }
109
+ except Exception as e:
110
+ return {
111
+ "path": filepath,
112
+ "exists": False,
113
+ "error": str(e),
114
+ "bytes": 0,
115
+ "estimated_tokens": 0,
116
+ "status": "ERROR",
117
+ "severity": "critical",
118
+ }
119
+
120
+
121
+ def detect_local_prompts(base_dir: str = ".") -> List[str]:
122
+ """Detects standard AI agent directive files in the given directory."""
123
+ found: List[str] = []
124
+ abs_base = os.path.abspath(base_dir)
125
+
126
+ for candidate in LOCAL_PROMPT_CANDIDATES:
127
+ p = os.path.join(abs_base, candidate)
128
+ if os.path.isfile(p):
129
+ found.append(p)
130
+
131
+ # Check .cursor/rules directory if it exists
132
+ cursor_rules_dir = os.path.join(abs_base, ".cursor", "rules")
133
+ if os.path.isdir(cursor_rules_dir):
134
+ for root, _, files in os.walk(cursor_rules_dir):
135
+ for f in sorted(files):
136
+ if f.endswith((".md", ".mdc", ".txt")):
137
+ found.append(os.path.join(root, f))
138
+
139
+ return found
140
+
141
+
142
+ def audit_git_hooks(repo_dir: str = ".") -> List[Dict[str, Any]]:
143
+ """Inspects .git/hooks for automated scripts that may silently trigger LLM calls."""
144
+ alerts: List[Dict[str, Any]] = []
145
+ hook_path = os.path.join(os.path.abspath(repo_dir), ".git", "hooks", "pre-commit")
146
+
147
+ if not os.path.exists(hook_path):
148
+ return alerts
149
+
150
+ try:
151
+ keywords = ["gga", "opencode", "gentle-ai", "claude", "gemini", "ollama", "llm review"]
152
+ matched = []
153
+ with open(hook_path, "r", encoding="utf-8", errors="ignore") as f:
154
+ for line in f:
155
+ stripped = line.strip()
156
+ if stripped.startswith("#"):
157
+ continue
158
+ lower_line = stripped.lower()
159
+ for k in keywords:
160
+ if k in lower_line and k not in matched:
161
+ matched.append(k)
162
+
163
+ if matched:
164
+ alerts.append({
165
+ "hook": "pre-commit",
166
+ "path": hook_path,
167
+ "severity": "critical",
168
+ "matched_patterns": matched,
169
+ "message": (
170
+ f"Pre-commit hook invokes AI/LLM review tooling ({', '.join(matched)}). "
171
+ "This causes invisible token consumption on every commit."
172
+ ),
173
+ })
174
+ except Exception as e:
175
+ alerts.append({
176
+ "hook": "pre-commit",
177
+ "path": hook_path,
178
+ "severity": "warning",
179
+ "error": str(e),
180
+ "message": f"Could not inspect pre-commit hook: {e}",
181
+ })
182
+
183
+ return alerts
184
+
185
+
186
+ def fix_git_hooks(repo_dir: str = ".") -> Dict[str, Any]:
187
+ """
188
+ Safely neutralizes unmonitored AI/LLM invocations in .git/hooks/pre-commit:
189
+ 1. Creates a backup copy at .git/hooks/pre-commit.bak.
190
+ 2. Comments out lines that invoke matched AI review keywords.
191
+ 3. Preserves original executable file permissions.
192
+ """
193
+ hook_path = os.path.join(os.path.abspath(repo_dir), ".git", "hooks", "pre-commit")
194
+ if not os.path.exists(hook_path):
195
+ return {
196
+ "fixed": False,
197
+ "hook_path": hook_path,
198
+ "backup_path": None,
199
+ "disabled_count": 0,
200
+ "message": "No pre-commit hook found in .git/hooks/",
201
+ }
202
+
203
+ keywords = ["gga", "opencode", "gentle-ai", "claude", "gemini", "ollama", "llm review"]
204
+ try:
205
+ with open(hook_path, "r", encoding="utf-8", errors="ignore") as f:
206
+ lines = f.readlines()
207
+
208
+ modified_lines = []
209
+ disabled_count = 0
210
+ for line in lines:
211
+ stripped = line.strip()
212
+ # Preserve already-commented lines
213
+ if stripped.startswith("#"):
214
+ modified_lines.append(line)
215
+ continue
216
+
217
+ lower_line = line.lower()
218
+ if any(k in lower_line for k in keywords):
219
+ modified_lines.append(f"# [token-diet disabled]: {line}")
220
+ disabled_count += 1
221
+ else:
222
+ modified_lines.append(line)
223
+
224
+ if disabled_count == 0:
225
+ return {
226
+ "fixed": False,
227
+ "hook_path": hook_path,
228
+ "backup_path": None,
229
+ "disabled_count": 0,
230
+ "message": "No irregular AI hooks detected to disable in .git/hooks/pre-commit",
231
+ }
232
+
233
+ backup_path = hook_path + ".bak"
234
+ with open(backup_path, "w", encoding="utf-8") as f:
235
+ f.writelines(lines)
236
+
237
+ mode = os.stat(hook_path).st_mode
238
+ with open(hook_path, "w", encoding="utf-8") as f:
239
+ f.writelines(modified_lines)
240
+ os.chmod(hook_path, mode)
241
+
242
+ return {
243
+ "fixed": True,
244
+ "hook_path": hook_path,
245
+ "backup_path": backup_path,
246
+ "disabled_count": disabled_count,
247
+ "message": f"Successfully neutralized {disabled_count} AI invocation(s). Backup saved to {backup_path}",
248
+ }
249
+ except Exception as e:
250
+ return {
251
+ "fixed": False,
252
+ "hook_path": hook_path,
253
+ "backup_path": None,
254
+ "disabled_count": 0,
255
+ "error": str(e),
256
+ "message": f"Failed to fix pre-commit hook: {e}",
257
+ }
258
+
259
+
260
+ def resolve_target_paths(input_paths: Optional[List[str]] = None, check_local: bool = True) -> List[str]:
261
+ """Resolves file paths, expanding directories recursively or defaulting to local/global prompts."""
262
+ if input_paths:
263
+ resolved: List[str] = []
264
+ for p in input_paths:
265
+ expanded = os.path.abspath(os.path.expanduser(p))
266
+ if os.path.isdir(expanded):
267
+ for root, _, files in os.walk(expanded):
268
+ for f in sorted(files):
269
+ if not f.startswith("."):
270
+ resolved.append(os.path.join(root, f))
271
+ else:
272
+ resolved.append(expanded)
273
+ return resolved
274
+
275
+ if check_local:
276
+ local_files = detect_local_prompts(".")
277
+ if local_files:
278
+ return local_files
279
+
280
+ return DEFAULT_PROMPT_PATHS
281
+
282
+
283
+ def audit_known_prompts(custom_paths: Optional[List[str]] = None, check_local: bool = True) -> List[Dict[str, Any]]:
284
+ """Audits target paths and returns itemized results."""
285
+ paths = resolve_target_paths(custom_paths, check_local=check_local)
286
+ return [audit_file(p) for p in paths]
287
+
288
+
289
+ def summarize_footprint(results: List[Dict[str, Any]], hook_alerts: Optional[List[Dict[str, Any]]] = None) -> Dict[str, Any]:
290
+ """Calculates aggregate footprint summary, status totals, and health indicators."""
291
+ total_bytes = sum(r.get("bytes", 0) for r in results)
292
+ total_tokens = sum(r.get("estimated_tokens", 0) for r in results)
293
+ files_found = sum(1 for r in results if r.get("exists"))
294
+ alert_count = sum(1 for r in results if r.get("status") == "ALERT")
295
+ warn_count = sum(1 for r in results if r.get("status") == "WARN")
296
+
297
+ if hook_alerts:
298
+ alert_count += len([h for h in hook_alerts if h.get("severity") == "critical"])
299
+
300
+ overall_status = "HEALTHY"
301
+ if alert_count > 0:
302
+ overall_status = "CRITICAL_BLOAT"
303
+ elif warn_count > 0:
304
+ overall_status = "WARNING_MODERATE"
305
+
306
+ return {
307
+ "total_bytes": total_bytes,
308
+ "total_tokens": total_tokens,
309
+ "files_found": files_found,
310
+ "total_checked": len(results),
311
+ "alerts": alert_count,
312
+ "warnings": warn_count,
313
+ "status": overall_status,
314
+ }
315
+
316
+
317
+ def main():
318
+ parser = argparse.ArgumentParser(
319
+ prog="token-diet",
320
+ description="Audit token footprint and detect silent context leaks in AI agent workflows.",
321
+ )
322
+ parser.add_argument(
323
+ "paths",
324
+ nargs="*",
325
+ help="Optional files or directories to inspect. Defaults to auto-detecting project files in CWD or global prompts.",
326
+ )
327
+ parser.add_argument(
328
+ "--global",
329
+ dest="global_only",
330
+ action="store_true",
331
+ help="Inspect global assistant prompts (~/.claude, ~/.codex, ~/.gemini) instead of local project files.",
332
+ )
333
+ parser.add_argument(
334
+ "--json",
335
+ action="store_true",
336
+ help="Output structured JSON payload.",
337
+ )
338
+ parser.add_argument(
339
+ "--max-tokens",
340
+ type=int,
341
+ metavar="N",
342
+ help="Exit with code 1 if total estimated tokens exceed N (useful for CI/CD gates).",
343
+ )
344
+ parser.add_argument(
345
+ "--strict",
346
+ action="store_true",
347
+ help="Exit with code 1 if any alert or warning threshold is exceeded.",
348
+ )
349
+ parser.add_argument(
350
+ "--fix-hooks",
351
+ action="store_true",
352
+ help="Automatically neutralize unmonitored AI review invocations in .git/hooks/pre-commit (creates .bak backup).",
353
+ )
354
+ args = parser.parse_args()
355
+
356
+ if args.fix_hooks:
357
+ fix_result = fix_git_hooks(".")
358
+ if args.json:
359
+ print(json.dumps({"fix_hooks": fix_result}, indent=2))
360
+ else:
361
+ if fix_result["fixed"]:
362
+ print(green(bold("🛠️ AUTO-REMEDIATION: PRE-COMMIT HOOKS NEUTRALIZED")))
363
+ print(f" • Backup saved: {fix_result['backup_path']}")
364
+ print(f" • Neutralized {fix_result['disabled_count']} AI review invocation(s).")
365
+ print(" • Safe pre-commit hook is active without silent token bleed.")
366
+ else:
367
+ print(yellow(f"ℹ️ {fix_result['message']}"))
368
+ return
369
+
370
+ check_local = not args.global_only
371
+ targets = args.paths if args.paths else None
372
+
373
+ # Detect git hooks in current working directory
374
+ hook_alerts = audit_git_hooks(".") if check_local and not targets else []
375
+
376
+ results = audit_known_prompts(targets, check_local=check_local)
377
+ summary = summarize_footprint(results, hook_alerts)
378
+
379
+ if args.json:
380
+ payload = {
381
+ "summary": summary,
382
+ "hook_alerts": hook_alerts,
383
+ "details": results,
384
+ }
385
+ print(json.dumps(payload, indent=2))
386
+ _check_exit_conditions(summary, args.max_tokens, args.strict)
387
+ return
388
+
389
+ # Terminal Output
390
+ print(bold("=" * 80))
391
+ print(bold("TOKEN DIET: FOOTPRINT & CONTEXT AUDIT"))
392
+ print(bold("=" * 80))
393
+ print(f'{"File / Directive":<46} | {"Bytes":>9} | {"Tokens":>9} | {"Status":>8}')
394
+ print("-" * 80)
395
+
396
+ for r in results:
397
+ status_path = r["path"]
398
+ if len(status_path) > 44:
399
+ status_path = "..." + status_path[-41:]
400
+
401
+ if not r["exists"]:
402
+ status_str = colorize("(missing)", "90")
403
+ print(f'{status_path:<46} | {"-":>9} | {"-":>9} | {status_str:>8}')
404
+ else:
405
+ status = r["status"]
406
+ if status == "ALERT":
407
+ badge = red("[ALERT]")
408
+ elif status == "WARN":
409
+ badge = yellow("[WARN]")
410
+ else:
411
+ badge = green("[OK]")
412
+
413
+ print(f'{status_path:<46} | {r["bytes"]:>9,d} | {r["estimated_tokens"]:>9,d} | {badge:>17}')
414
+
415
+ print(bold("=" * 80))
416
+ print(f"Total Bytes: {summary['total_bytes']:,d} B")
417
+ print(f"Total Tokens: ~{summary['total_tokens']:,d} estimated base tokens per turn")
418
+ print(f"Files Detected: {summary['files_found']} of {summary['total_checked']}")
419
+
420
+ # Print Hook Alerts if any
421
+ if hook_alerts:
422
+ print("\n" + red(bold("🚨 IRREGULAR HOOK DETECTED:")))
423
+ for h in hook_alerts:
424
+ print(red(f" • [{h['hook']}] {h['message']}"))
425
+ print(f" Path: {h['path']}")
426
+ print(colorize(" 💡 Tip: Run 'token-diet --fix-hooks' to automatically neutralize silent AI invocations.", "96"))
427
+
428
+ # Print Recommendations if bloated
429
+ if summary["alerts"] > 0:
430
+ print("\n" + red(bold("⚠️ CONTEXT BLOAT DETECTED:")))
431
+ print(" Files marked [ALERT] exceed 16 KB (>4k tokens) and severely penalize context windows.")
432
+ print(" Recommendation: Decouple procedures into On-Demand Skills using the LUT Router pattern.")
433
+ elif summary["warnings"] > 0:
434
+ print("\n" + yellow("ℹ️ MODERATE CONTEXT SIZE:"))
435
+ print(" Files marked [WARN] exceed 4 KB. Review if non-essential sections can be pruned.")
436
+
437
+ _check_exit_conditions(summary, args.max_tokens, args.strict)
438
+
439
+
440
+ def _check_exit_conditions(summary: Dict[str, Any], max_tokens: Optional[int], strict: bool):
441
+ """Handles exit codes for CI/CD gates."""
442
+ if max_tokens is not None and summary["total_tokens"] > max_tokens:
443
+ sys.exit(1)
444
+ if strict and (summary["alerts"] > 0 or summary["warnings"] > 0):
445
+ sys.exit(1)
446
+
447
+
448
+ if __name__ == "__main__":
449
+ main()
@@ -0,0 +1,304 @@
1
+ Metadata-Version: 2.4
2
+ Name: token-diet-cli
3
+ Version: 0.1.0
4
+ Summary: Diagnostic tools and methodology to audit and optimize token footprint in AI coding workflows
5
+ Author-email: josephrotts <387283+josephrotts@users.noreply.github.com>
6
+ License: MIT
7
+ Keywords: tokens,llm,claude,gemini,codex,opencode,developer-tools
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Quality Assurance
19
+ Requires-Python: >=3.8
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Dynamic: license-file
23
+
24
+ # token-diet
25
+
26
+ Audit token footprint and detect silent context leaks in AI agent workflows.
27
+
28
+ Zero-dependency CLI for **Claude Code**, **Cursor**, **Codex**, **Gemini**, and **OpenCode**.
29
+
30
+ ---
31
+
32
+ ## Why?
33
+
34
+ AI coding assistants inject instruction files (`AGENTS.md`, `CLAUDE.md`, `.cursorrules`) into the system prompt on **every single turn**. A bloated 25 KB prompt file forces the model to re-process ~6,000 tokens on every message, draining rate limits and breaking prompt cache discounts.
35
+
36
+ Worse, some local tools install hidden `pre-commit` hooks that send your entire git diff to an LLM on every commit.
37
+
38
+ `token-diet` scans your repository or workstation in milliseconds to:
39
+ - **Audit prompt size:** Flags instruction files that exceed context budgets (`[OK]`, `[WARN]`, `[ALERT]`).
40
+ - **Catch rogue git hooks:** Detects and disables silent LLM review hooks in `.git/hooks/pre-commit` (`--fix-hooks`).
41
+ - **Guard CI pipelines:** Fails PR builds if prompt expansions exceed token thresholds (`--strict`, `--max-tokens`).
42
+ - **Zero dependencies:** Pure Python standard library (Python >= 3.8). Runs in < 10ms.
43
+
44
+ ---
45
+
46
+ ## Installation
47
+
48
+ ### Via Homebrew (macOS & Linux)
49
+ ```bash
50
+ brew install josephrotts/tap/token-diet
51
+ # Or:
52
+ brew tap josephrotts/tap
53
+ brew install token-diet
54
+ ```
55
+
56
+ ### Via `pipx` (Recommended for Isolated CLI)
57
+ ```bash
58
+ pipx install token-diet-cli
59
+ ```
60
+
61
+ ### Via `pip` / `uv`
62
+ ```bash
63
+ # Using pip:
64
+ pip install token-diet-cli
65
+
66
+ # Using uv:
67
+ uv tool install token-diet-cli
68
+ ```
69
+
70
+ ### Running Directly from Source (No Installation Needed)
71
+ ```bash
72
+ git clone https://github.com/josephrotts/token-diet.git
73
+ cd token-diet
74
+ PYTHONPATH=src python3 -m token_diet
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Usage
80
+
81
+ ### 1. Instant Health Check in Current Directory
82
+ Simply run `token-diet` in any project repository. It automatically scans local directives and checks for dangerous pre-commit hooks:
83
+
84
+ ```bash
85
+ token-diet
86
+ ```
87
+
88
+ **Example Output:**
89
+ ```text
90
+ ================================================================================
91
+ TOKEN DIET: FOOTPRINT & CONTEXT AUDIT
92
+ ================================================================================
93
+ File / Directive | Bytes | Tokens | Status
94
+ --------------------------------------------------------------------------------
95
+ /Users/developer/my-project/AGENTS.md | 962 | 240 | [OK]
96
+ /Users/developer/my-project/.cursorrules | 1,240 | 310 | [OK]
97
+ ================================================================================
98
+ Total Bytes: 2,202 B
99
+ Total Tokens: ~550 estimated base tokens per turn
100
+ Files Detected: 2 of 2
101
+ ```
102
+
103
+ ### 2. Automated Alerts: Context Bloat & Invisible Pre-Commit Hooks
104
+ When a prompt file is oversized or a git hook silently burns tokens on every commit, `token-diet` issues an instant visual alert:
105
+
106
+ ```bash
107
+ token-diet
108
+ ```
109
+
110
+ **Example Alert Output:**
111
+ ```text
112
+ ================================================================================
113
+ TOKEN DIET: FOOTPRINT & CONTEXT AUDIT
114
+ ================================================================================
115
+ File / Directive | Bytes | Tokens | Status
116
+ --------------------------------------------------------------------------------
117
+ /Users/developer/my-project/AGENTS.md | 24,500 | 6,125 | [ALERT]
118
+ ================================================================================
119
+ Total Bytes: 24,500 B
120
+ Total Tokens: ~6,125 estimated base tokens per turn
121
+ Files Detected: 1 of 1
122
+
123
+ 🚨 IRREGULAR HOOK DETECTED:
124
+ • [pre-commit] Pre-commit hook invokes AI/LLM review tooling (gga, opencode). This causes invisible token consumption on every commit.
125
+ Path: /Users/developer/my-project/.git/hooks/pre-commit
126
+ 💡 Tip: Run 'token-diet --fix-hooks' to automatically neutralize silent AI invocations.
127
+
128
+ ⚠️ CONTEXT BLOAT DETECTED:
129
+ Files marked [ALERT] exceed 16 KB (>4k tokens) and severely penalize context windows.
130
+ Recommendation: Decouple procedures into On-Demand Skills using the LUT Router pattern.
131
+ ```
132
+
133
+ ### 3. Auto-Fix Silent Pre-Commit Hooks (`--fix-hooks`)
134
+ Neutralize unmonitored AI review tooling in `.git/hooks/pre-commit` in a single command with an automatic backup (`.git/hooks/pre-commit.bak`):
135
+
136
+ ```bash
137
+ token-diet --fix-hooks
138
+ ```
139
+
140
+ **Example Output:**
141
+ ```text
142
+ 🛠️ AUTO-REMEDIATION: PRE-COMMIT HOOKS NEUTRALIZED
143
+ • Backup saved: /Users/developer/my-project/.git/hooks/pre-commit.bak
144
+ • Neutralized 1 AI review invocation(s).
145
+ • Safe pre-commit hook is active without silent token bleed.
146
+ ```
147
+
148
+ ### 4. Audit System-Wide Global Prompts (`--global`)
149
+ Scan default assistant instruction files across your entire workstation (`~/.claude/CLAUDE.md`, `~/.codex/AGENTS.md`, `~/.gemini/GEMINI.md`, etc.):
150
+
151
+ ```bash
152
+ token-diet --global
153
+ ```
154
+
155
+ ### 5. Audit Specific Paths or Folders
156
+ ```bash
157
+ # Audit a single file
158
+ token-diet AGENTS.md
159
+
160
+ # Audit entire directories recursively
161
+ token-diet docs/
162
+ ```
163
+
164
+ ### 6. Automated CI / Pre-Commit Gate
165
+ Integrate into your CI pipeline or Git pre-commit workflow to prevent prompt regressions:
166
+
167
+ ```bash
168
+ # Fail CI if prompt footprint exceeds 2,500 tokens:
169
+ token-diet --max-tokens 2500 AGENTS.md
170
+
171
+ # Fail CI if any file triggers a [WARN] or [ALERT]:
172
+ token-diet --strict docs/
173
+ ```
174
+
175
+ ### 7. Structured Telemetry Output (`--json`)
176
+ Emit structured JSON for automated pipelines, threshold assertions, or telemetry dashboards:
177
+
178
+ ```bash
179
+ token-diet --json
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Health Status Indicators
185
+
186
+ | Indicator | Byte Threshold | Estimated Tokens | What it Means & Recommended Action |
187
+ |---|:---:|:---:|---|
188
+ | 🟢 `[OK]` | `< 4 KB` | `< 1,000 tokens` | **Optimal Context:** Fits cleanly within prompt cache. Preserves fast, cheap inference. |
189
+ | 🟡 `[WARN]` | `4 KB – 16 KB` | `1,000 – 4,000 tokens` | **Moderate Size:** Acceptable, but review for duplicate instructions or unneeded verbosity. |
190
+ | 🔴 `[ALERT]` | `> 16 KB` | `> 4,000 tokens` | **Severe Prompt Bloat:** Monolithic rules degrade reasoning and waste context budget every turn. Decouple into On-Demand Skills. |
191
+ | 🚨 `[HOOK ALERT]` | — | — | **Hidden Token Bleed:** Local `.git/hooks/pre-commit` sends code to cloud LLMs on every `git commit`. Replace with static linters. |
192
+
193
+ ---
194
+
195
+ ## What To Do When a Leak is Detected (Action Paths)
196
+
197
+ When `token-diet` flags an irregularity, follow the corresponding action path (detailed runbooks available in the [Remediation Playbook](docs/remediation-playbook.md)):
198
+
199
+ ### Path A: When an Irregular Git Hook is Flagged (`🚨 IRREGULAR HOOK DETECTED`)
200
+ * **Problem:** A local hook inside `.git/hooks/pre-commit` secretly sends git diffs to cloud AI tools on every single commit.
201
+ * **Action Path:**
202
+ 1. Inspect the script: `cat .git/hooks/pre-commit`
203
+ 2. Remove or comment out the automated AI review invocation.
204
+ 3. Replace it with fast, local deterministic linters (`ruff`, `eslint`, `biome`).
205
+ 4. Relocate semantic AI reviews to **Pull Request gates in CI** (see [CI/CD Integration](docs/ci-integration.md)), where reviews are metered and visible.
206
+
207
+ ### Path B: When an Agent Directive is Bloated (`🔴 [ALERT]`)
208
+ * **Problem:** A root instruction file (`AGENTS.md`, `CLAUDE.md`, `.cursorrules`) exceeds 16 KB (> 4,000 tokens), exhausting your token budget on every turn and destroying cache discounts.
209
+ * **Action Path (The Look-Up Table / LUT Router Pattern):**
210
+ 1. **Extract Specialized Protocols:** Move detailed procedure manuals, test specifications, and review arbitrations into standalone on-demand skills (e.g., `skills/<skill-name>/SKILL.md`).
211
+ 2. **Compress Root Directive:** Keep only core behavioral invariants and a routing index in the root file (< 3 KB / < 750 tokens):
212
+ ```markdown
213
+ ## On-Demand Skills
214
+ - When running database migrations, read `skills/db-migrate/SKILL.md`.
215
+ - When preparing a release, read `skills/oss-publisher/SKILL.md`.
216
+ ```
217
+ 3. Re-run `token-diet` to confirm the status turns 🟢 `[OK]`.
218
+
219
+ ### Path C: When CI Fails on Token Budget Exceeded (`exit code 1`)
220
+ * **Problem:** A Pull Request introduced unbudgeted prompt expansion that violated `--max-tokens <N>` or `--strict`.
221
+ * **Action Path:**
222
+ 1. Run `token-diet --json` to get the machine-readable breakdown of offending files.
223
+ 2. Prune duplicate rules or extract text into skills.
224
+ 3. Re-run local check before pushing: `token-diet --strict`.
225
+
226
+ ### Agentic Remediation: Prompt for AI Assistants
227
+ To have your AI coding assistant (Claude Code, Gemini CLI, Cursor, Windsurf, OpenCode) remediate prompt bloat autonomously without manual edits, copy and paste this prompt:
228
+
229
+ ```text
230
+ Run `token-diet` in this repository. If you detect any files marked [ALERT] or [WARN], follow `docs/remediation-playbook.md` to decouple operational procedures into on-demand skills under `skills/<skill-name>/SKILL.md`. Compress the root instruction file to a concise Look-Up Table (LUT Router) under 3 KB (< 750 tokens). If an irregular hook is flagged, run `token-diet --fix-hooks`. Verify that all tests pass and `token-diet` reports [OK].
231
+ ```
232
+
233
+ ---
234
+
235
+ ## Running Tests
236
+
237
+ Token Diet includes an automated test suite with deterministic coverage:
238
+
239
+ ```bash
240
+ python3 -m unittest discover -s tests -p 'test_*.py'
241
+ ```
242
+
243
+ ---
244
+
245
+ ## Repository Structure
246
+
247
+ ```
248
+ token-diet/
249
+ ├── .github/
250
+ │ └── workflows/
251
+ │ └── ci.yml # Automated multi-version CI test runner
252
+ ├── docs/
253
+ │ ├── remediation-playbook.md # Step-by-step token containment and LUT routing
254
+ │ └── ci-integration.md # CI workflows & pre-commit gatekeeper examples
255
+ ├── src/
256
+ │ └── token_diet/ # Core Python package (Zero external dependencies)
257
+ │ ├── __init__.py
258
+ │ ├── __main__.py
259
+ │ └── cli.py # CLI implementation and footprint engine
260
+ ├── tests/
261
+ │ └── test_token_audit.py # Automated unit test suite (TDD)
262
+ ├── .gitignore
263
+ ├── AGENTS.md # Agent-friendly repository directives
264
+ ├── CONTRIBUTING.md # Contribution guidelines & engineering principles
265
+ ├── LICENSE # MIT Open Source License
266
+ ├── pyproject.toml # PEP 621 packaging and CLI entrypoint
267
+ └── README.md # Project overview and documentation
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Core Methodology: The 5 Vectors of Token Leakage
273
+
274
+ Token Diet is built on empirical analysis of how developer environments silently deplete API quotas:
275
+
276
+ 1. **Global Prompt Bloat:** Monolithic instruction files (`CLAUDE.md`, `AGENTS.md`) exceeding 20 KB inject tens of thousands of static tokens on every turn. *Solution: Keep root directives under 3 KB (<750 tokens) and route to on-demand skills.*
277
+ 2. **Invisible Git Hooks:** Pre-commit hooks that intercept local commits to invoke cloud LLM reviews drain quotas without developer consent. *Solution: Keep local commits deterministic; reserve AI reviews for PR gates.*
278
+ 3. **Reasoning Effort Inflation:** Running frontier models at `high` reasoning effort for simple syntax or diagnostic queries generates thousands of hidden chain-of-thought tokens. *Solution: Default to `medium` or `low`.*
279
+ 4. **Static MCP Schemas:** Registering dozens of MCP tools serializes massive JSON parameter schemas into system prompts. *Solution: Prune unused tool servers and enforce lazy-loading.*
280
+ 5. **Prompt Cache Invalidation:** Injecting dynamic timestamps or changing session IDs at the start of instructions destroys provider prompt caching discounts (up to 90%). *Solution: Maintain immutable instruction prefixes.*
281
+
282
+ ---
283
+
284
+ ## Platform Compatibility
285
+
286
+ Token Diet is OS-agnostic and cross-platform:
287
+ - **CLI Diagnostic Tool:** Pure Python standard library with zero third-party dependencies. Runs seamlessly on **macOS**, **Linux**, and **Windows** (Python >= 3.8).
288
+ - **Universal Methodology:** Core principles apply across all assistants (Claude Code, Gemini CLI, OpenAI Codex, OpenCode, Cursor, Windsurf).
289
+
290
+ ---
291
+
292
+ ## Documentation & Guides
293
+
294
+ For in-depth operational procedures and automated pipeline setups:
295
+ - **[Remediation Playbook](docs/remediation-playbook.md):** Step-by-step runbook to prune prompt files, configure reasoning effort, and contain background services.
296
+ - **[CI/CD Integration](docs/ci-integration.md):** GitHub Actions workflows and pre-commit configurations for automated token budget enforcement.
297
+ - **[Agent Directives (AGENTS.md)](AGENTS.md):** Operational guidelines for AI coding assistants working on this codebase.
298
+ - **[Contributing Guidelines](CONTRIBUTING.md):** How to run tests, submit pull requests, and coding standards.
299
+
300
+ ---
301
+
302
+ ## License
303
+
304
+ This project is licensed under the terms of the [MIT License](LICENSE).
@@ -0,0 +1,9 @@
1
+ token_diet/__init__.py,sha256=s4rY5xZKu2vgKxyRMTMgBWg_otFHbb5O6e7jVsQ6t-U,844
2
+ token_diet/__main__.py,sha256=RUdFtZ0V7DqVae2VM23UN9llXRAhdkDSI9usEEKxSsg,71
3
+ token_diet/cli.py,sha256=S84-yfTe4UQKLo2KW3_ZMWrltmRfgSb6bydDkNZKXEo,15488
4
+ token_diet_cli-0.1.0.dist-info/licenses/LICENSE,sha256=0B21Z9VEU2PIYo8f9Zwv6_w8xIsnG2Z-iz-wu68Z7j0,1068
5
+ token_diet_cli-0.1.0.dist-info/METADATA,sha256=SAVv5tf5YrnPepu4CXrN5MFcOdRxrhMw1B_zEQZWyC0,13647
6
+ token_diet_cli-0.1.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
7
+ token_diet_cli-0.1.0.dist-info/entry_points.txt,sha256=WosBe1HHGSUBGvrpQNCMrZ_oTOr63wjrqi4onmheNeQ,51
8
+ token_diet_cli-0.1.0.dist-info/top_level.txt,sha256=-QNFHy0ZgQmQwuX39uVnNuNWN5ANdj4biiTKjwKeig4,11
9
+ token_diet_cli-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ token-diet = token_diet.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 josephrotts
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ token_diet