Skip to content

Instantly share code, notes, and snippets.

@kerray
Last active April 23, 2026 10:44
Show Gist options
  • Select an option

  • Save kerray/b2e1ca86c55a592d076eb0367846da79 to your computer and use it in GitHub Desktop.

Select an option

Save kerray/b2e1ca86c55a592d076eb0367846da79 to your computer and use it in GitHub Desktop.
Claude Code statusline for Windows/PowerShell - shows model, folder, git branch, API usage limits, and context window. Adapted from https://gist.github.com/kerray/a65a95a0d4931e19bf83cf19ab040e64
# fetch-usage.ps1
# Fetches Claude API usage stats and writes them to a cache file.
# Line 1: five_hour.utilization (integer %)
# Line 2: seven_day.utilization (integer %)
# Line 3: five_hour.resets_at (raw ISO string)
# Line 4: seven_day.resets_at (raw ISO string)
#
# Windows PowerShell version.
# Based on: https://gist.github.com/kerray/a65a95a0d4931e19bf83cf19ab040e64
# Original bash version by kerray, inspired by:
# https://www.reddit.com/r/ClaudeCode/comments/1rg3nmt/my_minimal_claude_code_statusline_config/
$ErrorActionPreference = 'SilentlyContinue'
$CacheFile = Join-Path $env:TEMP ".claude_usage_cache"
$CredsFile = Join-Path $env:USERPROFILE ".claude\.credentials.json"
# Read OAuth token from credentials file
if (-not (Test-Path $CredsFile)) {
exit 0
}
try {
$creds = Get-Content $CredsFile -Raw | ConvertFrom-Json
$token = $creds.claudeAiOauth.accessToken
} catch {
exit 0
}
if (-not $token) {
exit 0
}
# Fetch usage from API
try {
$headers = @{
"accept" = "application/json"
"anthropic-beta" = "oauth-2025-04-20"
"authorization" = "Bearer $token"
"user-agent" = "claude-code/2.1.11"
}
$response = Invoke-WebRequest -Uri "https://api.anthropic.com/oauth/usage" -Headers $headers -TimeoutSec 10
$usage = $response.Content | ConvertFrom-Json
} catch {
exit 0
}
if (-not $usage) {
exit 0
}
# Extract values - convert DateTime back to ISO format if PowerShell auto-converted
$fiveH = [math]::Round($usage.five_hour.utilization)
$sevenD = [math]::Round($usage.seven_day.utilization)
$fiveHReset = $usage.five_hour.resets_at
$sevenDReset = $usage.seven_day.resets_at
# If PowerShell converted to DateTime, format back to ISO
if ($fiveHReset -is [DateTime]) {
$fiveHReset = $fiveHReset.ToUniversalTime().ToString("o")
}
if ($sevenDReset -is [DateTime]) {
$sevenDReset = $sevenDReset.ToUniversalTime().ToString("o")
}
# Write to cache file
@($fiveH, $sevenD, $fiveHReset, $sevenDReset) | Out-File -FilePath $CacheFile -Encoding utf8
# statusline-command.ps1
# Claude Code statusline command - reads JSON from stdin, renders two-line status.
#
# Line 1: Model | Folder . Branch
# Line 2: 5h usage% (reset) . 7d usage% (reset) | ctx usage% (tokens)
#
# Windows PowerShell version.
# Based on: https://gist.github.com/kerray/a65a95a0d4931e19bf83cf19ab040e64
# Original bash version by kerray, inspired by:
# https://www.reddit.com/r/ClaudeCode/comments/1rg3nmt/my_minimal_claude_code_statusline_config/
$ErrorActionPreference = 'SilentlyContinue'
# Read JSON from stdin
$input_json = $input | Out-String
if (-not $input_json) {
exit 0
}
try {
$data = $input_json | ConvertFrom-Json
} catch {
exit 0
}
# --- Model ---
$model = $data.model.display_name
# --- Folder ---
$dir = if ($data.workspace.current_dir) { $data.workspace.current_dir } else { $data.cwd }
$dirName = Split-Path $dir -Leaf
# --- Git branch ---
$branch = ""
if (Test-Path (Join-Path $dir ".git")) {
Push-Location $dir
$branch = git symbolic-ref --short HEAD 2>$null
if (-not $branch) {
$branch = git rev-parse --short HEAD 2>$null
}
Pop-Location
}
# --- Usage stats from cache ---
$CacheFile = Join-Path $env:TEMP ".claude_usage_cache"
$fiveH = ""
$sevenD = ""
$fiveHReset = ""
$sevenDReset = ""
if (Test-Path $CacheFile) {
$lines = Get-Content $CacheFile
if ($lines.Count -ge 4) {
$fiveH = $lines[0]
$sevenD = $lines[1]
$fiveHReset = $lines[2]
$sevenDReset = $lines[3]
}
} else {
# Trigger background fetch
Start-Process -WindowStyle Hidden -FilePath "pwsh" -ArgumentList "-NoProfile", "-File", "$env:USERPROFILE\.claude\fetch-usage.ps1"
}
# --- Compute delta: human-readable time until reset ---
function Get-TimeDelta {
param([string]$isoTimestamp)
if (-not $isoTimestamp) { return "" }
try {
$resetTime = [DateTimeOffset]::Parse($isoTimestamp)
$now = [DateTimeOffset]::UtcNow
$diff = $resetTime - $now
if ($diff.TotalSeconds -le 0) { return "now" }
$days = [math]::Floor($diff.TotalDays)
$hours = $diff.Hours
$minutes = $diff.Minutes
if ($days -gt 0) {
return "${days}d ${hours}h"
} elseif ($hours -gt 0) {
return "${hours}h ${minutes}m"
} else {
return "${minutes}m"
}
} catch {
return ""
}
}
# --- Context window ---
$ctxStr = ""
$ctxTokensStr = ""
$used = $data.context_window.used_percentage
if ($used) {
$usedInt = [math]::Round($used)
$ctxStr = "${usedInt}%"
$cu = $data.context_window.current_usage
if ($cu) {
$ctxUsed = ($cu.cache_read_input_tokens + $cu.cache_creation_input_tokens + $cu.input_tokens + $cu.output_tokens)
$ctxTotal = $data.context_window.context_window_size
if ($ctxUsed -and $ctxTotal) {
$ctxUsedK = [math]::Floor($ctxUsed / 1000)
$ctxTotalK = [math]::Floor($ctxTotal / 1000)
$ctxTokensStr = "${ctxUsedK}k/${ctxTotalK}k"
}
}
}
# --- ANSI color codes ---
$esc = [char]27
$orange = "$esc[38;5;208m"
$cyan = "$esc[38;2;76;208;222m"
$purple = "$esc[38;2;192;103;222m"
$gray = "$esc[38;2;156;162;175m"
$dimGray = "$esc[2m$esc[38;2;156;162;175m"
$sepGray = "$esc[90m"
$bold = "$esc[1m"
$reset = "$esc[0m"
$sep = "${sepGray} . ${reset}"
$pipe = "${sepGray} | ${reset}"
# --- Line 1: Model | Folder . Branch ---
$line1 = "${orange}${bold}${model}${reset}${pipe}${bold}${cyan}${dirName}${reset}"
if ($branch) {
$line1 += "${sep}${bold}${purple}${branch}${reset}"
}
# --- Line 2: Usage | Context ---
$line2Parts = @()
if ($fiveH) {
$part = "${gray}5h ${fiveH}%${reset}"
$delta = Get-TimeDelta $fiveHReset
if ($delta) {
$part += " ${dimGray}(${delta})${reset}"
}
$line2Parts += $part
}
if ($sevenD) {
$part = "${gray}7d ${sevenD}%${reset}"
$delta = Get-TimeDelta $sevenDReset
if ($delta) {
$part += " ${dimGray}(${delta})${reset}"
}
$line2Parts += $part
}
$line2 = $line2Parts -join $sep
if ($ctxStr) {
if ($line2) {
$line2 += $pipe
}
$line2 += "${gray}ctx ${ctxStr}${reset}"
if ($ctxTokensStr) {
$line2 += " ${dimGray}(${ctxTokensStr})${reset}"
}
}
# --- Output ---
Write-Host $line1
Write-Host $line2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment