Skip to content

Commit 27861da

Browse files
committed
feat: add itkdev-statusline plugin
Lightweight statusline showing git branch, task progress, and context window usage with color-coded thresholds.
1 parent abe5adc commit 27861da

6 files changed

Lines changed: 228 additions & 0 deletions

File tree

.claude-plugin/marketplace.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
"name": "itkdev-tools",
1212
"description": "ITK Dev tools and MCP servers for Claude Code",
1313
"source": "./"
14+
},
15+
{
16+
"name": "itkdev-statusline",
17+
"description": "Claude Code statusline with git branch, plan progress, and context window usage",
18+
"source": "./plugins/itkdev-statusline"
1419
}
1520
]
1621
}

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- `itkdev-statusline` plugin with context window usage, git branch, and plan progress display
13+
1014
## [0.4.0] - 2026-02-20
1115

1216
### Added
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "itkdev-statusline",
3+
"description": "Claude Code statusline with git branch, plan progress, and context window usage",
4+
"version": "0.1.0",
5+
"author": {
6+
"name": "ITK Dev",
7+
"email": "itkdev@mkb.aarhus.dk"
8+
},
9+
"repository": "https://github.com/itk-dev/itkdev-claude-plugins",
10+
"license": "MIT",
11+
"keywords": [
12+
"statusline",
13+
"context-window",
14+
"git-branch",
15+
"plan-progress"
16+
]
17+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# itkdev-statusline
2+
3+
Claude Code statusline plugin showing git branch, plan progress, and context window usage.
4+
5+
## What it shows
6+
7+
```
8+
feat/auth │ 2/5 │ ▰▰▰▰▰▱▱▱▱▱ 45%
9+
```
10+
11+
| Segment | Source | Notes |
12+
|---------|--------|-------|
13+
| Git branch | `.git/HEAD` in `cwd` | Handles detached HEAD (short hash) |
14+
| Plan progress | `docs/plans/*.md` in `cwd` | Newest non-VERIFIED plan, checkbox counts |
15+
| Context % | stdin JSON `context_window.used_percentage` | 10-segment progress bar, color coded |
16+
17+
### Context color thresholds
18+
19+
- **Gray** (dim): below 80%
20+
- **Yellow**: 80–89%
21+
- **Red**: 90%+
22+
23+
## Installation
24+
25+
### Via Claude Code marketplace
26+
27+
```bash
28+
claude install itk-dev/itkdev-claude-plugins:itkdev-statusline
29+
```
30+
31+
### Setup
32+
33+
After installing the plugin, run the slash command:
34+
35+
```
36+
/setup-statusline
37+
```
38+
39+
This copies the statusline script to `~/.claude/bin/statusline.sh` and configures `~/.claude/settings.json`. Restart Claude Code for the statusline to appear.
40+
41+
### Manual setup
42+
43+
1. Copy `bin/statusline.sh` to `~/.claude/bin/statusline.sh`
44+
2. Make it executable: `chmod +x ~/.claude/bin/statusline.sh`
45+
3. Add to `~/.claude/settings.json`:
46+
47+
```json
48+
{
49+
"statusLine": {
50+
"command": "bash ~/.claude/bin/statusline.sh"
51+
}
52+
}
53+
```
54+
55+
## Requirements
56+
57+
- `bash` 4+
58+
- `jq`
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/usr/bin/env bash
2+
# itkdev-statusline: Claude Code statusline showing git branch, plan progress, and context usage.
3+
# Reads JSON from stdin (context_window.used_percentage, cwd).
4+
# Target: <30ms execution, no unnecessary subprocesses.
5+
6+
set -euo pipefail
7+
8+
# Parse cwd and used_percentage from stdin JSON via a single jq call.
9+
# Use parameter expansion to split on tab (read strips leading IFS chars).
10+
tsv=$(jq -r '[(.cwd // ""), (.context_window.used_percentage // 0), (.transcript_path // "")] | @tsv' 2>/dev/null) || true
11+
cwd="${tsv%%$'\t'*}"
12+
rest="${tsv#*$'\t'}"
13+
pct="${rest%%$'\t'*}"
14+
transcript="${rest#*$'\t'}"
15+
16+
# Bail if we got nothing useful.
17+
[[ -z "${cwd:-}" ]] && exit 0
18+
19+
pct="${pct%%.*}" # truncate to integer
20+
pct="${pct:-0}"
21+
22+
segments=()
23+
24+
# ── Git branch ─────────────────────────────────────────────────────────
25+
head_file="${cwd}/.git/HEAD"
26+
if [[ -f "$head_file" ]]; then
27+
head_content=$(<"$head_file")
28+
if [[ "$head_content" == ref:\ * ]]; then
29+
branch="${head_content#ref: refs/heads/}"
30+
else
31+
branch="${head_content:0:7}" # detached HEAD — short hash
32+
fi
33+
segments+=("$branch")
34+
fi
35+
36+
# ── Plan progress ──────────────────────────────────────────────────────
37+
plan_dir="${cwd}/docs/plans"
38+
if [[ -d "$plan_dir" ]]; then
39+
# Find the newest non-VERIFIED plan file.
40+
newest_plan=""
41+
for f in "$plan_dir"/*.md; do
42+
[[ -f "$f" ]] || continue
43+
# Skip files whose first line contains VERIFIED.
44+
first_line=$(head -1 "$f" 2>/dev/null)
45+
if [[ "$first_line" == *VERIFIED* ]]; then
46+
continue
47+
fi
48+
# Pick the most recently modified file.
49+
if [[ -z "$newest_plan" || "$f" -nt "$newest_plan" ]]; then
50+
newest_plan="$f"
51+
fi
52+
done
53+
54+
if [[ -n "$newest_plan" ]]; then
55+
# Count checkboxes.
56+
total=$(grep -cE '^\s*- \[(x| )\]' "$newest_plan" 2>/dev/null || true)
57+
done=$(grep -cE '^\s*- \[x\]' "$newest_plan" 2>/dev/null || true)
58+
total="${total:-0}"
59+
done="${done:-0}"
60+
if (( total > 0 )); then
61+
segments+=("${done}/${total}")
62+
fi
63+
fi
64+
fi
65+
66+
# ── Task progress (from transcript) ───────────────────────────────────
67+
if [[ -n "${transcript:-}" && -f "$transcript" ]]; then
68+
task_counts=$(grep -E 'TaskCreate|TaskUpdate' "$transcript" 2>/dev/null | \
69+
jq -sr '
70+
[.[].message.content[]? |
71+
select(.type == "tool_use") |
72+
select(.name == "TaskCreate" or .name == "TaskUpdate")] |
73+
([.[] | select(.name == "TaskCreate")] | length) as $total |
74+
([.[] | select(.name == "TaskUpdate") | select(.input.taskId)] |
75+
group_by(.input.taskId) | map(last | .input.status)) as $states |
76+
($states | map(select(. == "deleted")) | length) as $deleted |
77+
($states | map(select(. == "completed")) | length) as $done |
78+
"\($done) \($total - $deleted)"
79+
' 2>/dev/null) || true
80+
if [[ -n "$task_counts" ]]; then
81+
task_done="${task_counts%% *}"
82+
task_total="${task_counts##* }"
83+
if (( task_total > 0 )); then
84+
segments+=("${task_done}/${task_total}")
85+
fi
86+
fi
87+
fi
88+
89+
# ── Context window progress bar ───────────────────────────────────────
90+
filled=$(( pct / 10 ))
91+
empty=$(( 10 - filled ))
92+
bar=""
93+
for (( i = 0; i < filled; i++ )); do bar+=""; done
94+
for (( i = 0; i < empty; i++ )); do bar+=""; done
95+
96+
# ANSI colors: default < 80%, yellow 80-89%, red 90%+.
97+
reset=$'\033[0m'
98+
if (( pct >= 90 )); then
99+
ctx_segment=$'\033[31m'"${bar} ${pct}%${reset}"
100+
elif (( pct >= 80 )); then
101+
ctx_segment=$'\033[33m'"${bar} ${pct}%${reset}"
102+
else
103+
ctx_segment="${bar} ${pct}%"
104+
fi
105+
segments+=("$ctx_segment")
106+
107+
# ── Assemble output ───────────────────────────────────────────────────
108+
output=""
109+
for (( i = 0; i < ${#segments[@]}; i++ )); do
110+
(( i > 0 )) && output+=""
111+
output+="${segments[i]}"
112+
done
113+
printf '%s' "$output"
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
allowed-tools:
3+
- Bash
4+
- Read
5+
- Edit
6+
- Write
7+
---
8+
9+
# Setup itkdev-statusline
10+
11+
Install the statusline script and configure Claude Code to use it.
12+
13+
## Steps
14+
15+
1. **Copy the statusline script** to `~/.claude/bin/statusline.sh`:
16+
- Create `~/.claude/bin/` if it does not exist
17+
- Copy the `bin/statusline.sh` file from this plugin's directory to `~/.claude/bin/statusline.sh`
18+
- Make it executable (`chmod +x`)
19+
20+
2. **Update `~/.claude/settings.json`** to set the `statusLine` command:
21+
- Read the existing `~/.claude/settings.json` (create it if missing)
22+
- Set `"statusLine"` to `{"command": "bash ~/.claude/bin/statusline.sh"}`
23+
- Preserve all other existing settings
24+
25+
3. **Confirm to the user** that setup is complete and they should restart Claude Code for the statusline to appear.
26+
27+
## Important
28+
29+
- Use the `statusline-setup` subagent type if available, otherwise perform the steps directly.
30+
- The script path `~/.claude/bin/statusline.sh` is stable across plugin version updates.
31+
- Do NOT modify the statusline script itself — only copy it.

0 commit comments

Comments
 (0)