commit 79342c73dad2e9123319642796bc9e8d4a994fd7 Author: Andre <200930841+Andre-Bzk@users.noreply.github.com> Date: Sat Jul 18 15:48:14 2026 +0200 feat: add portable Claude Code statusline kit Replicating the cship-based statusline across machines meant manually copying three files and hand-editing settings.json with per-user absolute paths — error-prone and slow. Bundling the assets with an idempotent installer that resolves the pwsh path at runtime and merges into an existing settings.json makes rollout a single command per PC. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bb64b63 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# Local install artefacts / backups +*.bak +settings.json.bak diff --git a/README.md b/README.md new file mode 100644 index 0000000..8cbb352 --- /dev/null +++ b/README.md @@ -0,0 +1,110 @@ +[English](#english) | [Deutsch](#deutsch) + +--- + +## English + +# Claude Code Statusline Kit + +A portable, self-contained kit that installs a custom Claude Code statusline +(built on the [`cship`](https://cship.dev) Starship fork) onto any Windows PC +with a single command. + +### What it installs + +| Asset | Target location | Purpose | +| ----------------------------- | -------------------------- | ----------------------------------------- | +| `assets/cship.exe` | `~/.local/bin/` | Renders the statusline | +| `assets/cship.toml` | `~/.config/` | Module config (colors, icons, bars) | +| `assets/cship-statusline.ps1` | `~/.claude/` | Wrapper (progress bars, token formatting) | +| `statusLine` block | `~/.claude/settings.json` | Wires everything into Claude Code | + +### Requirements + +- **PowerShell 7** (`pwsh`). Install: `winget install --id Microsoft.PowerShell -e` +- A terminal font with **emoji / Nerd-Font glyphs** (e.g. Cascadia Code, + JetBrainsMono Nerd Font) so `🤖 ⚡ 🧠 █░` render correctly. + +### Install on a new PC + +```powershell +git clone Claude_Statusline +cd Claude_Statusline +.\install.ps1 +``` + +Then restart Claude Code (or start a new session). + +The installer is **idempotent** — run it again anytime. It auto-detects the +`pwsh` path on the target machine and merges the `statusLine` block into an +existing `settings.json` **without** overwriting your other settings (a +`.bak` backup is written first). + +### Options + +- `.\install.ps1 -Force` — also overwrite an existing `~/.config/cship.toml` + (by default an existing config is kept, so local tweaks survive). + +### Updating the kit + +Edit the files under `assets/`, commit, `git push`. On another PC: + +```powershell +git pull +.\install.ps1 -Force +``` + +--- + +## Deutsch + +# Claude Code Statusline Kit + +Ein portables, in sich geschlossenes Kit, das eine individuelle Claude-Code- +Statusline (basierend auf dem Starship-Fork [`cship`](https://cship.dev)) mit +einem einzigen Befehl auf jeden Windows-PC installiert. + +### Was installiert wird + +| Asset | Zielort | Zweck | +| ----------------------------- | -------------------------- | ---------------------------------------- | +| `assets/cship.exe` | `~/.local/bin/` | Rendert die Statusline | +| `assets/cship.toml` | `~/.config/` | Modul-Konfiguration (Farben, Icons, Bars)| +| `assets/cship-statusline.ps1` | `~/.claude/` | Wrapper (Progress-Bars, Token-Format) | +| `statusLine`-Block | `~/.claude/settings.json` | Verdrahtet alles in Claude Code | + +### Voraussetzungen + +- **PowerShell 7** (`pwsh`). Installation: `winget install --id Microsoft.PowerShell -e` +- Ein Terminal-Font mit **Emoji-/Nerd-Font-Glyphen** (z. B. Cascadia Code, + JetBrainsMono Nerd Font), damit `🤖 ⚡ 🧠 █░` korrekt dargestellt werden. + +### Installation auf einem neuen PC + +```powershell +git clone Claude_Statusline +cd Claude_Statusline +.\install.ps1 +``` + +Danach Claude Code neu starten (oder eine neue Session öffnen). + +Der Installer ist **idempotent** — jederzeit erneut ausführbar. Er erkennt den +`pwsh`-Pfad auf dem Zielrechner automatisch und fügt den `statusLine`-Block in +eine vorhandene `settings.json` ein, **ohne** deine anderen Einstellungen zu +überschreiben (vorher wird ein `.bak`-Backup geschrieben). + +### Optionen + +- `.\install.ps1 -Force` — überschreibt zusätzlich eine vorhandene + `~/.config/cship.toml` (standardmäßig wird eine bestehende Config behalten, + damit lokale Anpassungen erhalten bleiben). + +### Kit aktualisieren + +Dateien unter `assets/` bearbeiten, committen, `git push`. Auf einem anderen PC: + +```powershell +git pull +.\install.ps1 -Force +``` diff --git a/assets/cship-statusline.ps1 b/assets/cship-statusline.ps1 new file mode 100644 index 0000000..727253f --- /dev/null +++ b/assets/cship-statusline.ps1 @@ -0,0 +1,60 @@ +# cship statusline wrapper +# Runs cship, then converts its usage_limits markers (§ 5|7 § pct § reset §) +# into progress bars styled identically to the context_bar module. +$ErrorActionPreference = 'SilentlyContinue' +[Console]::InputEncoding = New-Object System.Text.UTF8Encoding $false +[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding $false +$OutputEncoding = New-Object System.Text.UTF8Encoding $false + +$cship = Join-Path $env:USERPROFILE '.local\bin\cship.exe' + +# Read the full Claude Code session JSON from stdin, hand it to cship. +$inp = [Console]::In.ReadToEnd() +$out = $inp | & $cship +# Starship's prompt carries a leading blank line (add_newline); drop leading/trailing +# blank lines so the statusline doesn't waste a row. +$text = ($out -join "`n").Trim("`r", "`n") + +$S = [char]0x00A7 +$esc = [char]0x1B +$rx = [regex]("$S([57])$S([0-9.]+)$S([^$S]*)$S") + +$render = [System.Text.RegularExpressions.MatchEvaluator]{ + param($m) + $type = $m.Groups[1].Value + $pct = [double]$m.Groups[2].Value + $reset = $m.Groups[3].Value + + $width = 10 + $filled = [int][math]::Round($pct / 100.0 * $width) + if ($filled -lt 0) { $filled = 0 } + if ($filled -gt $width) { $filled = $width } + $bar = ([string]([char]0x2588) * $filled) + ([string]([char]0x2591) * ($width - $filled)) + + # Same thresholds/colors as context_bar: warn >=40 (yellow), critical >=70 (bold red) + if ($pct -ge 70) { $color = '1;31' } + elseif ($pct -ge 40) { $color = '33' } + else { $color = '38;2;125;207;255' } + + if ($type -eq '5') { $label = '⏳ 5h' } else { $label = '📅 7d' } + $pctTxt = '{0:0}%' -f $pct + $resetTxt = if ([string]::IsNullOrWhiteSpace($reset)) { '' } else { " ($reset)" } + + "$esc[${color}m$label $bar $pctTxt$resetTxt$esc[0m" +} + +# Compact the context_window token count marker (§T§§) to K/M form, e.g. +# 42329 -> 42.3K. cship has no native thousands formatting, so it's done here. +$rxTok = [regex]("${S}T${S}([0-9]+)${S}") +$renderTok = [System.Text.RegularExpressions.MatchEvaluator]{ + param($m) + $n = [double]$m.Groups[1].Value + $ic = [Globalization.CultureInfo]::InvariantCulture + if ($n -ge 1000000) { $v = ($n / 1000000).ToString('0.0', $ic) + 'M' } + elseif ($n -ge 1000) { $v = ($n / 1000).ToString('0.0', $ic) + 'K' } + else { $v = $n.ToString('0', $ic) } + $v -replace '\.0([KM]?)$', '$1' +} +$text = $rxTok.Replace($text, $renderTok) + +[Console]::Out.Write($rx.Replace($text, $render)) diff --git a/assets/cship.exe b/assets/cship.exe new file mode 100644 index 0000000..f017a1c Binary files /dev/null and b/assets/cship.exe differ diff --git a/assets/cship.toml b/assets/cship.toml new file mode 100644 index 0000000..168aaf8 --- /dev/null +++ b/assets/cship.toml @@ -0,0 +1,52 @@ +# cship — Claude Code statusline (Hero / Recommended + usage progress bars) +# Reference: https://cship.dev +[cship] +lines = [ + "$starship_prompt", + "$cship.model $cship.effort $cship.context_window.total_input_tokens $cship.context_bar $cship.peak_usage $cship.usage_limits", +] + +[cship.model] +symbol = "🤖 " +style = "bold cyan" + +[cship.effort] +symbol = "⚡ " +style = "fg:#7dcfff" +high_style = "fg:#e0af68" +xhigh_style = "bold fg:#e0af68" +max_style = "bold fg:#f7768e" + +[cship.context_bar] +symbol = "🧠 " +filled_char = "█" +empty_char = "░" +format = "[$symbol$value]($style)" +width = 10 +style = "fg:#7dcfff" +warn_threshold = 40.0 +warn_style = "yellow" +critical_threshold = 70.0 +critical_style = "bold red" + +# $value is emitted inside a §T§…§ marker so the statusline wrapper can +# compact the raw token count (e.g. 42329 → 42.3K) before display. +[cship.context_window.total_input_tokens] +symbol = "🔢 " +style = "fg:#a9b1d6" +format = "[$symbol§T§$value§]($style)" + +# usage_limits emits machine markers (§TYPE§pct§reset§); the statusline wrapper +# turns them into progress bars styled like context_bar. Thresholds >100 so cship +# adds no ANSI of its own around the markers. +[cship.usage_limits] +style = "" +separator = " " +five_hour_format = "§5§{pct}§{reset}§" +seven_day_format = "§7§{pct}§{reset}§" +warn_threshold = 101 +critical_threshold = 101 + +[cship.peak_usage] +symbol = "⏰ " +style = "fg:#e0af68" \ No newline at end of file diff --git a/install.ps1 b/install.ps1 new file mode 100644 index 0000000..4b96ca3 --- /dev/null +++ b/install.ps1 @@ -0,0 +1,89 @@ +#requires -Version 5.1 +<# + install.ps1 — Deploys the Claude Code "cship" statusline onto this machine. + + Idempotent: safe to run repeatedly. Copies the three assets to their target + locations, auto-detects the local pwsh path, and merges the statusLine block + into an existing ~/.claude/settings.json without touching other settings. +#> +[CmdletBinding()] +param( + # Overwrite an existing cship.toml even if one is already present. + [switch]$Force +) + +$ErrorActionPreference = 'Stop' +$assets = Join-Path $PSScriptRoot 'assets' + +function Write-Step { param($m) Write-Host " $m" -ForegroundColor Cyan } +function Write-Ok { param($m) Write-Host " OK $m" -ForegroundColor Green } +function Write-Warn { param($m) Write-Host " !! $m" -ForegroundColor Yellow } + +Write-Host "`nClaude Code statusline installer" -ForegroundColor White + +# --- Target locations ------------------------------------------------------- +$localBin = Join-Path $env:USERPROFILE '.local\bin' +$config = Join-Path $env:USERPROFILE '.config' +$claude = Join-Path $env:USERPROFILE '.claude' +foreach ($d in @($localBin, $config, $claude)) { + New-Item -ItemType Directory -Force -Path $d | Out-Null +} + +# --- 1. cship.exe ----------------------------------------------------------- +Copy-Item (Join-Path $assets 'cship.exe') (Join-Path $localBin 'cship.exe') -Force +Write-Ok "cship.exe -> $localBin" + +# --- 2. cship.toml (do not clobber a customised config unless -Force) -------- +$tomlTarget = Join-Path $config 'cship.toml' +if ((Test-Path $tomlTarget) -and -not $Force) { + Write-Warn "cship.toml already exists, kept as-is (use -Force to overwrite)" +} else { + Copy-Item (Join-Path $assets 'cship.toml') $tomlTarget -Force + Write-Ok "cship.toml -> $config" +} + +# --- 3. Wrapper script ------------------------------------------------------ +$wrapperTarget = Join-Path $claude 'cship-statusline.ps1' +Copy-Item (Join-Path $assets 'cship-statusline.ps1') $wrapperTarget -Force +Write-Ok "cship-statusline.ps1 -> $claude" + +# --- 4. Locate pwsh --------------------------------------------------------- +$pwsh = (Get-Command pwsh -ErrorAction SilentlyContinue).Source +if (-not $pwsh) { + $fallback = 'C:\Program Files\PowerShell\7\pwsh.exe' + if (Test-Path $fallback) { + $pwsh = $fallback + } else { + Write-Warn "PowerShell 7 (pwsh) not found. Install it, then re-run this script." + Write-Warn " winget install --id Microsoft.PowerShell -e" + $pwsh = $fallback # write the conventional path so it works once pwsh is installed + } +} +$pwshFwd = $pwsh.Replace('\', '/') +$wrapperFwd = $wrapperTarget.Replace('\', '/') +$command = '"{0}" -NoProfile -ExecutionPolicy Bypass -File "{1}"' -f $pwshFwd, $wrapperFwd + +# --- 5. Merge statusLine into settings.json --------------------------------- +$settingsPath = Join-Path $claude 'settings.json' +if (Test-Path $settingsPath) { + Copy-Item $settingsPath "$settingsPath.bak" -Force + $settings = Get-Content $settingsPath -Raw | ConvertFrom-Json +} else { + $settings = [PSCustomObject]@{} +} + +$statusLine = [PSCustomObject]@{ type = 'command'; command = $command } +if ($settings.PSObject.Properties.Name -contains 'statusLine') { + $settings.statusLine = $statusLine +} else { + $settings | Add-Member -MemberType NoteProperty -Name 'statusLine' -Value $statusLine +} + +$settings | ConvertTo-Json -Depth 20 | Set-Content $settingsPath -Encoding UTF8 +Write-Ok "settings.json statusLine wired to detected pwsh" + +# --- Post-install notes ----------------------------------------------------- +Write-Host "`nDone." -ForegroundColor Green +Write-Host "Notes:" -ForegroundColor White +Write-Warn "Use a terminal font with emoji / Nerd-Font glyphs so the icons render (Cascadia Code, JetBrainsMono Nerd Font, ...)." +Write-Host " Restart Claude Code (or start a new session) to see the statusline.`n"