AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Code Count

skill-stevederico-skills-code-count · by stevederico

Count Claude Code tokens and estimate API cost from local JSONL transcripts. Use when the user asks about usage, token counts, API cost, or billing stats.

No reviews yet
0 installs
44 views
0.0% view→install

Install

$ agentstack add skill-stevederico-skills-code-count

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access Used
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-stevederico-skills-code-count)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
5mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Code Count? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Claude Code Usage Stats

Count tokens and estimate equivalent API cost from local Claude Code JSONL transcripts stored in ~/.claude/projects/.

How it works

Claude Code stores conversation transcripts as JSONL files in ~/.claude/projects//*.jsonl. Each line is a JSON object. Lines with assistant messages contain a message object with a usage block tracking token consumption for that API call.

Deduplication

Streaming responses write multiple JSONL lines for the same API call with cumulative token counts. To avoid double-counting, deduplicate using messageId:requestId as a composite key and keep only the last entry per key.

  • messageId = message.id field
  • requestId = top-level requestId field
  • If either is missing, the entry is always counted (never deduped)

Token fields

| Field | Description | |-------|-------------| | input_tokens | Direct input tokens (small — most context hits cache) | | cache_creation_input_tokens | Tokens written to prompt cache (costs 1.25x input) | | cache_read_input_tokens | Tokens read from prompt cache (costs 0.1x input) | | output_tokens | Generated output tokens |

Timestamps

All timestamps in the JSONL are UTC. Always convert to the user's local timezone before bucketing by date. Use datetime.now(timezone.utc).astimezone().tzinfo to auto-detect local timezone.

Optional: costUSD

Some transcripts include a pre-calculated costUSD field per entry. If present, sum those instead of computing from tokens. Pro/Max subscriptions typically don't populate this field.

Opus API pricing (per 1M tokens)

| Type | Cost | |------|------| | Input | $15 | | Cache creation | $18.75 | | Cache read | $1.50 | | Output | $75 |

When the user asks for usage stats

Run the following script via python3 -c. Adjust the days variable if the user specifies a time range (default: 30 days). Present results as a formatted table.

import json, os, glob
from datetime import datetime, timedelta, timezone

LOCAL_TZ = datetime.now(timezone.utc).astimezone().tzinfo
days = 30
cutoff = (datetime.now(timezone.utc) - timedelta(days=days)).isoformat()

def to_local_date(ts):
    if not ts:
        return None
    if ts.endswith('Z'):
        dt = datetime.fromisoformat(ts.replace('Z', '+00:00'))
    elif '+' in ts[10:] or ts.count('-') > 2:
        dt = datetime.fromisoformat(ts)
    else:
        dt = datetime.fromisoformat(ts).replace(tzinfo=timezone.utc)
    return dt.astimezone(LOCAL_TZ).strftime('%Y-%m-%d')

messages = {}

for path in glob.glob(os.path.expanduser('~/.claude/projects/*/*.jsonl')):
    with open(path) as f:
        for line in f:
            try:
                obj = json.loads(line.strip())
                mid = obj.get('message', {}).get('id')
                rid = obj.get('requestId')
                if not mid or not rid:
                    continue
                u = obj.get('message', {}).get('usage', {})
                cost = obj.get('costUSD')
                if not u:
                    continue
                ts = obj.get('timestamp') or obj.get('message', {}).get('created_at') or ''
                if ts 15,}')
print(f'Input tokens:         {total_in:>15,}')
print(f'Cache creation:       {total_cache_create:>15,}')
print(f'Cache reads:          {total_cache_read:>15,}')
print(f'Output tokens:        {total_out:>15,}')
if cost_entries > 0:
    print(f'Pre-calculated cost:  ${total_cost:>14,.2f}')
else:
    cost = (total_in/1e6*15 + total_cache_create/1e6*18.75 + total_cache_read/1e6*1.50 + total_out/1e6*75)
    print(f'Estimated API cost:   ${cost:>14,.2f}  (Opus rates)')

When the user asks for a daily breakdown

Run the same parsing logic above, then bucket by local date and display a bar chart:

from collections import defaultdict

daily = defaultdict(float)
for v in messages.values():
    u = v['usage']
    cost = (u.get('input_tokens',0)/1e6*15 + u.get('cache_creation_input_tokens',0)/1e6*18.75
            + u.get('cache_read_input_tokens',0)/1e6*1.50 + u.get('output_tokens',0)/1e6*75)
    daily[v['date']] += cost

start = datetime.strptime(min(daily.keys()), '%Y-%m-%d')
end = datetime.strptime(max(daily.keys()), '%Y-%m-%d')
all_days = []
d = start
while d  0 else 0
    day = datetime.strptime(date, '%Y-%m-%d').strftime('%a')
    print(f'{date} {day}  {"█" * bars} ${cost:>7,.0f}')
print(f'\nTotal: ${sum(c for _, c in all_days):>,.0f}')

When the user asks for per-project breakdown

from collections import defaultdict

projects = defaultdict(lambda: {'calls': 0, 'in': 0, 'out': 0, 'cache_create': 0, 'cache_read': 0})

for path in glob.glob(os.path.expanduser('~/.claude/projects/*/*.jsonl')):
    project = os.path.basename(os.path.dirname(path))
    file_msgs = {}
    with open(path) as f:
        for line in f:
            try:
                obj = json.loads(line.strip())
                mid = obj.get('message', {}).get('id')
                rid = obj.get('requestId')
                if not mid or not rid:
                    continue
                u = obj.get('message', {}).get('usage', {})
                if not u:
                    continue
                file_msgs[f'{mid}:{rid}'] = u
            except:
                pass
    p = projects[project]
    for u in file_msgs.values():
        p['calls'] += 1
        p['in'] += u.get('input_tokens', 0)
        p['out'] += u.get('output_tokens', 0)
        p['cache_create'] += u.get('cache_creation_input_tokens', 0)
        p['cache_read'] += u.get('cache_read_input_tokens', 0)

for name in sorted(projects, key=lambda k: projects[k]['out'], reverse=True):
    p = projects[name]
    short = name.split('-')[-1] if name.count('-') > 3 else name
    cost = (p['in']/1e6*15 + p['cache_create']/1e6*18.75 + p['cache_read']/1e6*1.5 + p['out']/1e6*75)
    print(f'{short:6} calls  {p["out"]:>10,} out tokens  ${cost:>8,.2f}')

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.