Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add skills/oxi-717/ai-native-toolkit/cc-analyticsnpx skills add OXI-717/ai-native-toolkit --skill cc-analyticsgit clone --depth 1 https://github.com/OXI-717/ai-native-toolkitWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/oxi-717/ai-native-toolkit/cc-analytics)<a href="https://agentmods.dev/skills/oxi-717/ai-native-toolkit/cc-analytics"><img src="https://agentmods.dev/badge/skills/oxi-717/ai-native-toolkit/cc-analytics.svg" alt="Measured on agentmods" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5 | $0.00059 | $0.02473 |
| Opus 5 | $0.00030 | $0.01236 |
| Sonnet 5 | $0.00012 | $0.00495 |
| Haiku 4.5 | $0.00006 | $0.00247 |
Grade A, and why
cc-analytics scanned grade A with 1 finding against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 5d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Runs shell commandslowCapability
Expected in a hook, worth knowing in a rule or an instructions file.
result = subprocess.run(['git', '-C', path, 'remote', 'get-url', 'origin'], This is a copy
100% identical to cc-analytics — 101 lines differ, which has more behind it and is treated as the original. This page carries a canonical link to it rather than competing with it.
How it starts
The opening of the file, as written. The whole thing — 270 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Claude Code Analytics
Generate HTML report of Claude Code usage from ~/.claude/history.jsonl.
Data Sources
- History:
~/.claude/history.jsonl— prompts with timestamps and project paths - Git: Remote URLs and commit counts per project
Output
Single HTML file with terminal aesthetic:
- ASCII art header
- Summary stats (projects, prompts, commits, days)
- Project table with remote links
- ASCII bar chart
Generation Script
Run this Python script to generate the report:
import json
import os
import subprocess
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime, timedelta
from collections import defaultdict
SKIP_DIRS = {'node_modules', '.venv', 'venv', '.worktrees', 'dist', 'build', '__pycache__'}
def _repo_stats(path, week_ago):
"""remote + commit count for a single git repo."""
try:
result = subprocess.run(['git', '-C', path, 'remote', 'get-url', 'origin'],
capture_output=True, text=True, timeout=5)
remote = result.stdout.strip() if result.returncode == 0 else None
if remote:
remote = remote.replace('[email protected]:', 'github.com/').replace('.git', '').replace('https://', '')
result = subprocess.run(['git', '-C', path, 'rev-list', '--count', f'--since={week_ago}', 'HEAD'],
capture_output=True, text=True, timeout=5)
commits = int(result.stdout.strip()) if result.returncode == 0 else 0
return remote, commits
except Exception:
return None, 0
def _nested_repos(path, depth=2):
"""Git repos below a container directory (the project dir itself is not a repo)."""
found = []
def walk(cur, level):
if level > depth:
return
try:
entries = os.listdir(cur)
except OSError:
return
for name in entries:
if name.startswith('.') or name in SKIP_DIRS:
continue
sub = os.path.join(cur, name)
if not os.path.isdir(sub) or os.path.islink(sub):
continue
if os.path.exists(os.path.join(sub, '.git')):
found.append(sub) # a repo's own subdirs are not scanned further
else:
walk(sub, level + 1)
walk(path, 1)
return found
def assign_repos(projects):
"""Map each container project to the repos it alone accounts for.
Containers nest (a work root holds a per-client folder, which holds the repos), so the same
repo is reachable from several projects and its commits would be counted once per
project. A repo belongs to the deepest container that sees it, and to no one if it is
a project in its own right — that project reports it directly.
"""
own_repos = {os.path.realpath(p) for p in projects
if os.path.exists(os.path.join(p, '.git'))}
owner = {} # repo realpath -> owning container
for project in projects:
if os.path.realpath(project) in own_repos:
continue
for repo in _nested_repos(project):
key = os.path.realpath(repo)
if key in own_repos:
continue
current = owner.get(key)
if current is None or len(project) > len(current):
owner[key] = project
assigned = defaultdict(list)
for repo, project in owner.items():
assigned[project].append(repo)
return assigned
def get_git_info(path, container_repos=()):
"""Commit stats for a project dir.
A project dir is often a container (several repos side by side) rather than a repo
itself — working from it used to report zero commits and hide the week's real work.
For containers, sum the commits of the repos assigned to it by `assign_repos`.
"""
if not os.path.isdir(path):
return None, 0
week_ago = (datetime.now() - timedelta(days=7)).strftime('%Y-%m-%d')
if os.path.exists(os.path.join(path, '.git')):
return _repo_stats(path, week_ago)
repos = list(container_repos)
if not repos:
return None, 0
# Two git calls per repo, all I/O-bound: sequential scanning of a large container
# takes minutes, threads bring it back to seconds.
total = 0
busiest = (None, -1) # remote of the repo with the most commits
with ThreadPoolExecutor(max_workers=16) as pool:
for remote, commits in pool.map(lambda r: _repo_stats(r, week_ago), repos):
total += commits
if commits > busiest[1]:
busiest = (remote, commits)
return busiest[0], total
# Parse history
history = []
with open(os.path.expanduser('~/.claude/history.jsonl'), 'r') as f:
for line in f:
try:
history.append(json.loads(line))
except:
pass
# Filter last N days (default 7)
days = 7
now = datetime.now()
cutoff = (now - timedelta(days=days)).timestamp() * 1000
projects = defaultdict(lambda: {'prompts': [], 'sessions': set()})
for entry in history:
ts = entry.get('timestamp', 0)
if ts >= cutoff:
project = entry.get('project', 'unknown')
projects[project]['prompts'].append(entry)
projects[project]['sessions'].add(datetime.fromtimestamp(ts/1000).strftime('%Y-%m-%d'))
# Collect data
home = os.path.expanduser('~')
def short_path(path):
"""Render an absolute project path relative to the current user's home."""
return '~' + path[len(home):] if path == home or path.startswith(home + os.sep) else path
results = []
total_commits = 0
container_repos = assign_repos(projects)
for project, data in projects.items():
remote, commits = get_git_info(project, container_repos.get(project, ()))
total_commits += commits
results.append({
'name': os.path.basename(project) or short_path(project),
'folder': short_path(project),
'remote': remote,
'prompts': len(data['prompts']),
'sessions': len(data['sessions']),
'commits': commits
})
results.sort(key=lambda x: -x['prompts'])
max_prompts = results[0]['prompts'] if results else 1
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 5d ago First seen · 270 lines · 59 tokens per session scan A e0649abd95b1
cc-analytics is a skill published in the GitHub repository OXI-717/ai-native-toolkit (7 stars, last pushed 12d ago), licensed MIT. It adds 59 tokens to every session and 2,473 once invoked, about $0.0003 per session on Opus 5. A static security scan graded it A with 1 finding (runs shell commands). It is 100% identical to cc-analytics, differing in 101 lines, and is treated as a copy.
Other skills, from other repositories
systematic-debugging
Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes.
local-ai-agents
Build local-first AI agents that run entirely on a developer workstation with Microsoft Foundry Local and Qwen function-calling models. Covers Small Language Models (SLMs), the OpenAI-compatible local endpoint, sandboxed local tools, local RAG with Chroma, local MCP servers, hybrid cloud/local routing, and the…
chronicle
Analyze Copilot session history for standup reports, usage tips, session search, and session reindexing. Use when the user asks for a standup, daily summary, usage tips, workflow recommendations, wants to search or find past sessions by keyword/file/PR, wants to reindex their session store, or asks about deleting…
imagegen
Generate or edit raster images when the task benefits from AI-created bitmap visuals such as photos, illustrations, textures, sprites, mockups, or transparent-background cutouts. Use when Codex should create a brand-new image, transform an existing image, or derive visual variants from references, and the output…
chat-pet-sprite-creation
Use when creating or changing VS Code chat pet sprite art, sprite sheets, state animations, eye treatments, Stable/Insiders variants, or pet transitions under src/vs/workbench/contrib/chat/browser/widget/media/chatPet.
cpu-profile-analysis
Analyze V8/Chrome CPU profiles (.cpuprofile) and DevTools trace files (Trace-.json). Use when: profiling performance, investigating slow functions, comparing code paths, finding bottlenecks, analyzing timeToRequest, understanding call trees from sampling profiler data, analyzing layout/paint/rendering, investigating…