Skip to content

Commit 2d3c44e

Browse files
authored
feat!: standardize on claude-code-statusline and self-install (#39)
Makes `uvx claude-code-statusline install` a one-command, ai-rules-free way to install the statusline and wire it into `~/.claude/settings.json`. The console command, its config dir, and the `settings.json` command value were the lone `claude-statusline` outliers while the PyPI package and import module are already `claude-code-statusline`, so `uvx claude-code-statusline …` couldn't resolve. Standardizing on the single name lets the one entry point resolve under `uvx`, and self-installing on `install` keeps an ephemeral `uvx` run from leaving a dangling command behind. - Rename the sole console entry point and every `claude-statusline` reference (source, scripts, docs, tests) to `claude-code-statusline`; the config dir moves to `~/.config/claude-code-statusline/`. - `install` now self-installs the tool via `uv tool`/`pipx` when the command isn't already on `PATH`, then writes the `statusLine` config. - Migrate an existing `~/.config/claude-statusline/config.yaml` on `install`; `doctor` flags a stale command value and the README gains an Upgrading note. BREAKING CHANGE: users on the old `claude-statusline` command must re-run `claude-code-statusline install` after upgrading (widget config migrates automatically). Related: [ai-agent-rules#177](wpfleger96/ai-agent-rules#177)
1 parent 32d04d2 commit 2d3c44e

15 files changed

Lines changed: 272 additions & 57 deletions

File tree

AGENTS.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ uv run pytest -m integration # Integration tests only
3232
uv run pytest -m performance # Performance benchmarks (opt-in)
3333

3434
# CLI testing (local development)
35-
uv run claude-statusline # Test with stdin
36-
echo '{"transcript_path": "..."}' | uv run claude-statusline
37-
uv run claude-statusline install # Install local version to Claude Code
38-
uv run claude-statusline doctor # Verify installation health
39-
uv run claude-statusline --version # Show version
35+
uv run claude-code-statusline # Test with stdin
36+
echo '{"transcript_path": "..."}' | uv run claude-code-statusline
37+
uv run claude-code-statusline install # Install local version to Claude Code
38+
uv run claude-code-statusline doctor # Verify installation health
39+
uv run claude-code-statusline --version # Show version
4040

4141
# Installation scripts (for end users)
4242
curl -fsSL https://raw.githubusercontent.com/wpfleger96/claude-code-status-line/main/scripts/install.sh | bash
@@ -111,10 +111,10 @@ Fixtures in `tests/conftest.py`: `mock_stdin`, `sample_input_payload`, `basic_se
111111

112112
## Common Gotchas
113113

114-
1. **Local dev vs installed tool** - **CRITICAL**: Always use `uv run claude-statusline` when developing locally:
115-
- **Local dev (from repo)**: `uv run claude-statusline <args>` → runs YOUR local code changes
116-
- **Installed tool (any directory)**: `claude-statusline <args>` → runs installed version from `~/.local/share/uv/tools/`
117-
- Running `claude-statusline` without `uv run` will NOT reflect local changes
114+
1. **Local dev vs installed tool** - **CRITICAL**: Always use `uv run claude-code-statusline` when developing locally:
115+
- **Local dev (from repo)**: `uv run claude-code-statusline <args>` → runs YOUR local code changes
116+
- **Installed tool (any directory)**: `claude-code-statusline <args>` → runs installed version from `~/.local/share/uv/tools/`
117+
- Running `claude-code-statusline` without `uv run` will NOT reflect local changes
118118
- **NEVER use editable install** (`uv pip install -e .`) - risks conflicts, unnecessary complexity
119119

120120
2. **Context window priority** (Claude Code 2.0.70+): `context_window` field from payload takes priority over transcript parsing for token counts. Falls back to transcript if `context_window` missing/null. This is the authoritative source.
@@ -129,7 +129,7 @@ Fixtures in `tests/conftest.py`: `mock_stdin`, `sample_input_payload`, `basic_se
129129

130130
7. **Performance tests opt-in**: Excluded by default. Run with `uv run pytest -m performance`.
131131

132-
8. **Installation scripts handle both uv and pipx**: `scripts/install.sh` checks for uv first, falls back to pipx. Auto-configures Claude Code with `claude-statusline install --yes`.
132+
8. **Installation scripts handle both uv and pipx**: `scripts/install.sh` checks for uv first, falls back to pipx. Auto-configures Claude Code with `claude-code-statusline install --yes`.
133133

134134
9. **Debug logging per-session**: Set `CLAUDE_CODE_STATUSLINE_DEBUG=1` → creates `logs/statusline_debug_<session_id>.log` with token breakdown, compact boundaries, parsing errors.
135135

README.md

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,28 @@ This will:
5959

6060
**Requirements:** Either `uv` or `pipx`
6161

62+
Or, if you have [`uv`](https://docs.astral.sh/uv/), install and configure in a single command:
63+
64+
```bash
65+
uvx claude-code-statusline install
66+
```
67+
68+
This installs the tool persistently (via `uv tool`) and then writes the `statusLine` config to `~/.claude/settings.json`.
69+
6270
### Manual Installation
6371

6472
#### Option 1: Using uv tool
6573

6674
```bash
6775
uv tool install claude-code-statusline
68-
claude-statusline install
76+
claude-code-statusline install
6977
```
7078

7179
#### Option 2: Using pipx
7280

7381
```bash
7482
pipx install claude-code-statusline
75-
claude-statusline install
83+
claude-code-statusline install
7684
```
7785

7886
### Upgrading
@@ -87,6 +95,8 @@ uv tool upgrade claude-code-statusline
8795
pipx upgrade claude-code-statusline
8896
```
8997

98+
> **Upgrading from a version that used the `claude-statusline` command?** The command was renamed to `claude-code-statusline`. After upgrading, re-run `claude-code-statusline install` to update `~/.claude/settings.json` — your `~/.config` widget config is migrated automatically. If a stale `claude-statusline` command lingers on your `PATH`, run `uv tool uninstall claude-code-statusline` (or `pipx uninstall claude-code-statusline`) and reinstall.
99+
90100
### Uninstalling
91101

92102
To uninstall:
@@ -96,26 +106,26 @@ To uninstall:
96106
curl -fsSL https://raw.githubusercontent.com/wpfleger96/claude-code-status-line/main/scripts/uninstall.sh | bash
97107

98108
# Or manually
99-
claude-statusline uninstall
109+
claude-code-statusline uninstall
100110
uv tool uninstall claude-code-statusline # or: pipx uninstall claude-code-statusline
101111
```
102112

103113
## CLI Commands
104114

105115
```bash
106-
claude-statusline # Output statusline (reads JSON from stdin)
107-
claude-statusline install # Configure Claude Code integration
108-
claude-statusline uninstall # Remove Claude Code configuration
109-
claude-statusline doctor # Verify installation health
110-
claude-statusline --version # Show version
116+
claude-code-statusline # Output statusline (reads JSON from stdin)
117+
claude-code-statusline install # Configure Claude Code integration
118+
claude-code-statusline uninstall # Remove Claude Code configuration
119+
claude-code-statusline doctor # Verify installation health
120+
claude-code-statusline --version # Show version
111121
```
112122

113123
### Health Check
114124

115125
Verify your installation is working correctly:
116126

117127
```bash
118-
claude-statusline doctor
128+
claude-code-statusline doctor
119129
```
120130

121131
This checks:
@@ -128,7 +138,7 @@ This checks:
128138

129139
### Widget Customization
130140

131-
Customize your status line by creating `~/.config/claude-statusline/config.yaml`:
141+
Customize your status line by creating `~/.config/claude-code-statusline/config.yaml`:
132142

133143
```yaml
134144
version: 2
@@ -156,12 +166,12 @@ widgets:
156166
**Color Options:** `white`, `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `dim`, `auto`, `none`
157167

158168
**Default Config:**
159-
If no config file exists, all default widgets are shown with built-in defaults. Create `~/.config/claude-statusline/config.yaml` to customize colors, ordering, or disable specific widgets.
169+
If no config file exists, all default widgets are shown with built-in defaults. Create `~/.config/claude-code-statusline/config.yaml` to customize colors, ordering, or disable specific widgets.
160170

161171
## Features
162172

163173
### Customizable Widget System
164-
- **Configurable Layout**: Customize which widgets appear and in what order via `~/.config/claude-statusline/config.yaml`
174+
- **Configurable Layout**: Customize which widgets appear and in what order via `~/.config/claude-code-statusline/config.yaml`
165175
- **Built-in Widgets**: 14 widgets including model, directory, git status, context, cost, session info
166176
- **Flexible Styling**: Per-widget color customization and bold formatting
167177
- **Automatic Fallback**: Missing config uses sensible defaults with all widgets enabled
@@ -341,14 +351,14 @@ Debug logs are written to **per-session files** in the `logs/` directory:
341351

342352
2. **Configure Claude Code to use local version:**
343353
```bash
344-
uv run claude-statusline install
354+
uv run claude-code-statusline install
345355
```
346356

347357
### Testing Changes
348358

349359
```bash
350360
# Test statusline output
351-
echo '{"workspace": {"current_dir": "/test"}, "transcript_path": "", "model": {"id": "test", "display_name": "Test"}, "cost": {}, "version": "test"}' | uv run claude-statusline
361+
echo '{"workspace": {"current_dir": "/test"}, "transcript_path": "", "model": {"id": "test", "display_name": "Test"}, "cost": {}, "version": "test"}' | uv run claude-code-statusline
352362

353363
# Run test suite
354364
uv run pytest

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Documentation = "https://github.com/wpfleger96/claude-code-status-line#readme"
2323
Changelog = "https://github.com/wpfleger96/claude-code-status-line/blob/main/CHANGELOG.md"
2424

2525
[project.scripts]
26-
claude-statusline = "claude_code_statusline.statusline:main"
26+
claude-code-statusline = "claude_code_statusline.statusline:main"
2727

2828
[dependency-groups]
2929
dev = [

scripts/install.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ echo "Package installed successfully!"
4545
echo ""
4646
echo "Configuring Claude Code..."
4747

48-
if ! claude-statusline install --yes; then
48+
if ! claude-code-statusline install --yes; then
4949
echo ""
5050
echo "Error: Configuration failed"
51-
echo "You can try manually running: claude-statusline install"
51+
echo "You can try manually running: claude-code-statusline install"
5252
exit 1
5353
fi
5454

@@ -58,7 +58,7 @@ echo ""
5858
echo "Next steps:"
5959
echo "1. Restart Claude Code or start a new session"
6060
echo "2. The statusline should appear automatically"
61-
echo "3. Customize via ~/.config/claude-statusline/config.yaml"
61+
echo "3. Customize via ~/.config/claude-code-statusline/config.yaml"
6262
echo ""
6363
echo "For more information, visit:"
6464
echo " https://github.com/wpfleger96/claude-code-status-line"

scripts/uninstall.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
set -e
44

55
PACKAGE_NAME="claude-code-statusline"
6-
CONFIG_DIR="$HOME/.config/claude-statusline"
6+
CONFIG_DIR="$HOME/.config/claude-code-statusline"
77

88
echo "Uninstalling $PACKAGE_NAME..."
99
echo ""
@@ -13,17 +13,17 @@ if [ "$1" = "--purge" ]; then
1313
PURGE=1
1414
fi
1515

16-
if command -v claude-statusline &> /dev/null; then
16+
if command -v claude-code-statusline &> /dev/null; then
1717
echo "Removing statusLine configuration..."
18-
if claude-statusline uninstall; then
18+
if claude-code-statusline uninstall; then
1919
echo ""
2020
else
2121
echo "Warning: Failed to remove statusLine configuration"
2222
echo "You may need to manually edit ~/.claude/settings.json"
2323
echo ""
2424
fi
2525
else
26-
echo "claude-statusline command not found"
26+
echo "claude-code-statusline command not found"
2727
echo "Skipping configuration cleanup"
2828
echo ""
2929
fi

src/claude_code_statusline/cli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""CLI commands for claude-statusline."""
1+
"""CLI commands for claude-code-statusline."""
22

33
from .commands import cmd_doctor, cmd_install, cmd_uninstall
44

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""Persistent-install bootstrap for the statusline command.
2+
3+
When invoked ephemerally (e.g. ``uvx claude-code-statusline install``) the console
4+
script is not on the user's PATH, so the ``statusLine`` command written into
5+
settings.json would point at a missing binary. ``ensure_command_installed`` installs
6+
the tool persistently (via ``uv tool`` or ``pipx``) before Claude Code is configured,
7+
mirroring the detection in scripts/install.sh.
8+
"""
9+
10+
import shutil
11+
import subprocess
12+
13+
NAME = "claude-code-statusline"
14+
15+
16+
def ensure_command_installed() -> tuple[bool, str]:
17+
"""Ensure the ``claude-code-statusline`` command is persistently on PATH.
18+
19+
Returns a ``(ok, message)`` pair. ``ok`` is False only for hard failures (no
20+
installer found, or the install command failed); callers should abort before
21+
writing settings.json. A successful no-op returns ``(True, "")``. If the tool
22+
was installed but is not yet visible on PATH, returns ``(True, warning)`` so the
23+
caller can still write the config (a fresh shell/session resolves it).
24+
"""
25+
if shutil.which(NAME):
26+
return True, ""
27+
28+
if shutil.which("uv"):
29+
installer, command = "uv", ["uv", "tool", "install", NAME]
30+
elif shutil.which("pipx"):
31+
installer, command = "pipx", ["pipx", "install", NAME]
32+
else:
33+
return False, (
34+
f"'{NAME}' is not on PATH and neither 'uv' nor 'pipx' was found.\n"
35+
f"Install uv (https://astral.sh/uv) or run: pipx install {NAME}"
36+
)
37+
38+
print(f"Installing {NAME} with {installer}...")
39+
try:
40+
subprocess.run(command, check=True)
41+
except (subprocess.CalledProcessError, OSError) as e:
42+
return False, f"Failed to install {NAME} via {installer}: {e}"
43+
44+
if shutil.which(NAME):
45+
return True, f"Installed {NAME} via {installer}."
46+
return True, (
47+
f"Installed {NAME} via {installer}, but '{NAME}' is not yet on PATH. "
48+
f"Restart your shell (or run 'uv tool update-shell') so Claude Code can find it."
49+
)

0 commit comments

Comments
 (0)