Skip to content

Commit 3d446a6

Browse files
committed
feat(plugin): auto-install statusLine, tmux sidebar, and config update
- Add _install_statusline() to auto-copy codingbuddy-hud.py and register in settings.json, replacing OMC while preserving custom statusLines - Add _setup_tmux_sidebar() with $TMUX detection, duplicate pane prevention, and i18n suggestion messages (en/ko) for non-tmux users - Add _get_plugin_version() to read version from plugin.json dynamically - Set CODINGBUDDY_AUTO_TUI=0 to disable standalone TUI auto-launch - Wire Steps 2.5, 4.5, 6.5 into session-start main() flow - Add 15 tests (9 install + 6 tmux), all passing Closes #1089 Closes #1091 Closes #1092
1 parent 1075b2b commit 3d446a6

4 files changed

Lines changed: 618 additions & 0 deletions

File tree

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
# Wave 3: Auto-Install StatusLine + tmux Sidebar + Config Change
2+
3+
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4+
5+
**Goal:** Wire up statusLine auto-installation in session-start, add tmux sidebar auto-setup, and set `CODINGBUDDY_AUTO_TUI=0`. All changes are in `session-start.py`.
6+
7+
**Architecture:** Three new functions added to `session-start.py`, inserted as Step 2.5, Step 4.5, and Step 6.5 in the existing `main()` flow.
8+
9+
**Tech Stack:** Python 3, shutil, subprocess, json
10+
11+
**Issues:** #1089, #1091, #1092
12+
13+
## Alternatives
14+
15+
### Decision: HUD script source discovery
16+
17+
| Criteria | Reuse find_plugin_source() with param | Separate find function |
18+
|---|---|---|
19+
| DRY | Reuses existing 3-tier search | Duplicates logic |
20+
| Flexibility | Need to parameterize filename | Hardcoded to one file |
21+
| Risk | Changing shared function may break hook install | Isolated |
22+
23+
**Decision:** Separate helper `_find_hud_source()` that follows the same 3-tier pattern but searches for `codingbuddy-hud.py`. Simpler and zero risk to existing hook installation.
24+
25+
---
26+
27+
## Part A: #1089 — Auto-Install StatusLine
28+
29+
### Step A1: Write test — `_install_statusline`
30+
31+
**File:** `packages/claude-code-plugin/tests/test_session_start_hud.py`
32+
33+
Tests:
34+
- `test_installs_hud_script_to_claude_hud_dir` — copies file, sets permissions
35+
- `test_sets_statusline_in_settings` — writes statusLine config
36+
- `test_replaces_omc_statusline` — replaces omc-hud with codingbuddy-hud
37+
- `test_skips_custom_statusline` — preserves non-OMC custom statusLine
38+
- `test_skips_if_already_installed` — no-op when codingbuddy-hud already set
39+
- `test_sets_auto_tui_to_zero` — changes CODINGBUDDY_AUTO_TUI from 1 to 0
40+
41+
### Step A2: Implement `_find_hud_source()`
42+
43+
Same 3-tier search as `find_plugin_source()` but for `codingbuddy-hud.py`:
44+
1. `CLAUDE_PLUGIN_DIR` env → `hooks/codingbuddy-hud.py`
45+
2. Plugin cache paths → `hooks/codingbuddy-hud.py`
46+
3. Dev paths → `hooks/codingbuddy-hud.py`
47+
48+
### Step A3: Implement `_install_statusline(home, settings_file)`
49+
50+
```python
51+
def _install_statusline(home: Path, settings_file: Path) -> None:
52+
"""Install codingbuddy statusLine and set CODINGBUDDY_AUTO_TUI=0."""
53+
# 1. Find source
54+
source = _find_hud_source()
55+
if not source:
56+
return
57+
58+
# 2. Copy to ~/.claude/hud/
59+
hud_dir = home / ".claude" / "hud"
60+
hud_dir.mkdir(parents=True, exist_ok=True)
61+
target = hud_dir / "codingbuddy-hud.py"
62+
shutil.copy(source, target)
63+
target.chmod(0o755)
64+
65+
# 3. Update settings.json
66+
settings = _read_settings_file(settings_file) if settings_file.exists() else {}
67+
68+
# Check existing statusLine
69+
current_sl = settings.get("statusLine", {}).get("command", "")
70+
if "codingbuddy-hud" in current_sl:
71+
pass # already installed
72+
elif "omc-hud" in current_sl or not current_sl:
73+
settings["statusLine"] = {
74+
"type": "command",
75+
"command": f'python3 "{home}/.claude/hud/codingbuddy-hud.py"'
76+
}
77+
# else: custom statusLine, preserve
78+
79+
# 4. Set CODINGBUDDY_AUTO_TUI=0 (#1092)
80+
env = settings.setdefault("env", {})
81+
if env.get("CODINGBUDDY_AUTO_TUI") == "1":
82+
env["CODINGBUDDY_AUTO_TUI"] = "0"
83+
84+
_write_settings_file(settings_file, settings)
85+
```
86+
87+
### Step A4: Wire into `main()` as Step 2.5
88+
89+
After line 492 (after status message), before Step 3:
90+
```python
91+
# Step 2.5: Install codingbuddy statusLine (#1089, #1092)
92+
try:
93+
_install_statusline(home, settings_file)
94+
except Exception:
95+
pass
96+
```
97+
98+
### Step A5: Implement Step 4.5 — Init HUD state
99+
100+
After line 525 (after stats init):
101+
```python
102+
# Step 4.5: Initialize HUD state (#1089)
103+
try:
104+
_ensure_lib_path()
105+
from hud_state import init_hud_state
106+
from session_utils import get_session_id as _get_sid_hud
107+
init_hud_state(_get_sid_hud(), "5.1.1")
108+
except Exception:
109+
pass
110+
```
111+
112+
---
113+
114+
## Part B: #1091 — tmux Sidebar Auto-Setup
115+
116+
### Step B1: Write test — tmux detection + sidebar
117+
118+
**File:** `packages/claude-code-plugin/tests/test_tmux_sidebar.py`
119+
120+
Tests:
121+
- `test_detects_tmux_env` — returns True when $TMUX set
122+
- `test_no_tmux_env` — returns False when $TMUX unset
123+
- `test_sidebar_pane_exists_detection` — detects existing codingbuddy pane
124+
- `test_prints_tmux_suggestion_when_not_in_tmux` — outputs tip message
125+
126+
### Step B2: Implement `_setup_tmux_sidebar()`
127+
128+
```python
129+
import subprocess
130+
131+
TMUX_SUGGESTION = {
132+
"en": (
133+
"╭───────────────────────────────────────────────╮\n"
134+
"│ ◕‿◕ Tip: Run Claude Code inside tmux for │\n"
135+
"│ the full CodingBuddy sidebar experience! │\n"
136+
"│ │\n"
137+
"│ tmux new -s dev │\n"
138+
"│ claude │\n"
139+
"╰───────────────────────────────────────────────╯"
140+
),
141+
"ko": (
142+
"╭───────────────────────────────────────────────╮\n"
143+
"│ ◕‿◕ Tip: tmux 안에서 Claude Code를 실행하면 │\n"
144+
"│ CodingBuddy 사이드바를 볼 수 있어요! │\n"
145+
"│ │\n"
146+
"│ tmux new -s dev │\n"
147+
"│ claude │\n"
148+
"╰───────────────────────────────────────────────╯"
149+
),
150+
}
151+
152+
def _sidebar_pane_exists() -> bool:
153+
try:
154+
result = subprocess.run(
155+
["tmux", "list-panes", "-F", "#{pane_current_command}"],
156+
capture_output=True, text=True, timeout=2,
157+
)
158+
return "codingbuddy" in result.stdout
159+
except Exception:
160+
return False
161+
162+
def _setup_tmux_sidebar() -> None:
163+
if not os.environ.get("TMUX"):
164+
# Print suggestion
165+
lang = _get_cached_language()
166+
tip = TMUX_SUGGESTION.get(lang, TMUX_SUGGESTION["en"])
167+
print(tip, file=sys.stderr)
168+
return
169+
170+
if _sidebar_pane_exists():
171+
return
172+
173+
subprocess.Popen(
174+
["tmux", "split-window", "-h", "-l", "25%", "-d", "codingbuddy", "tui"],
175+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
176+
)
177+
subprocess.Popen(
178+
["tmux", "select-pane", "-L"],
179+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
180+
)
181+
```
182+
183+
### Step B3: Wire into `main()` as Step 6.5
184+
185+
After buddy greeting (end of Step 6):
186+
```python
187+
# Step 6.5: tmux sidebar auto-setup (#1091)
188+
try:
189+
_setup_tmux_sidebar()
190+
except Exception:
191+
pass
192+
```
193+
194+
---
195+
196+
## Execution Order
197+
198+
1. Write tests (A1 + B1)
199+
2. Implement functions (A2-A5 + B2-B3)
200+
3. Run all tests
201+
4. Commit + ship
202+
203+
## Files Modified
204+
205+
| File | Changes |
206+
|------|---------|
207+
| `hooks/session-start.py` | Add `_find_hud_source`, `_install_statusline`, `_setup_tmux_sidebar`, `_sidebar_pane_exists`, `TMUX_SUGGESTION` + wire Steps 2.5, 4.5, 6.5 |
208+
| `tests/test_session_start_hud.py` | NEW — statusLine install tests |
209+
| `tests/test_tmux_sidebar.py` | NEW — tmux detection tests |
210+
211+
## Verification
212+
213+
1. `python3 -m pytest tests/test_session_start_hud.py tests/test_tmux_sidebar.py -v`
214+
2. `python3 -m pytest tests/ -q` (full regression)
215+
3. Manual: Start new Claude Code session → check `~/.claude/settings.json` statusLine
216+
4. Manual (tmux): Start Claude Code in tmux → verify sidebar pane appears

0 commit comments

Comments
 (0)