Skip to content

Commit c4557d4

Browse files
HumanBean17claude
andcommitted
fix(cli install): resolve tuple unpacking bug and UX issues
Fixes #291 - CLI install command bugs: 1. Fix "Index already exists" false positive: - Properly unpack tuple from index_dir_has_existing_artifacts() - Function returns tuple[bool, list[str]], not bool - Prevents always-true condition causing incorrect messages 2. Fix UI visibility on white/light terminal themes: - Add custom questionary styles with bold/blue colors - Selected items now visible on both light and dark backgrounds - Added underline for highlighted items 3. Fix UX confusion with agent host selection: - Changed from pre-selecting ALL hosts to only claude-code - Added help message explaining multi-select behavior - Added confirmation showing what will be deployed 4. Improve scope selection clarity: - Added explanatory notes about project vs user scope - Added confirmation message showing selected scope All 53 installer tests pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent aaaf7fe commit c4557d4

1 file changed

Lines changed: 33 additions & 7 deletions

File tree

java_codebase_rag/installer.py

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,16 +111,31 @@ def prompt(
111111

112112
# Lazy import questionary only when needed (TTY)
113113
import questionary
114+
from prompt_toolkit.styles import Style
115+
116+
# Custom style for better visibility on both light and dark backgrounds
117+
# Uses bold and darker colors (blue/cyan) which work well on white backgrounds
118+
custom_style = Style(
119+
[
120+
("qmark", "fg:cyan bold"), # Question mark '?'
121+
("question", "bold"), # Question text
122+
("answer", "fg:blue bold"), # Selected answer (darker blue for white bg)
123+
("pointer", "fg:cyan bold"), # Selection pointer '>'
124+
("selected", "fg:blue bold"), # Selected item in checkbox
125+
("highlighted", "fg:blue underline"), # Highlighted item with underline
126+
("instruction", "dim"), # Instruction text
127+
]
128+
)
114129

115130
try:
116131
if prompt_type == "checkbox":
117-
return questionary.checkbox(message, choices=choices).ask()
132+
return questionary.checkbox(message, choices=choices, style=custom_style).ask()
118133
elif prompt_type == "select":
119-
return questionary.select(message, choices=choices).ask()
134+
return questionary.select(message, choices=choices, style=custom_style).ask()
120135
elif prompt_type == "text":
121-
return questionary.text(message, default=default).ask()
136+
return questionary.text(message, default=default, style=custom_style).ask()
122137
elif prompt_type == "confirm":
123-
return questionary.confirm(message).ask()
138+
return questionary.confirm(message, style=custom_style).ask()
124139
else:
125140
raise ValueError(f"Unknown prompt_type: {prompt_type}")
126141
except KeyboardInterrupt:
@@ -279,10 +294,15 @@ def select_hosts(*, non_interactive: bool, cli_agents: list[str] | None) -> list
279294
print(f"Valid agents: {', '.join(HOSTS.keys())}")
280295
raise SystemExit(2)
281296

282-
# Interactive: show checkbox with all hosts pre-selected
297+
# Interactive: show checkbox with claude-code pre-selected (most common)
298+
# Changed from all pre-selected to avoid confusion
283299
host_names = list(HOSTS.keys())
284-
choices = [{"name": name, "value": name, "checked": True} for name in host_names]
300+
choices = [
301+
{"name": name, "value": name, "checked": (name == "claude-code")}
302+
for name in host_names
303+
]
285304

305+
print("Note: You can select multiple agent hosts with Space. Navigate with arrow keys.")
286306
selected = prompt("checkbox", "Select agent hosts to configure:", choices=choices)
287307

288308
if not selected:
@@ -296,6 +316,8 @@ def select_hosts(*, non_interactive: bool, cli_agents: list[str] | None) -> list
296316
else:
297317
raise SystemExit(2)
298318

319+
# Show confirmation of what will be deployed
320+
print(f"Will deploy to: {', '.join(selected)}")
299321
return [HOSTS[name] for name in selected]
300322

301323

@@ -319,6 +341,8 @@ def select_scope(*, non_interactive: bool, cli_scope: str | None) -> Scope:
319341
return "project"
320342

321343
# Interactive: prompt for scope
344+
print("Note: 'project' scope stores configs in the project directory.")
345+
print(" 'user' scope stores configs in your home directory.")
322346
selected = prompt(
323347
"select",
324348
"Select installation scope:",
@@ -328,6 +352,7 @@ def select_scope(*, non_interactive: bool, cli_scope: str | None) -> Scope:
328352
if not selected:
329353
return "project"
330354

355+
print(f"Selected scope: {selected}")
331356
return selected # type: ignore
332357

333358

@@ -738,7 +763,8 @@ def run_init_if_needed(
738763
)
739764
from java_codebase_rag.pipeline import run_build_ast_graph, run_cocoindex_update
740765

741-
if index_dir_has_existing_artifacts(index_dir):
766+
has_existing, _ = index_dir_has_existing_artifacts(index_dir)
767+
if has_existing:
742768
print("Index already exists. Run `java-codebase-rag reprocess` to rebuild.")
743769
return False
744770

0 commit comments

Comments
 (0)