Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ ACTION: Use Skill tool BEFORE responding
git clone https://github.com/parcadei/Continuous-Claude-v3.git
cd Continuous-Claude-v3/opc

# Run setup wizard (12 steps)
# Run setup wizard (15 steps)
uv run python -m scripts.setup.wizard
```

Expand All @@ -187,7 +187,9 @@ uv run python -m scripts.setup.wizard
| 8 | Install Claude Code integration (32 agents, 109 skills, 30 hooks) |
| 9 | Math features (SymPy, Z3, Pint - optional) |
| 10 | TLDR code analysis tool |
| 11-12 | Diagnostics tools + Loogle (optional) |
| 11 | Code quality CLI - qlty (optional) |
| 12 | AST-based code search - ast-grep (optional) |
| 13-14 | Diagnostics tools + Loogle (optional) |


#### To Uninstall:
Expand Down
114 changes: 100 additions & 14 deletions opc/scripts/setup/wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,13 +517,14 @@ async def run_setup_wizard() -> None:
5. Start Docker stack
6. Run migrations
7. Install Claude Code integration (hooks, skills, rules)
8. Install optional CLI tools (qlty, ast-grep)
"""
console.print(
Panel.fit("[bold]CLAUDE CONTINUITY KIT v3 - SETUP WIZARD[/bold]", border_style="blue")
)

# Step 0: Backup global ~/.claude (safety first)
console.print("\n[bold]Step 0/13: Backing up global Claude configuration...[/bold]")
console.print("\n[bold]Step 0/15: Backing up global Claude configuration...[/bold]")
from scripts.setup.claude_integration import (
backup_global_claude_dir,
get_global_claude_dir,
Expand All @@ -540,7 +541,7 @@ async def run_setup_wizard() -> None:
console.print(" [dim]No existing ~/.claude found (clean install)[/dim]")

# Step 1: Check prerequisites (with installation offers)
console.print("\n[bold]Step 1/13: Checking system requirements...[/bold]")
console.print("\n[bold]Step 1/15: Checking system requirements...[/bold]")
prereqs = await check_prerequisites_with_install_offers()

if prereqs["docker"]:
Expand All @@ -565,7 +566,7 @@ async def run_setup_wizard() -> None:
sys.exit(1)

# Step 2: Database config
console.print("\n[bold]Step 2/13: Database Configuration[/bold]")
console.print("\n[bold]Step 2/15: Database Configuration[/bold]")
console.print(" Choose your database backend:")
console.print(" [bold]docker[/bold] - PostgreSQL in Docker (recommended)")
console.print(" [bold]embedded[/bold] - Embedded PostgreSQL (no Docker needed)")
Expand Down Expand Up @@ -605,29 +606,29 @@ async def run_setup_wizard() -> None:
db_config["mode"] = "docker"

# Step 3: Embedding configuration
console.print("\n[bold]Step 3/13: Embedding Configuration[/bold]")
console.print("\n[bold]Step 3/15: Embedding Configuration[/bold]")
if Confirm.ask("Configure embedding provider?", default=True):
embeddings = await prompt_embedding_config()
else:
embeddings = {"provider": "local"}

# Step 4: API keys
console.print("\n[bold]Step 4/13: API Keys (Optional)[/bold]")
console.print("\n[bold]Step 4/15: API Keys (Optional)[/bold]")
if Confirm.ask("Configure API keys?", default=False):
api_keys = await prompt_api_keys()
else:
api_keys = {"perplexity": "", "nia": "", "braintrust": ""}

# Step 5: Generate .env
console.print("\n[bold]Step 5/13: Generating configuration...[/bold]")
console.print("\n[bold]Step 5/15: Generating configuration...[/bold]")
config = {"database": db_config, "embeddings": embeddings, "api_keys": api_keys}
env_path = Path.cwd() / ".env"
generate_env_file(config, env_path)
console.print(f" [green]OK[/green] Generated {env_path}")

# Step 5: Container stack (Sandbox Infrastructure)
runtime = prereqs.get("container_runtime", "docker")
console.print(f"\n[bold]Step 6/13: Container Stack (Sandbox Infrastructure)[/bold]")
console.print(f"\n[bold]Step 6/15: Container Stack (Sandbox Infrastructure)[/bold]")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

f-string without placeholders (static analysis).

Line 631 uses an f-string but contains no interpolated variables. The runtime variable on line 630 is likely intended to be used here.

Proposed fix
-        console.print(f"\n[bold]Step 6/15: Container Stack (Sandbox Infrastructure)[/bold]")
+        console.print("\n[bold]Step 6/15: Container Stack (Sandbox Infrastructure)[/bold]")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.print(f"\n[bold]Step 6/15: Container Stack (Sandbox Infrastructure)[/bold]")
console.print("\n[bold]Step 6/15: Container Stack (Sandbox Infrastructure)[/bold]")
🧰 Tools
🪛 Ruff (0.15.0)

[error] 631-631: f-string without any placeholders

Remove extraneous f prefix

(F541)

🤖 Prompt for AI Agents
In `@opc/scripts/setup/wizard.py` at line 631, The print call uses an unnecessary
f-string and likely meant to include the runtime variable; update the call to
include runtime (e.g., interpolate runtime into the message) or remove the
leading f to make it a normal string. Locate the console.print invocation in
wizard.py (the call to console.print(... "Step 6/15: Container Stack (Sandbox
Infrastructure)")) and either add {runtime} in the formatted string where
appropriate or change the string to a plain literal to eliminate the unused
f-string.

console.print(" The sandbox requires PostgreSQL and Redis for:")
console.print(" - Agent coordination and scheduling")
console.print(" - Build cache and LSP index storage")
Expand Down Expand Up @@ -655,7 +656,7 @@ async def run_setup_wizard() -> None:
console.print(f" You can start manually with: {runtime} compose up -d")

# Step 6: Migrations
console.print("\n[bold]Step 7/13: Database Setup[/bold]")
console.print("\n[bold]Step 7/15: Database Setup[/bold]")
if Confirm.ask("Run database migrations?", default=True):
from scripts.setup.docker_setup import run_migrations, set_container_runtime

Expand All @@ -668,7 +669,7 @@ async def run_setup_wizard() -> None:
console.print(f" [red]ERROR[/red] {result.get('error', 'Unknown error')}")

# Step 7: Claude Code Integration
console.print("\n[bold]Step 8/13: Claude Code Integration[/bold]")
console.print("\n[bold]Step 8/15: Claude Code Integration[/bold]")
from scripts.setup.claude_integration import (
analyze_conflicts,
backup_claude_dir,
Expand Down Expand Up @@ -863,7 +864,7 @@ async def run_setup_wizard() -> None:
console.print(f' export CLAUDE_OPC_DIR="{opc_dir}"')

# Step 8: Math Features (Optional)
console.print("\n[bold]Step 9/13: Math Features (Optional)[/bold]")
console.print("\n[bold]Step 9/15: Math Features (Optional)[/bold]")
console.print(" Math features include:")
console.print(" - SymPy: symbolic algebra, calculus, equation solving")
console.print(" - Z3: SMT solver for constraint satisfaction & proofs")
Expand Down Expand Up @@ -922,7 +923,7 @@ async def run_setup_wizard() -> None:
console.print(" [dim]Install later with: uv sync --extra math[/dim]")

# Step 9: TLDR Code Analysis Tool
console.print("\n[bold]Step 10/13: TLDR Code Analysis Tool[/bold]")
console.print("\n[bold]Step 10/15: TLDR Code Analysis Tool[/bold]")
console.print(" TLDR provides token-efficient code analysis for LLMs:")
console.print(" - 95% token savings vs reading raw files")
console.print(" - 155x faster queries with daemon mode")
Expand Down Expand Up @@ -1080,8 +1081,93 @@ async def run_setup_wizard() -> None:
if strip_tldr_hooks_from_settings(settings_path):
console.print(" [green]OK[/green] TLDR hooks disabled")

# Step 10: Diagnostics Tools (Shift-Left Feedback)
console.print("\n[bold]Step 11/13: Diagnostics Tools (Shift-Left Feedback)[/bold]")
# Step 10b: Code Quality CLI - qlty (Optional)
console.print("\n[bold]Step 11/15: Code Quality CLI (Optional)[/bold]")
console.print(" qlty provides universal code quality checking:")
console.print(" - 70+ linters across 40+ languages")
console.print(" - Auto-fix for common issues")
console.print(" - Powers the /qlty-check skill")
console.print("")

if shutil.which("qlty"):
console.print(" [green]OK[/green] qlty already installed")
elif Confirm.ask("\nInstall qlty?", default=True):
console.print(" Installing qlty...")
import subprocess

try:
result = subprocess.run(
["sh", "-c", "curl -fsSL https://qlty.sh | sh"],
capture_output=True,
text=True,
timeout=120,
)
Comment on lines +1099 to +1104

This comment was marked as outdated.

if result.returncode == 0:
console.print(" [green]OK[/green] qlty installed")
else:
console.print(" [yellow]WARN[/yellow] Installation failed")
console.print(" Install manually: curl -fsSL https://qlty.sh | sh")
except subprocess.TimeoutExpired:
console.print(" [yellow]WARN[/yellow] Installation timed out")
console.print(" Install manually: curl -fsSL https://qlty.sh | sh")
except Exception as e:
console.print(f" [red]ERROR[/red] {e}")
else:
console.print(" Skipped qlty installation")
console.print(" [dim]Install later: curl -fsSL https://qlty.sh | sh[/dim]")
Comment on lines +1098 to +1128
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing qlty init and post-install verification per PR objectives.

The PR description states that qlty init should be called on successful install, and the issue requires following the "explain → confirm → install → verify" pattern. Currently, neither happens after qlty installation succeeds.

Proposed fix
             if result.returncode == 0:
                 console.print("  [green]OK[/green] qlty installed")
+
+                # Verify installation
+                verify = subprocess.run(
+                    ["qlty", "--version"],
+                    capture_output=True,
+                    text=True,
+                    timeout=10,
+                )
+                if verify.returncode == 0:
+                    console.print(f"  [green]OK[/green] Verified: {verify.stdout.strip()}")
+                else:
+                    console.print("  [yellow]WARN[/yellow] qlty installed but not on PATH")
+
+                # Initialize qlty in the project
+                console.print("  Running qlty init...")
+                init_result = subprocess.run(
+                    ["qlty", "init"],
+                    capture_output=True,
+                    text=True,
+                    timeout=60,
+                )
+                if init_result.returncode == 0:
+                    console.print("  [green]OK[/green] qlty initialized")
+                else:
+                    console.print("  [yellow]WARN[/yellow] qlty init failed (run manually: qlty init)")
             else:
🤖 Prompt for AI Agents
In `@opc/scripts/setup/wizard.py` around lines 1098 - 1117, After a successful
curl install (the branch where subprocess.run returns 0), invoke the qlty
initialization and a verification command: call "qlty init" (run via
subprocess.run similar to the existing call) and then run a verification command
such as "qlty --version" or another appropriate qlty health/status check; handle
non-zero return codes and exceptions for both calls and log results via
console.print (reuse the same timeout/ capture_output/text pattern), printing an
OK on success or WARN/ERROR with actionable manual instructions on failure.
Ensure you update the success branch that currently prints "OK qlty installed"
to perform these two subprocess.run calls (referencing subprocess.run and
result.returncode) and to surface errors/exceptions just like the existing
install block.


# Step 10c: AST-Grep (Optional)
console.print("\n[bold]Step 12/15: AST-Based Code Search (Optional)[/bold]")
console.print(" ast-grep enables structural code search and refactoring:")
console.print(" - Search by AST patterns, not text")
console.print(" - Language-aware refactoring")
console.print(" - Powers the /ast-grep-find and search-router skills")
console.print("")

if shutil.which("ast-grep") or shutil.which("sg"):
console.print(" [green]OK[/green] ast-grep already installed")
elif Confirm.ask("\nInstall ast-grep?", default=True):
console.print(" Installing ast-grep...")
import subprocess

try:
# Try brew first (macOS), then cargo
if shutil.which("brew"):
result = subprocess.run(
["brew", "install", "ast-grep"],
capture_output=True,
text=True,
timeout=120,
)
elif shutil.which("cargo"):
console.print(" [dim]Using cargo (may take a few minutes)...[/dim]")
result = subprocess.run(
["cargo", "install", "ast-grep", "--locked"],
capture_output=True,
text=True,
timeout=300,
)
else:
console.print(" [yellow]WARN[/yellow] Neither brew nor cargo found")
console.print(" Install manually: https://github.com/ast-grep/ast-grep#installation")
result = None

if result and result.returncode == 0:
console.print(" [green]OK[/green] ast-grep installed")
elif result:
console.print(" [yellow]WARN[/yellow] Installation failed")
console.print(" Install manually: brew install ast-grep")
except subprocess.TimeoutExpired:
console.print(" [yellow]WARN[/yellow] Installation timed out")
console.print(" Install manually: brew install ast-grep")
except Exception as e:
console.print(f" [red]ERROR[/red] {e}")
Comment on lines +1144 to +1187
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing post-install verification for ast-grep, and misleading fallback message.

Two issues:

  1. Like qlty, ast-grep doesn't verify the install succeeded (e.g., sg --version), deviating from the "explain → confirm → install → verify" pattern required by issue #140.

  2. Lines 1158-1159 and 1161-1162: when cargo install fails or times out, the fallback message suggests brew install ast-grep, which is confusing if the user doesn't have brew. Consider a more generic message.

Proposed fix
             if result and result.returncode == 0:
                 console.print("  [green]OK[/green] ast-grep installed")
+
+                # Verify installation
+                sg_cmd = "sg" if shutil.which("sg") else "ast-grep"
+                verify = subprocess.run(
+                    [sg_cmd, "--version"],
+                    capture_output=True,
+                    text=True,
+                    timeout=10,
+                )
+                if verify.returncode == 0:
+                    console.print(f"  [green]OK[/green] Verified: {verify.stdout.strip()}")
+                else:
+                    console.print("  [yellow]WARN[/yellow] ast-grep installed but not on PATH")
             elif result:
                 console.print("  [yellow]WARN[/yellow] Installation failed")
-                console.print("  Install manually: brew install ast-grep")
+                console.print("  Install manually: https://github.com/ast-grep/ast-grep#installation")
         except subprocess.TimeoutExpired:
             console.print("  [yellow]WARN[/yellow] Installation timed out")
-            console.print("  Install manually: brew install ast-grep")
+            console.print("  Install manually: https://github.com/ast-grep/ast-grep#installation")
🤖 Prompt for AI Agents
In `@opc/scripts/setup/wizard.py` around lines 1133 - 1164, The ast-grep install
block (in wizard.py around the ast-grep install logic) must verify the
installation and avoid misleading fallback text: after a successful
subprocess.run that returns 0, run a verification check (e.g.,
subprocess.run(["sg","--version"], capture_output=True, text=True) or check
shutil.which("sg")) and only print "[green]OK[/green] ast-grep installed" if the
verification succeeds; if verification fails, treat it as an installation
failure and print the appropriate failure message. Also replace hardcoded
"Install manually: brew install ast-grep" in the failure and timeout branches
with a generic instruction or a context-aware suggestion (if
shutil.which("brew") is truthy suggest brew, elif shutil.which("cargo") suggest
cargo, else print the upstream install URL
https://github.com/ast-grep/ast-grep#installation) so users without brew aren't
directed to use it.

else:
console.print(" Skipped ast-grep installation")
console.print(" [dim]Install later: brew install ast-grep[/dim]")

# Step 10d: Diagnostics Tools (Shift-Left Feedback)
console.print("\n[bold]Step 13/15: Diagnostics Tools (Shift-Left Feedback)[/bold]")
console.print(" Claude gets immediate type/lint feedback after editing files.")
console.print(" This catches errors before tests run (shift-left).")
console.print("")
Expand Down Expand Up @@ -1119,7 +1205,7 @@ async def run_setup_wizard() -> None:
console.print(" [dim]TypeScript, Go, Rust coming soon.[/dim]")

# Step 11: Loogle (Lean 4 type search for /prove skill)
console.print("\n[bold]Step 12/13: Loogle (Lean 4 Type Search)[/bold]")
console.print("\n[bold]Step 14/15: Loogle (Lean 4 Type Search)[/bold]")
console.print(" Loogle enables type-aware search of Mathlib theorems:")
console.print(" - Used by /prove skill for theorem proving")
console.print(" - Search by type signature (e.g., 'Nontrivial _ ↔ _')")
Expand Down