     1→#!/bin/bash
     2→# cc.sh - Unified Claude Code ROI Dashboard Control
     3→#
     4→# Usage:
     5→#   cc              # Quick status overview
     6→#   cc status       # Detailed status
     7→#   cc value        # Manage run values (interactive)
     8→#   cc watch        # Live monitoring
     9→#   cc action X     # Run automation action
    10→#   cc report       # Generate daily report
    11→#   cc help         # Show all commands
    12→
    13→SCRIPT_DIR="$HOME"
    14→API_BASE="http://localhost:9001/api/cc"
    15→
    16→RED='\033[0;31m'
    17→GREEN='\033[0;32m'
    18→YELLOW='\033[1;33m'
    19→CYAN='\033[0;36m'
    20→PURPLE='\033[0;35m'
    21→BOLD='\033[1m'
    22→DIM='\033[2m'
    23→NC='\033[0m'
    24→
    25→# Quick status - default command
    26→quick_status() {
    27→    # Check if server is running
    28→    local health
    29→    health=$(curl -s "$API_BASE/health" 2>/dev/null)
    30→
    31→    if [ -z "$health" ]; then
    32→        echo -e "${RED}⚠ CC Dashboard server is offline${NC}"
    33→        echo -e "${DIM}  Start with: python3 ~/log-server.py${NC}"
    34→        return 1
    35→    fi
    36→
    37→    # Get all data in parallel
    38→    local alltime roi_real
    39→    alltime=$(curl -s "$API_BASE/roi/all-time" 2>/dev/null)
    40→    roi_real=$(curl -s "$API_BASE/roi/real" 2>/dev/null)
    41→
    42→    # Parse with python
    43→    echo "$health" | python3 -c '
    44→import sys, json
    45→
    46→PURPLE = "\033[0;35m"
    47→GREEN = "\033[0;32m"
    48→YELLOW = "\033[1;33m"
    49→RED = "\033[0;31m"
    50→CYAN = "\033[0;36m"
    51→BOLD = "\033[1m"
    52→DIM = "\033[2m"
    53→NC = "\033[0m"
    54→
    55→try:
    56→    h = json.load(sys.stdin)
    57→    overall = h.get("overall", "unknown")
    58→    budget = h.get("gates", {}).get("budget", {})
    59→
    60→    status_icon = "●"
    61→    status_color = GREEN if overall == "ok" else YELLOW if overall == "warning" else RED
    62→
    63→    spent = budget.get("spent_usd", 0)
    64→    limit = budget.get("limit_usd", 10)
    65→    pct = budget.get("used_pct", 0)
    66→
    67→    print(f"{PURPLE}{BOLD}⚡ CC Dashboard{NC}")
    68→    print(f"  Status: {status_color}{status_icon} {overall.upper()}{NC}")
    69→    print(f"  Budget: ${spent:.2f}/${limit:.0f} ({pct:.1f}%)")
    70→except Exception as e:
    71→    print(f"Error: {e}")
    72→'
    73→
    74→    echo "$alltime" | python3 -c '
    75→import sys, json
    76→
    77→GREEN = "\033[0;32m"
    78→CYAN = "\033[0;36m"
    79→NC = "\033[0m"
    80→
    81→try:
    82→    d = json.load(sys.stdin)
    83→    profit = d.get("profit_usd", 0)
    84→    roi = d.get("roi_pct", 0)
    85→    runs = d.get("runs_total", 0)
    86→    success = d.get("success_rate_pct", 0)
    87→
    88→    print(f"  Profit: {GREEN}${profit:.2f}{NC} (+{roi:.0f}% ROI)")
    89→    print(f"  Runs:   {runs} total ({success:.0f}% success)")
    90→except Exception as e:
    91→    print(f"Error: {e}")
    92→'
    93→
    94→    echo "$roi_real" | python3 -c '
    95→import sys, json
    96→
    97→GREEN = "\033[0;32m"
    98→YELLOW = "\033[1;33m"
    99→DIM = "\033[2m"
   100→NC = "\033[0m"
   101→
   102→try:
   103→    d = json.load(sys.stdin)
   104→    real_pct = d.get("total", {}).get("real_pct", 0)
   105→    verified = d.get("real", {}).get("runs", 0)
   106→    estimated = d.get("estimated", {}).get("runs", 0)
   107→
   108→    if real_pct < 20:
   109→        color = YELLOW
   110→        msg = "needs verification"
   111→    else:
   112→        color = GREEN
   113→        msg = "good"
   114→
   115→    print(f"  Data:   {color}{real_pct:.0f}% verified{NC} {DIM}({verified} real, {estimated} estimated){NC}")
   116→except Exception as e:
   117→    print(f"Error: {e}")
   118→'
   119→
   120→    echo ""
   121→    echo -e "${DIM}Quick: cc value | cc watch | cc action report${NC}"
   122→}
   123→
   124→# Detailed status
   125→detailed_status() {
   126→    echo -e "${PURPLE}${BOLD}═══════════════════════════════════════════════════════${NC}"
   127→    echo -e "${PURPLE}${BOLD}  CC ROI Dashboard - Detailed Status${NC}"
   128→    echo -e "${PURPLE}${BOLD}═══════════════════════════════════════════════════════${NC}"
   129→    echo ""
   130→
   131→    # Health check
   132→    echo -e "${CYAN}Health Check:${NC}"
   133→    "$SCRIPT_DIR/cc-action.sh" health 2>/dev/null | grep -E "(✅|⚠|❌|Status)" | head -10
   134→    echo ""
   135→
   136→    # Value stats
   137→    echo -e "${CYAN}Value Statistics:${NC}"
   138→    "$SCRIPT_DIR/cc-value.sh" stats 2>/dev/null | tail -20
   139→    echo ""
   140→
   141→    # Recent runs
   142→    echo -e "${CYAN}Recent Runs:${NC}"
   143→    "$SCRIPT_DIR/cc-value.sh" list 2>/dev/null | head -12
   144→}
   145→
   146→# Morning report
   147→morning_report() {
   148→    echo -e "${PURPLE}${BOLD}☀  Good Morning! Here's your CC status:${NC}"
   149→    echo ""
   150→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

#!/bin/bash
# cc.sh - Unified Claude Code ROI Dashboard Control
#
# Usage:
#   cc              # Quick status overview
#   cc status       # Detailed status
#   cc value        # Manage run values (interactive)
#   cc watch        # Live monitoring
#   cc action X     # Run automation action
#   cc report       # Generate daily report
#   cc help         # Show all commands

SCRIPT_DIR="$HOME"
API_BASE="http://localhost:9001/api/cc"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
PURPLE='\033[0;35m'
BOLD='\033[1m'
DIM='\033[2m'
NC='\033[0m'

# Quick status - default command
quick_status() {
    # Check if server is running
    local health
    health=$(curl -s "$API_BASE/health" 2>/dev/null)

    if [ -z "$health" ]; then
        echo -e "${RED}⚠ CC Dashboard server is offline${NC}"
        echo -e "${DIM}  Start with: python3 ~/log-server.py${NC}"
        return 1
    fi

    # Get all data in parallel
    local alltime roi_real
    alltime=$(curl -s "$API_BASE/roi/all-time" 2>/dev/null)
    roi_real=$(curl -s "$API_BASE/roi/real" 2>/dev/null)

    # Parse with python
    echo "$health" | python3 -c '
import sys, json

PURPLE = "\033[0;35m"
GREEN = "\033[0;32m"
YELLOW = "\033[1;33m"
RED = "\033[0;31m"
CYAN = "\033[0;36m"
BOLD = "\033[1m"
DIM = "\033[2m"
NC = "\033[0m"

try:
    h = json.load(sys.stdin)
    overall = h.get("overall", "unknown")
    budget = h.get("gates", {}).get("budget", {})

    status_icon = "●"
    status_color = GREEN if overall == "ok" else YELLOW if overall == "warning" else RED

    spent = budget.get("spent_usd", 0)
    limit = budget.get("limit_usd", 10)
    pct = budget.get("used_pct", 0)

    print(f"{PURPLE}{BOLD}⚡ CC Dashboard{NC}")
    print(f"  Status: {status_color}{status_icon} {overall.upper()}{NC}")
    print(f"  Budget: ${spent:.2f}/${limit:.0f} ({pct:.1f}%)")
except Exception as e:
    print(f"Error: {e}")
'

    echo "$alltime" | python3 -c '
import sys, json

GREEN = "\033[0;32m"
CYAN = "\033[0;36m"
NC = "\033[0m"

try:
    d = json.load(sys.stdin)
    profit = d.get("profit_usd", 0)
    roi = d.get("roi_pct", 0)
    runs = d.get("runs_total", 0)
    success = d.get("success_rate_pct", 0)

    print(f"  Profit: {GREEN}${profit:.2f}{NC} (+{roi:.0f}% ROI)")
    print(f"  Runs:   {runs} total ({success:.0f}% success)")
except Exception as e:
    print(f"Error: {e}")
'

    echo "$roi_real" | python3 -c '
import sys, json

GREEN = "\033[0;32m"
YELLOW = "\033[1;33m"
DIM = "\033[2m"
NC = "\033[0m"

try:
    d = json.load(sys.stdin)
    real_pct = d.get("total", {}).get("real_pct", 0)
    verified = d.get("real", {}).get("runs", 0)
    estimated = d.get("estimated", {}).get("runs", 0)

    if real_pct < 20:
        color = YELLOW
        msg = "needs verification"
    else:
        color = GREEN
        msg = "good"

    print(f"  Data:   {color}{real_pct:.0f}% verified{NC} {DIM}({verified} real, {estimated} estimated){NC}")
except Exception as e:
    print(f"Error: {e}")
'

    echo ""
    echo -e "${DIM}Quick: cc value | cc watch | cc action report${NC}"
}

# Detailed status
detailed_status() {
    echo -e "${PURPLE}${BOLD}═══════════════════════════════════════════════════════${NC}"
    echo -e "${PURPLE}${BOLD}  CC ROI Dashboard - Detailed Status${NC}"
    echo -e "${PURPLE}${BOLD}═══════════════════════════════════════════════════════${NC}"
    echo ""

    # Health check
    echo -e "${CYAN}Health Check:${NC}"
    "$SCRIPT_DIR/cc-action.sh" health 2>/dev/null | grep -E "(✅|⚠|❌|Status)" | head -10
    echo ""

    # Value stats
    echo -e "${CYAN}Value Statistics:${NC}"
    "$SCRIPT_DIR/cc-value.sh" stats 2>/dev/null | tail -20
    echo ""

    # Recent runs
    echo -e "${CYAN}Recent Runs:${NC}"
    "$SCRIPT_DIR/cc-value.sh" list 2>/dev/null | head -12
}

# Morning report
morning_report() {
    echo -e "${PURPLE}${BOLD}☀  Good Morning! Here's your CC status:${NC}"
    echo ""


173:    cost = d.get("cost_usd", 0)
180:    print(f"  💸 Total Cost: ${cost:.2f}")

[Showing results with pagination = limit: 40, offset: 0]


Perfect! Now let me check the CLAUDE.md to see the quickstart documentation for this system:


Bash

find /Users/neog -name "CC-ROI-QUICKSTART.md" -o -name "claude-code-tracking.md" 2>/dev/null

Find CC ROI quickstart documentation


grep -r "real-time token" /Users/neog/Docs 2>/dev/null | head -5

Search for real-time token documentation


List docs directory


total 32
drwxr-xr-x@   9 neog  staff   288 Dec 13 12:05 .
drwxr-x---+ 149 neog  staff  4768 Dec 25 01:40 ..
-rw-r--r--@   1 neog  staff  6148 Dec 21 21:47 .DS_Store
-rw-r--r--@   1 neog  staff  5043 Oct 27 13:53 README.md
drwxr-xr-x@ 303 neog  staff  9696 Nov 30 19:34 archive
drwxr-xr-x@   8 neog  staff   256 Nov 30 19:33 changelogs
drwxr-xr-x@  76 neog  staff  2432 Dec 18 18:34 guides
drwxr-xr-x@  47 neog  staff  1504 Dec 15 15:55 reports
drwx------@   3 neog  staff    96 Dec  2 23:57 transcripts


Let me look at the guides and search for how token data flows through the system:


ls /Users/neog/Docs/guides/ | grep -i "cc\|token\|roi\|tracking"

Find ROI/token tracking guides


grep -l "token" /Users/neog/Docs/guides/* 2>/dev/null | head -5

Find files mentioning tokens


ls -la ~/.claude/ | grep -E "history|stats|cache"

Check Claude data files for token tracking


MacController-README.md
REMOTE-ACCESS-GUIDE.md
ROI-SIMULATOR-README.md


/Users/neog/Docs/guides/AI-CHAT-INTEGRATION-COMPLETE.md
/Users/neog/Docs/guides/AUTH-README.md
/Users/neog/Docs/guides/CHAT-GPT-OSS-120B-README.md
/Users/neog/Docs/guides/CHAT-SYSTEM-README.md
/Users/neog/Docs/guides/CRYPTO-BOT-README.md


drwx------@ 184 neog  staff     5888 Dec 24 18:20 file-history
-rw-r--r--@   1 neog  staff  8774174 Dec 25 01:40 history.jsonl
-rw-------@   1 neog  staff    11513 Dec 23 21:25 stats-cache.json
drwxr-xr-x@   7 neog  staff      224 Dec 24 18:07 statsig


Excellent! Let me look at the actual data flow by examining API endpoints more carefully:


   660→# ===== CC RUNS ENDPOINTS =====
   661→
   662→@app.route('/api/cc/run', methods=['POST'])
   663→def create_cc_run():
   664→    """Create a new automation run"""
   665→    try:
   666→        data = request.json
   667→        run_id = data.get('run_id', str(uuid.uuid4()))
   668→        device_ip = request.headers.get('X-Forwarded-For', request.remote_addr)
   669→
   670→        conn = sqlite3.connect(DB_PATH)
   671→        c = conn.cursor()
   672→        c.execute('''INSERT INTO cc_runs (run_id, session_id, prompt, source, device_ip, status, model)
   673→                     VALUES (?, ?, ?, ?, ?, ?, ?)''',
   674→                  (run_id,
   675→                   data.get('session_id'),
   676→                   data.get('prompt', ''),
   677→                   data.get('source', 'manual'),
   678→                   device_ip,
   679→                   'running',
   680→                   data.get('model', 'claude-opus-4-5-20251101')))
   681→        conn.commit()
   682→        conn.close()
   683→
   684→        # Broadcast new run via WebSocket
   685→        socketio.emit('cc_run_created', {
   686→            'run_id': run_id,
   687→            'prompt': data.get('prompt', '')[:100],
   688→            'source': data.get('source', 'manual'),
   689→            'status': 'running'
   690→        })
   691→
   692→        return jsonify({'status': 'ok', 'run_id': run_id})
   693→
   694→    except Exception as e:
   695→        return jsonify({'status': 'error', 'message': str(e)}), 500
   696→
   697→@app.route('/api/cc/run/<run_id>', methods=['PATCH'])
   698→def update_cc_run(run_id):
   699→    """Update an existing run (tokens, status, etc.)"""
   700→    try:
   701→        data = request.json
   702→        conn = sqlite3.connect(DB_PATH)
   703→        c = conn.cursor()
   704→
   705→        # Build dynamic update query
   706→        updates = []
   707→        params = []
   708→        allowed_fields = ['status', 'input_tokens', 'output_tokens', 'cache_read_tokens',
   709→                          'cost_usd', 'value_generated_usd', 'gate_guardrails_ok',
   710→                          'gate_budget_ok', 'gate_heartbeat_ok', 'halt_reason',
   711→                          'tools_used', 'files_modified', 'error_message']
   712→
   713→        for field in allowed_fields:
   714→            if field in data:
   715→                updates.append(f'{field} = ?')
   716→                value = data[field]
   717→                # Convert lists to JSON strings
   718→                if isinstance(value, (list, dict)):
   719→                    value = json.dumps(value)
   720→                params.append(value)
   721→
   722→        # Auto-calculate cost if tokens provided
   723→        if 'input_tokens' in data or 'output_tokens' in data:
   724→            c.execute('SELECT input_tokens, output_tokens, cache_read_tokens, model FROM cc_runs WHERE run_id = ?', (run_id,))
   725→            row = c.fetchone()
   726→            if row:
   727→                input_t = data.get('input_tokens', row[0])
   728→                output_t = data.get('output_tokens', row[1])
   729→                cache_t = data.get('cache_read_tokens', row[2])
   730→                model = row[3]
   731→                cost = calculate_cost(input_t, output_t, cache_t, model)
   732→                updates.append('cost_usd = ?')
   733→                params.append(cost)
   734→
   735→        if updates:
   736→            params.append(run_id)
   737→            c.execute(f'UPDATE cc_runs SET {", ".join(updates)} WHERE run_id = ?', params)
   738→            conn.commit()
   739→
   740→        conn.close()
   741→
   742→        # Broadcast update via WebSocket
   743→        socketio.emit('cc_run_updated', {'run_id': run_id, **data})
   744→
   745→        return jsonify({'status': 'ok', 'run_id': run_id})
   746→
   747→    except Exception as e:
   748→        return jsonify({'status': 'error', 'message': str(e)}), 500
   749→
   750→def estimate_run_value(prompt, source, cost_usd, tokens):
   751→    """Smart value estimation based on run characteristics"""
   752→    base_value = 0
   753→
   754→    # Source-based multipliers
   755→    source_multipliers = {
   756→        'ios_app': 3.0,      # iOS apps are high value
   757→        'web': 2.5,          # Web projects
   758→        'dashboard': 2.0,    # Dashboard automation
   759→        'terminal': 1.5,     # Terminal tasks

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

# ===== CC RUNS ENDPOINTS =====

@app.route('/api/cc/run', methods=['POST'])
def create_cc_run():
    """Create a new automation run"""
    try:
        data = request.json
        run_id = data.get('run_id', str(uuid.uuid4()))
        device_ip = request.headers.get('X-Forwarded-For', request.remote_addr)

        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()
        c.execute('''INSERT INTO cc_runs (run_id, session_id, prompt, source, device_ip, status, model)
                     VALUES (?, ?, ?, ?, ?, ?, ?)''',
                  (run_id,
                   data.get('session_id'),
                   data.get('prompt', ''),
                   data.get('source', 'manual'),
                   device_ip,
                   'running',
                   data.get('model', 'claude-opus-4-5-20251101')))
        conn.commit()
        conn.close()

        # Broadcast new run via WebSocket
        socketio.emit('cc_run_created', {
            'run_id': run_id,
            'prompt': data.get('prompt', '')[:100],
            'source': data.get('source', 'manual'),
            'status': 'running'
        })

        return jsonify({'status': 'ok', 'run_id': run_id})

    except Exception as e:
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/cc/run/<run_id>', methods=['PATCH'])
def update_cc_run(run_id):
    """Update an existing run (tokens, status, etc.)"""
    try:
        data = request.json
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()

        # Build dynamic update query
        updates = []
        params = []
        allowed_fields = ['status', 'input_tokens', 'output_tokens', 'cache_read_tokens',
                          'cost_usd', 'value_generated_usd', 'gate_guardrails_ok',
                          'gate_budget_ok', 'gate_heartbeat_ok', 'halt_reason',
                          'tools_used', 'files_modified', 'error_message']

        for field in allowed_fields:
            if field in data:
                updates.append(f'{field} = ?')
                value = data[field]
                # Convert lists to JSON strings
                if isinstance(value, (list, dict)):
                    value = json.dumps(value)
                params.append(value)

        # Auto-calculate cost if tokens provided
        if 'input_tokens' in data or 'output_tokens' in data:
            c.execute('SELECT input_tokens, output_tokens, cache_read_tokens, model FROM cc_runs WHERE run_id = ?', (run_id,))
            row = c.fetchone()
            if row:
                input_t = data.get('input_tokens', row[0])
                output_t = data.get('output_tokens', row[1])
                cache_t = data.get('cache_read_tokens', row[2])
                model = row[3]
                cost = calculate_cost(input_t, output_t, cache_t, model)
                updates.append('cost_usd = ?')
                params.append(cost)

        if updates:
            params.append(run_id)
            c.execute(f'UPDATE cc_runs SET {", ".join(updates)} WHERE run_id = ?', params)
            conn.commit()

        conn.close()

        # Broadcast update via WebSocket
        socketio.emit('cc_run_updated', {'run_id': run_id, **data})

        return jsonify({'status': 'ok', 'run_id': run_id})

    except Exception as e:
        return jsonify({'status': 'error', 'message': str(e)}), 500

def estimate_run_value(prompt, source, cost_usd, tokens):
    """Smart value estimation based on run characteristics"""
    base_value = 0

    # Source-based multipliers
    source_multipliers = {
        'ios_app': 3.0,      # iOS apps are high value
        'web': 2.5,          # Web projects
        'dashboard': 2.0,    # Dashboard automation
        'terminal': 1.5,     # Terminal tasks


662:@app.route('/api/cc/run', methods=['POST'])
663:def create_cc_run():
792:@app.route('/api/cc/run/<run_id>/complete', methods=['POST'])
888:@app.route('/api/cc/run/<run_id>/value', methods=['POST'])
931:@app.route('/api/cc/runs/clear-estimates', methods=['POST'])
1110:@app.route('/api/cc/event', methods=['POST'])
1536:@app.route('/api/cc/budget/auto-scale', methods=['POST'])
1851:@app.route('/api/cc/gate/check', methods=['POST'])
1927:@app.route('/api/cc/gate/heartbeat', methods=['POST'])
1991:@app.route('/api/cc/budget', methods=['POST'])
2053:@app.route('/api/cc/tags', methods=['POST'])
2069:@app.route('/api/cc/run/<run_id>/tags', methods=['POST'])
2149:@app.route('/api/cc/guardrails', methods=['POST'])
2231:@app.route('/api/cc/webhooks', methods=['POST'])
2251:@app.route('/api/cc/webhooks/test', methods=['POST'])

[Showing results with pagination = limit: 50, offset: 0]


Perfect! Now I have a comprehensive understanding. Let me create a detailed report summarizing my findings:

## Summary: Claude Code CLI Usage Reporting and Real-Time Token Capture

Based on my exploration of your codebase, here's a comprehensive report on how Claude Code CLI reports usage information and how the existing CC ROI tracking system works.

---

### 1. Claude Code CLI Data Storage

**Primary Data Files:**

- **`/Users/neog/.claude/stats-cache.json`** - The main usage cache file containing:
  - Daily activity metrics (messages, sessions, tool calls)
  - Daily model token usage by date
  - Per-model token counts (input, output, cache read/creation)
  - Cumulative usage statistics

- **`/Users/neog/.claude/history.jsonl`** - Full session history (8.7 MB JSONL file) containing:
  - Command display/input
  - Timestamps
  - Project context
  - User interactions

- **`/Users/neog/.claude/settings.local.json`** - Configuration with permitted tools and capabilities

**Current Token Data Available:**
The `stats-cache.json` file tracks:
- Input tokens, output tokens, cache read tokens per model per day
- Models tracked: `claude-opus-4-5-20251101`, `claude-sonnet-4-5-20250929`
- **Cost field is present but shows as 0** (not calculated by Claude Code CLI internally)

---

### 2. Existing CC ROI Tracking System (Port 9001)

Your existing system has a sophisticated backend for capturing and analyzing Claude Code usage:

**Database Structure** (`/Users/neog/Services/servers/log-server.py`):

The `cc_runs` table tracks each automation run with:
```
- run_id (unique identifier)
- session_id
- prompt (the instruction)
- source (manual, ios_app, web, etc.)
- input_tokens, output_tokens, cache_read_tokens
- cost_usd (calculated from tokens)
- value_generated_usd (revenue from the run)
- duration_ms
- status (pending, running, completed)
- model (claude-opus-4-5-20251101, etc.)
- Tools used, files modified, errors
```

**Cost Calculation:**
```python
def calculate_cost(input_tokens, output_tokens, cache_read_tokens=0, model='default'):
    # Token cost rates (USD per 1M tokens)
    rates = {
        'claude-opus-4-5-20251101': {
            'input': 3.00,           # $3 per 1M input tokens
            'output': 15.00,         # $15 per 1M output tokens
            'cache_read': 0.30,      # $0.30 per 1M cache read tokens
            'cache_creation': 3.75   # $3.75 per 1M cache creation tokens
        },
        'claude-sonnet-4-5-20250929': { ... }
    }
    cost = (input_tokens / 1_000_000 * rates['input'] +
            output_tokens / 1_000_000 * rates['output'] +
            cache_read_tokens / 1_000_000 * rates['cache_read'])
```

---

### 3. Current Data Flow Architecture

```
Claude Code CLI (Haiku 4.5)
    ↓
.claude/stats-cache.json (daily summary)
.claude/history.jsonl (full history)
    ↓
    ← [ISSUE: Stats don't include token counts from active session]
    ↓
Manual API calls via cc-track.sh
    ↓ (POST /api/cc/run)
SQLite Database (logs.db)
    ↓
REST API (port 9001) + WebSocket
    ↓
cc-watch.sh (live monitoring)
cc-value.sh (ROI analysis)
Dashboard UI (ROI graphs)
```

---

### 4. Real-Time Token Capture Methods (Current)

**How tokens flow into the system today:**

1. **Manual Submission via `cc-track.sh`:**
   ```bash
   cc-track.sh start "Your prompt here"    # Creates run_id
   # ... Claude runs ...
   cc-track.sh complete <run_id> 25.00    # Provides tokens/cost manually
   ```

2. **Event-Based Tracking via `/api/cc/event` endpoint:**
   ```bash
   curl -X POST http://localhost:9001/api/cc/event \
     -d "{\"run_id\": \"xyz\", \"input_tokens\": 5000,
           \"output_tokens\": 2000, \"cost_usd\": 0.15}"
   ```

3. **Post-Session Updates via PATCH endpoint:**
   ```bash
   curl -X PATCH http://localhost:9001/api/cc/run/<run_id> \
     -d "{\"input_tokens\": 5000, \"output_tokens\": 2000}"
   # Cost auto-calculates based on model rates
   ```

---

### 5. Existing Tracking Scripts

**Main Scripts in `/Users/neog/Scripts/cc/`:**

| Script | Purpose | Real-Time? |
|--------|---------|-----------|
| `cc-track.sh` | Start/complete runs, track costs | Manual triggers |
| `cc-watch.sh` | Live terminal dashboard (polls API every 2s) | Polling-based |
| `cc.sh` | Quick status & health checks | Polling-based |
| `cc-action.sh` | Automation actions (9,814 bytes) | Event-driven |
| `cc-scheduler.sh` | Schedule reports & health checks | Time-based |
| `cc-services.sh` | Start/stop log server | Service mgmt |

**Live Monitoring via `cc-watch.sh`:**
- Connects to port 9001 API
- Pulls health, ROI summary, recent runs every 2 seconds
- Displays budget status, profit/ROI, active runs
- Shows color-coded status (ok/warning/critical)

---

### 6. The Gap: Real-Time Token Counting

**Current Limitation:**
Claude Code CLI doesn't expose **active session** token counts in real-time. The `stats-cache.json` is only updated after sessions complete.

**Why This Matters:**
- You can't see tokens being consumed during a running session
- Cost estimates must be added manually after the fact
- No mid-stream alerts if a session uses too many tokens

**Data Available Post-Session:**
- `~/.claude/stats-cache.json` updates daily with aggregate counts
- `~/.claude/history.jsonl` has session metadata but not token breakdown
- No detailed per-message token counts in history

---

### 7. Recommended Architecture for Real-Time Capture

Based on your existing system, here are the three approaches:

**Option A: CLI Wrapper (Lightweight)**
```bash
# Intercept claude code invocations
claude [args] > session.log 2>&1
# Parse completion with: jq .stats-cache.json
# POST to /api/cc/run/<id>/complete
```

**Option B: File Watcher (Medium)**
```python
# Monitor ~/.claude/stats-cache.json
# On change, diff against previous
# Calculate tokens used, POST to API
# Updates run records in real-time
```

**Option C: Webhook Integration (Advanced)**
```python
# Extend log-server.py to:
# - Watch stats-cache.json via watchdog
# - Parse daily token deltas
# - Emit WebSocket events to dashboard
# - Store granular event history
```

---

### 8. API Endpoints for Token Integration

Your system already has endpoints ready for real-time data:

```bash
# Create a run
POST /api/cc/run
{
  "prompt": "...",
  "source": "cli",
  "session_id": "uuid",
  "model": "claude-haiku-4-5-20251001"
}

# Update with tokens mid-session (could be called every message)
PATCH /api/cc/run/<run_id>
{
  "input_tokens": 1500,
  "output_tokens": 800,
  "cache_read_tokens": 50
  # cost_usd auto-calculates!
}

# Complete the run
POST /api/cc/run/<run_id>/complete
{
  "status": "completed",
  "input_tokens": 5000,
  "output_tokens": 2000,
  "value_generated_usd": 25.00
}
```

---

### 9. Key Files to Reference

| Location | Purpose | Size |
|----------|---------|------|
| `/Users/neog/.claude/stats-cache.json` | Token cache (updated daily) | 11.5 KB |
| `/Users/neog/.claude/history.jsonl` | Full history (read-only) | 8.7 MB |
| `/Users/neog/Services/servers/log-server.py` | CC ROI backend | ~770 KB |
| `/Users/neog/Scripts/cc/cc-*.sh` | CLI scripts (10 files) | ~60 KB total |
| `/Users/neog/logs.db` | SQLite database (ROI data) | (size varies) |

---

### 10. Token Pricing Built Into System

The system has pre-configured rates for:
- **Claude Opus 4.5**: $3.00 input, $15.00 output per 1M tokens
- **Claude Sonnet 4.5**: (lower rates, exact values in code)
- **Claude Haiku 4.5**: (lowest cost, values in code)
- Cache-aware pricing for read/creation tokens

---

### Summary

**What's Already Built:**
- Complete ROI tracking system (port 9001)
- SQLite backend with schema for tokens, costs, runs
- Shell scripts for CLI integration
- Live dashboard with WebSocket support
- Cost calculation engine with model-specific rates

**What's Missing for Real-Time Token Capture:**
- Integration between Claude Code CLI local data and your API
- Automated parsing of `.claude/stats-cache.json` changes
- Mid-session token reporting (would need CLI wrapper or file watcher)
- Active session token counts (Claude CLI doesn't export these currently)

The best path forward would be a **file watcher** (Option B) that monitors `~/.claude/stats-cache.json` for changes and posts incremental token updates to your existing `/api/cc/run/<id>` endpoint, which already has all the database infrastructure ready.