Skip to content

Commit 8c73918

Browse files
committed
feat: add plugin system for custom segments
1 parent 9eb0ebd commit 8c73918

3 files changed

Lines changed: 255 additions & 125 deletions

File tree

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ Key sections in `claude-code-status-line.py` (~2,200 lines):
7373
- **Usage data source**: CC 2.1.80+ sends `rate_limits` in stdin JSON (preferred). Falls back to deprecated OAuth API (`fetch_usage_data()`) for older CC versions. OAuth path (`get_oauth_token()`, `USAGE_CACHE_PATH`, `SL_USAGE_CACHE_DURATION`) will be removed in a future version.
7474
- **Credential sources**: macOS Keychain (`security` command) → `~/.claude/.credentials.json` fallback (deprecated, only used by OAuth fallback).
7575
- **Cache writes**: atomic via `tempfile.mkstemp()` + `os.replace()` with temp file cleanup on failure.
76+
- **Plugin system**: auto-discovers `.py` files in `.claude/statusline/` (project-level, cwd-relative) and `~/.claude/statusline/` (global). Each plugin defines `register(api)` where `api` provides `add_segment(name, renderer, defaults)`, `fg(color)`, `bg(color)`, `text_color(key)`, `RESET`, `BOLD`. Registered segments become valid in `SL_SEGMENTS`. Plugin errors are silently ignored. The `ctx` dict passed to renderers includes `data` (raw JSON from Claude Code stdin) so plugins can access `session_id`, `cwd`, and other fields.
7677
- **No type hints** per project convention — uses f-strings throughout.
7778
- **Effort level limitations**: The statusline JSON from Claude Code does NOT include effort level. The `model:effort` option reads from settings files as a workaround. Known gaps:
7879
- `max` is session-only (never written to disk) — undetectable

README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ A statusline script for [Claude Code](https://docs.anthropic.com/en/docs/claude-
2727
- **Usage** tracking both 5-hour and 7-day window showing what needs to be known (how much, to when and how much you're burning through them)
2828
- **Dark and light theme** support (Nord-inspired palette) with option to customize.
2929
- **Truecolor (24-bit)** with automatic 256-color fallback
30+
- **Plugin system** for custom segments
3031
- **Customization of what is shown and how**
3132

3233
## Installation
@@ -335,6 +336,53 @@ Countdown omits the renewal gap when it rounds to ≤ 1 hour. Color-coded: orang
335336

336337
The script checks the `COLORTERM` environment variable for `truecolor` or `24bit`. If present, it uses 24-bit RGB colors. Otherwise, it falls back to 256-color mode using the fallback values defined in the theme.
337338

339+
## Plugins
340+
341+
Extend the statusline with custom segments by dropping `.py` files into plugin directories:
342+
343+
1. **Project-level:** `.claude/statusline/` (relative to cwd)
344+
2. **Global:** `~/.claude/statusline/`
345+
346+
Each plugin defines a `register(api)` function that registers one or more segments:
347+
348+
```python
349+
# ~/.claude/statusline/session.py
350+
351+
def register(api):
352+
def render_session(ctx, opts):
353+
session_id = ctx["data"].get("session_id", "")
354+
if not session_id:
355+
return ""
356+
short = session_id[:8]
357+
color = api.fg("#88C0D0")
358+
return f" {color}{short}{api.RESET}"
359+
360+
api.add_segment("session", render_session)
361+
```
362+
363+
Enable the segment via `SL_SEGMENTS`:
364+
365+
```
366+
SL_SEGMENTS="model progress_bar percentage session directory git_branch"
367+
```
368+
369+
### Plugin API
370+
371+
| Method | Description |
372+
|---|---|
373+
| `api.add_segment(name, renderer, defaults=None)` | Register a segment. `renderer(ctx, opts) -> str` |
374+
| `api.fg(color)` | Foreground ANSI code. `"#RRGGBB"` (truecolor with 256 fallback) or `int` (256-color) |
375+
| `api.bg(color)` | Background ANSI code. Same formats |
376+
| `api.text_color(key)` | Themed text color by key (e.g. `"percent"`, `"cwd"`, `"git"`) |
377+
| `api.RESET` | ANSI reset escape |
378+
| `api.BOLD` | ANSI bold escape |
379+
380+
The `ctx` dict passed to renderers includes all standard fields (model, cwd, pct, tokens, usage data) plus `data` — the raw JSON input from Claude Code, giving access to `session_id`, `cwd`, and other fields.
381+
382+
The `opts` dict contains per-segment options from `SL_SEGMENTS` colon syntax (e.g. `session:short=1``opts = {"short": "1"}`). Use `defaults` in `add_segment()` to set fallback values.
383+
384+
Plugin errors are silently ignored — a broken plugin never breaks the statusline.
385+
338386
## Contributing
339387

340388
This is a personal tool that I built for my own workflow. You're welcome to fork it and adapt it to your needs.

0 commit comments

Comments
 (0)