Skip to content

Commit 36eb4bc

Browse files
authored
Merge pull request #27 from itk-dev/feature/itkdev-statusline
feat: add itkdev-statusline extension
2 parents abe5adc + 27b30c2 commit 36eb4bc

7 files changed

Lines changed: 265 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": "./extensions/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` extension with context window usage, git branch, and plan progress display
13+
1014
## [0.4.0] - 2026-02-20
1115

1216
### Added

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ itkdev-claude-plugins/
1818
├── agents/ # Agents (flat .md files)
1919
│ ├── itkdev-code-review.md
2020
│ └── itkdev-issue-workflow.md
21+
├── extensions/ # Extensions (standalone tools)
22+
│ └── itkdev-statusline/
2123
├── skills/ # Skills (subdirectories with SKILL.md)
2224
│ ├── itkdev-adr/
2325
│ ├── itkdev-documentation/
@@ -75,6 +77,12 @@ GitHub workflow guidelines for the ITK Dev team. Automatically activates when wo
7577

7678
Autonomous GitHub issue workflow. Works through GitHub issues with minimal user interaction — handling development, testing, review, and merge — only pausing when user review or merge approval is required.
7779

80+
## Included Extensions
81+
82+
### itkdev-statusline
83+
84+
Claude Code statusline displaying git branch, plan/task progress, and context window usage. Install with `/setup-statusline` after adding the marketplace. See [extensions/itkdev-statusline/README.md](extensions/itkdev-statusline/README.md) for details.
85+
7886
## Included Agents
7987

8088
### itkdev-code-review
@@ -168,6 +176,23 @@ description: When this skill should be activated automatically.
168176
Your skill instructions here...
169177
```
170178

179+
### Adding Extensions
180+
181+
Create a subdirectory in `extensions/` with its own `.claude-plugin/plugin.json` and any commands or scripts:
182+
183+
```
184+
extensions/
185+
└── your-extension-name/
186+
├── .claude-plugin/
187+
│ └── plugin.json
188+
├── bin/
189+
│ └── your-script.sh
190+
└── commands/
191+
└── setup-your-extension.md
192+
```
193+
194+
Extensions are standalone tools (statuslines, utilities, setup scripts) that don't fit the skill/agent/MCP categories but benefit from marketplace distribution.
195+
171196
### Adding Agents
172197

173198
Create a flat `.md` file in `agents/` with YAML frontmatter:
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: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
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+
if [[ -z "$(git -C "$cwd" status --porcelain 2>/dev/null)" ]]; then
34+
segments+=($'\033[32m'"${branch}"$'\033[0m') # green = clean
35+
else
36+
segments+=($'\033[31m'"${branch}"$'\033[0m') # red = dirty
37+
fi
38+
fi
39+
40+
# ── Plan progress ──────────────────────────────────────────────────────
41+
plan_dir="${cwd}/docs/plans"
42+
if [[ -d "$plan_dir" ]]; then
43+
# Find the newest non-VERIFIED plan file.
44+
newest_plan=""
45+
for f in "$plan_dir"/*.md; do
46+
[[ -f "$f" ]] || continue
47+
# Skip files whose first line contains VERIFIED.
48+
first_line=$(head -1 "$f" 2>/dev/null)
49+
if [[ "$first_line" == *VERIFIED* ]]; then
50+
continue
51+
fi
52+
# Pick the most recently modified file.
53+
if [[ -z "$newest_plan" || "$f" -nt "$newest_plan" ]]; then
54+
newest_plan="$f"
55+
fi
56+
done
57+
58+
if [[ -n "$newest_plan" ]]; then
59+
# Count checkboxes.
60+
total=$(grep -cE '^\s*- \[(x| )\]' "$newest_plan" 2>/dev/null || true)
61+
done=$(grep -cE '^\s*- \[x\]' "$newest_plan" 2>/dev/null || true)
62+
total="${total:-0}"
63+
done="${done:-0}"
64+
if (( total > 0 )); then
65+
if (( done == total )); then
66+
segments+=($'\033[32m'"${done}/${total}"$'\033[0m') # green = complete
67+
else
68+
segments+=("${done}/${total}")
69+
fi
70+
fi
71+
fi
72+
fi
73+
74+
# ── Task progress (from transcript) ───────────────────────────────────
75+
if [[ -n "${transcript:-}" && -f "$transcript" ]]; then
76+
task_counts=$(grep -E 'TaskCreate|TaskUpdate' "$transcript" 2>/dev/null | \
77+
jq -sr '
78+
[.[].message.content[]? |
79+
select(.type == "tool_use") |
80+
select(.name == "TaskCreate" or .name == "TaskUpdate")] |
81+
([.[] | select(.name == "TaskCreate")] | length) as $total |
82+
([.[] | select(.name == "TaskUpdate") | select(.input.taskId)] |
83+
group_by(.input.taskId) | map(last | .input.status)) as $states |
84+
($states | map(select(. == "deleted")) | length) as $deleted |
85+
($states | map(select(. == "completed")) | length) as $done |
86+
"\($done) \($total - $deleted)"
87+
' 2>/dev/null) || true
88+
if [[ -n "$task_counts" ]]; then
89+
task_done="${task_counts%% *}"
90+
task_total="${task_counts##* }"
91+
if (( task_total > 0 )); then
92+
if (( task_done == task_total )); then
93+
segments+=($'\033[32m'"${task_done}/${task_total}"$'\033[0m') # green = complete
94+
else
95+
segments+=("${task_done}/${task_total}")
96+
fi
97+
fi
98+
fi
99+
fi
100+
101+
# ── Context window progress bar ───────────────────────────────────────
102+
filled=$(( pct / 10 ))
103+
empty=$(( 10 - filled ))
104+
bar=""
105+
for (( i = 0; i < filled; i++ )); do bar+=""; done
106+
for (( i = 0; i < empty; i++ )); do bar+=""; done
107+
108+
# ANSI colors: default < 80%, yellow 80-89%, red 90%+.
109+
reset=$'\033[0m'
110+
if (( pct >= 90 )); then
111+
ctx_segment=$'\033[31m'"${bar} ${pct}%${reset}"
112+
elif (( pct >= 80 )); then
113+
ctx_segment=$'\033[33m'"${bar} ${pct}%${reset}"
114+
else
115+
ctx_segment="${bar} ${pct}%"
116+
fi
117+
segments+=("$ctx_segment")
118+
119+
# ── Assemble output ───────────────────────────────────────────────────
120+
output=""
121+
for (( i = 0; i < ${#segments[@]}; i++ )); do
122+
(( i > 0 )) && output+=""
123+
output+="${segments[i]}"
124+
done
125+
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)