Custom Claude Code Statusline: Track Tokens and Context Usage

Configure a custom statusline for Claude Code showing model, tokens, context percentage, and directories

The Problem

Claude Code has a 200K token context window and automatically runs /compact at ~80% usage. Without visibility into your context consumption, you won’t know you’re approaching the limit until it happens.

Solution: Custom Statusline

With statusline customization, you can display real-time token usage:

1
[Opus 4.5] | 🪙 56.8K | 35% | 📁 project-name | 📂 current-dir

showcase of my current custom claude code statusline setup

Setup

Step 1: Create the Script

Save to ~/.claude/statusline-command.sh:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#!/bin/bash

# read JSON input from stdin
input=$(cat)

# extract values
model=$(echo "$input" | jq -r '.model.display_name // "Claude"')
cwd=$(echo "$input" | jq -r '.workspace.current_dir')
project_dir=$(echo "$input" | jq -r '.workspace.project_dir')
session_id=$(echo "$input" | jq -r '.session_id // empty')

# get directory names
project_name=$(basename "$project_dir")
if [ "$cwd" = "$project_dir" ]; then
  cwd_name="."
elif [ "$cwd" = "$HOME" ]; then
  cwd_name="~"
else
  cwd_name=$(basename "$cwd")
fi

# estimate tokens from session transcript
token_display="--"
used_pct=""
if [ -n "$session_id" ] && [ -n "$project_dir" ]; then
  # convert project_dir to claude's path format
  # /Users/name/_code/foo.bar -> -Users-name--code-foo-bar
  project_path=$(echo "$project_dir" | sed 's|^/||; s|_|-|g; s|\.|-|g; s|/|-|g; s|^|-|')
  transcript_file="$HOME/.claude/projects/${project_path}/${session_id}.jsonl"

  if [ -f "$transcript_file" ]; then
    # find last compaction point (if any) and only count bytes after it
    compact_line=$(grep -n '"isCompactSummary":true' "$transcript_file" 2>/dev/null | tail -1 | cut -d: -f1)
    if [ -n "$compact_line" ]; then
      # count bytes from lines after compaction
      file_size=$(tail -n +$((compact_line + 1)) "$transcript_file" | wc -c | tr -d ' ')
    else
      file_size=$(stat -f%z "$transcript_file" 2>/dev/null || stat -c%s "$transcript_file" 2>/dev/null || echo 0)
    fi
    # ~8 bytes per token (JSON overhead in JSONL)
    tokens=$((file_size / 8))
    if [ "$tokens" -ge 1000 ]; then
      token_display=$(awk "BEGIN {printf \"%.1fK\", $tokens/1000}")
    else
      token_display="${tokens}"
    fi
    # percentage of 200K context window
    used_pct=$((tokens * 100 / 200000))
    [ "$used_pct" -gt 100 ] && used_pct=100
  fi
fi

# build status line
status="[${model}]"
status="${status} | 🪙 ${token_display}"
[ -n "$used_pct" ] && status="${status} | ${used_pct}%"
status="${status} | 📁 ${project_name}"
[ "$cwd_name" != "." ] && status="${status} | 📂 ${cwd_name}"

printf '%s' "$status"

Step 2: Configure Claude Code

Add to ~/.claude/settings.json:

1
2
3
4
5
6
{
  "statusLine": {
    "type": "command",
    "command": "bash ~/.claude/statusline-command.sh"
  }
}

Step 3: Make Executable and Restart

1
chmod +x ~/.claude/statusline-command.sh

Restart Claude Code to see the new statusline.

How It Works

  • Token estimation: Counts transcript file size, ~8 bytes per token (accounts for JSON overhead). Note: this is a rough approximation—actual token count may vary by ±10%
  • Compaction-aware: Resets count after /compact by detecting isCompactSummary markers
  • Path conversion: Claude stores transcripts at ~/.claude/projects/{project-path}/{session_id}.jsonl where /Users/name/project becomes -Users-name-project

Format

  • [model] - Current Claude model
  • 🪙 tokens - Estimated token count (K notation)
  • % - Context usage toward 200K limit
  • 📁 project - Project directory name
  • 📂 cwd - Current working directory (hidden if same as project)

Sources

Based on work by @pnd.

Licensed under CC BY-ND
last updated on Feb 05, 2026 19:39 CET
comments powered by Disqus