Skip to content

Comments

feat: rename Claude Pilot to Pilot Shell#86

Merged
maxritter merged 14 commits intomainfrom
dev
Feb 24, 2026
Merged

feat: rename Claude Pilot to Pilot Shell#86
maxritter merged 14 commits intomainfrom
dev

Conversation

@maxritter
Copy link
Owner

@maxritter maxritter commented Feb 24, 2026

Summary

  • Full project rename from Claude Pilot to Pilot Shell
  • All URLs updated from claude-pilot.com to pilot-shell.com
  • GitHub repo references updated from maxritter/claude-pilot to maxritter/pilot-shell
  • ASCII art banners updated in launcher and installer
  • Shell config markers updated with backward compatibility for existing installations
  • Console display strings renamed (CLAUDE_PILOT_* env var keys intentionally kept as-is)
  • Website, docs, blog, devcontainer, and CI configuration updated
  • Stop guard rule added to task-and-workflow rules
  • Bugfix spec workflow and viewer enhancements (feat: add bugfix spec workflow and viewer enhancements #85 rebased)

BREAKING CHANGE: Project renamed from Claude Pilot to Pilot Shell. All URLs, GitHub repo references, and branding updated. Existing shell config markers are handled with backward compatibility.

Test plan

  • 1162 Python tests pass (launcher, installer, hooks)
  • 989 console tests pass
  • Type checker clean (pre-existing errors only)
  • Comprehensive grep scan confirms zero stale references
  • Backward compatibility verified for shell config markers

Summary by CodeRabbit

  • New Features

    • Clickable task navigation in Specs (task jump + back-to-tasks) and plan deduplication for cleaner plan lists.
  • Chores

    • Project-wide rebrand: Claude Pilot → Pilot Shell across UI, installer, site, metadata, links, and theme identifiers.
  • Tests

    • Updated and added tests to cover branding changes, spec task navigation, and plan deduplication.
  • Documentation

    • Updated docs, changelog, site content, and install/uninstall guidance to reflect Pilot Shell.

…cements

Introduce /spec-bugfix-plan command for structured bug fix planning with
root cause analysis. Spec dispatcher now auto-detects task type (feature vs
bugfix) and routes accordingly. Console viewer shows spec type badges,
extracted SpecHeaderCard component, and updated plan reader to parse Type
field. Installer adds property-based testing tools. Documentation and
workflow rules updated to reflect the dual-mode spec system.

# Conflicts:
#	console/src/services/worker/http/routes/utils/planFileReader.ts
#	console/src/ui/viewer/views/Dashboard/PlanStatus.tsx
#	console/src/ui/viewer/views/Spec/SpecHeaderCard.tsx
#	console/src/ui/viewer/views/Spec/index.tsx
#	console/tests/worker/plan-stats-endpoint.test.ts
#	installer/steps/dependencies.py
#	installer/tests/unit/steps/test_dependencies.py
#	launcher/statusline/formatter.py
#	launcher/tests/unit/statusline/test_formatter.py
#	pilot/commands/spec-bugfix-plan.md
#	pilot/scripts/worker-service.cjs
#	pilot/ui/viewer-bundle.js
# Conflicts:
#	console/package.json
#	launcher/__init__.py
#	pilot/package.json
#	pilot/plugin.json
Rename "Claude Pilot" → "Pilot Shell" and "claude-pilot" → "pilot-shell"
across 20 console TypeScript files (display text, URLs, CSS theme names).
CLAUDE_PILOT_* env var keys intentionally kept as-is.

Also fix stop guard hook: remove unused get_next_phase, simplify message
to let model decide next action, add stop guard rule to task-and-workflow.md.
@vercel
Copy link

vercel bot commented Feb 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
pilot-shell Ignored Ignored Preview Feb 24, 2026 0:26am

Request Review

@claude
Copy link

claude bot commented Feb 24, 2026

Claude finished @maxritter's task in 4m 9s —— View job


Code Review

  • Gather context and read CLAUDE.md
  • Review changed files
  • Post review feedback

Summary

This is a comprehensive project rename from Claude PilotPilot Shell across 98 files, plus two bundled changes: a stop guard refactor (rebased from #85) and a version parsing bugfix. The rename is thorough and the backward compatibility approach for shell config markers is well-implemented. A few issues worth addressing before merge:


Issues

🔴 Version Downgrade in Package Files

Three package files regressed from 6.11.06.10.3 as part of commit acee225:

  • pilot/plugin.json6.11.06.10.3
  • pilot/package.json6.11.06.10.3
  • console/package.json6.11.06.10.3

The commit message for acee225 explicitly notes conflicts in all three files, which suggests these resolved in favor of the dev branch version instead of keeping main's 6.11.0. Since CHANGELOG.md still references [6.11.0] for today's release, this creates a mismatch between the changelog and the actual package versions.

Action needed: These should all be 6.11.0 (or whatever the intended next version is). Fix this →


🟡 CHANGELOG History Rewrite

The CHANGELOG rewrites historical entries — e.g., changing "Project renamed from Claude CodePro to Claude Pilot" to "Project renamed from Claude CodePro to Pilot Shell". This is technically inaccurate for entries that describe the past state (the project was called Claude Pilot at that time).

Consider whether consumers of the CHANGELOG will be confused by retroactively rewritten history, especially since released versions under the "Claude Pilot" name existed. A common approach is to add a header note like > Previously known as Claude Pilot rather than rewriting old entries.


🟡 Bundled Functional Change: Stop Guard Refactor

pilot/hooks/spec_stop_guard.py has a meaningful behavioral change that's separate from the rename:

  • Removed get_next_phase(status, approved) and approved field tracking
  • Removed the Approved: field parsing from plan files
  • Changed the stop-block message from including Next: Skill(skill='...', ...) to issuing a CRITICAL INSTRUCTION TO CLAUDE directive in the reason text

The old approach dynamically routed Claude to the correct next skill phase. The new approach issues an imperative instruction. This is a valid design choice (simpler, avoids stale routing), but it's a functional behavior change bundled into a rename PR, which makes it harder to bisect if issues arise. The PR description does call this out as "#85 rebased", which is good.

No correctness issue here — the tests were updated consistently (test_spec_stop_guard.py returns 2-tuples instead of 3-tuples). Just worth being aware of during review.


🟢 Demo Repository Link

README.md now links to https://github.com/maxritter/pilot-shell-demo. Confirm the demo repo has been renamed on GitHub, otherwise this will be a broken link for users.


What Looks Good

Backward compatibility is handled well. installer/steps/shell_config.py correctly introduces OLD_CLAUDE_PILOT_MARKER = "# Claude Pilot" alongside the new CLAUDE_ALIAS_MARKER = "# Pilot Shell", and remove_old_alias() strips both. uninstall.sh mirrors this with OLD_CLAUDE_PILOT_MARKER and the updated awk block.

Version parsing fix is correct. The sed pattern change from s/.*Pilot v\(.*\)/\1/ps/.* v\([^ ]*\).*/\1/p in both install.sh and uninstall.sh correctly generalizes the version extraction to be product-name agnostic.

Rename coverage is comprehensive. A grep scan of non-launcher source files shows zero stale claude-pilot.com or Claude Pilot references (the remaining "# Claude Pilot" entries are intentional backward-compat markers).

Test updates are consistent. test_spec_stop_guard.py, test_install_sh.py, test_finalize.py, and other test files were all updated to match the renamed constants and new function signatures.

pilot/rules/task-and-workflow.md correctly documents the stop guard behavior for Claude.


Verdict

Approve after fixing the version downgrade in the three package files. The version mismatch between CHANGELOG.md ([6.11.0]) and the package files (6.10.3) is the only blocking issue.

@coderabbitai
Copy link

coderabbitai bot commented Feb 24, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ecde27a and 7a04df0.

⛔ Files ignored due to path filters (4)
  • pilot/package.json is excluded by !pilot/**
  • pilot/plugin.json is excluded by !pilot/**
  • pilot/scripts/mcp-server.cjs is excluded by !pilot/**
  • pilot/scripts/worker-service.cjs is excluded by !pilot/**
📒 Files selected for processing (3)
  • README.md
  • console/package.json
  • docs/site/index.html

Walkthrough

Rebrands the project from "Claude Pilot" to "Pilot Shell" across packaging, docs, website, UI, installer/uninstaller, tests, and assets; adds plan deduplication utility in the console worker plan reader and integrates it into plan/spec listing and stats; adds Spec UI task navigation wiring and tests; minor installer alias/version parsing updates.

Changes

Cohort / File(s) Summary
Project metadata & packaging
pyproject.toml, console/package.json, cliff.toml, .devcontainer/devcontainer.json
Renamed project/package metadata, container identifiers and descriptions to Pilot Shell.
Docs, changelog & license
README.md, CHANGELOG.md, LICENSE
Updated product name and domain links across documentation, changelog and license text.
Website / SEO / static site
docs/site/index.html, docs/site/public/manifest.json, docs/site/public/robots.txt, docs/site/vite-plugin-sitemap.ts, docs/site/src/pages/..., docs/site/src/components/...
Rebranded site metadata, structured data, canonical URLs, SEO defaults, images and component copy/links to pilot-shell.com and Pilot Shell.
Console UI & styles
console/src/ui/viewer/App.tsx, console/src/ui/viewer/index.html, console/src/ui/viewer/viewer.html, console/src/ui/viewer/components/*, console/src/ui/viewer/layouts/*, console/src/ui/viewer/styles/main.css, console/src/ui/viewer/hooks/useTheme.ts
Switched UI copy, page titles, theme tokens and DaisyUI theme names; updated repo/pricing links, logo alt text and small layout/height adjustments.
Console services & plan reader
console/src/services/worker-service.ts, console/src/services/worker/http/routes/utils/planFileReader.ts
Updated license messaging; added exported deduplicatePlans(plans: PlanInfo[]): PlanInfo[] and integrated deduplication into active/all plan and stats flows.
Spec UI & navigation
console/src/ui/viewer/views/Spec/..., console/src/ui/viewer/views/Spec/SpecHeaderCard.tsx, console/src/ui/viewer/views/Spec/SpecContent.tsx
Added task-id generation for headings, clickable task rows via onTaskClick, scroll-back button and wiring to scroll between task list/header and content.
Console tests
console/tests/...
Updated branding expectations; added tests for plan deduplication and Spec task navigation; adjusted multiple UI/test fixtures to pilot-shell values.
Installer & CLI
install.sh, uninstall.sh, installer/__init__.py, installer/cli.py, installer/ui.py
Replaced branding strings and repo references; added OLD_CLAUDE_PILOT_MARKER handling; adjusted version-extraction regex and messaging.
Installer steps & shell config
installer/steps/claude_files.py, installer/steps/finalize.py, installer/steps/shell_config.py
Updated REPO_URL to pilot-shell, adjusted version extraction, added old-marker handling and alias detection/cleanup changes.
Installer tests
installer/tests/unit/..., installer/tests/unit/test_finalize.py, installer/tests/unit/test_install_sh.py
Updated expected outputs, fixtures, and assertions to use pilot-shell strings and devcontainer/workspace expectations.
Templates, CI & misc
.github/ISSUE_TEMPLATE/*, .gitattributes, .githooks/pre-commit
Updated issue template copy/links, added gitattributes rule, and added early-exit logic to pre-commit hook for non-root git work trees.
Misc UI/content tweaks
assorted docs/*, console/src/ui/*
Numerous presentational updates, minor layout tweaks, SEO/manifest defaults and string replacements to reflect rebranding.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Client as Client (browser / CLI)
participant Server as Console Worker HTTP
participant FS as File System (.worktrees/ + docs/plans)
participant Cache as Plan cache/index

Client->>Server: GET /plans
Server->>FS: read plan files from docs/plans and .worktrees
FS-->>Server: return PlanInfo[] (may contain duplicates)
Server->>Server: deduplicatePlans(plans)
Note over Server: prefer .worktrees/ paths; within same source keep newest by modifiedAt
Server->>Cache: cache/update deduplicated plan list & compute stats
Server-->>Client: return deduplicated plans and stats

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

released

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.84% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: rename Claude Pilot to Pilot Shell' accurately and concisely summarizes the main change: a complete project rebranding. The title is clear, specific, and directly reflects the primary objective evident across all file changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude
Copy link

claude bot commented Feb 24, 2026

Claude finished @maxritter's task in 1m 20s —— View job


Incremental Code Review

  • Gather context and read CLAUDE.md
  • Review files changed in this push
  • Post incremental review feedback

Push: fix: exclude __init__.py from source encryption filter (2262b08)

Changed files reviewed: .gitattributes, LICENSE (launcher __init__.py files are git-crypt encrypted — skipped)


New Issues

None introduced by this push.


Fixed Issues

None of the previously reported issues are resolved by this push.


Still Open

  • 🔴 Version downgradepilot/plugin.json, pilot/package.json, console/package.json remain at 6.10.3 vs 6.11.0 in CHANGELOG
  • 🟡 CHANGELOG history rewrite — historical entries still retroactively rename "Claude Pilot" to "Pilot Shell"
  • 🟡 Bundled stop guard refactor — behavioral change from #85 still merged into rename PR
  • 🟢 Demo repo linkREADME.md references maxritter/pilot-shell-demo; confirm GitHub repo has been renamed

Delta Notes

.gitattributes — The new launcher/**/__init__.py !filter !diff line correctly opts __init__.py files out of git-crypt encryption. The ** pattern in gitattributes matches zero or more path components, so this covers both launcher/__init__.py and nested ones (launcher/tests/__init__.py, etc.). The binary size reductions in the commit stat confirm decryption is working as intended.

LICENSE — One remaining https://claude-pilot.comhttps://pilot-shell.com substitution was applied. No issues.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
installer/steps/finalize.py (1)

20-29: ⚠️ Potential issue | 🟡 Minor

Version parsing may fail if pilot --version includes trailing tokens.
Anchoring to end can miss versions like Pilot Shell v1.2.3 (build abc). Consider matching the first v<version> token instead.

💡 Suggested fix
-                match = re.search(r" v(\S+)$", result.stdout.strip())
+                version_line = result.stdout.strip()
+                match = re.search(r"\bv([0-9A-Za-z][0-9A-Za-z.\-+]*)(?:\b|$)", version_line)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@installer/steps/finalize.py` around lines 20 - 29, The current version
parsing uses re.search(r" v(\S+)$", result.stdout.strip()) which only matches a
'v' token at the end and will miss strings like "Pilot Shell v1.2.3 (build
abc)"; update the regex to find the first v<version> token anywhere in the
output (for example re.search(r"\bv(\d+(?:\.\d+)*\S*)", result.stdout) or simply
re.search(r"v(\S+)", result.stdout)) and return match.group(1) as before; locate
the block that calls subprocess.run([str(pilot_path), "--version"], ...) and
replace the anchored regex with the more permissive one so it captures versions
followed by extra text.
🧹 Nitpick comments (1)
console/src/ui/viewer/views/Spec/index.tsx (1)

93-99: Consider moving the project-change reset logic into a useEffect.

Calling setState directly in the render body (outside a useEffect) is a React anti-pattern. While React permits it as an escape hatch, it causes a double render on every project change and can behave unexpectedly under React Strict Mode's intentional double-invocation.

♻️ Suggested refactor
-  if (lastProjectRef.current !== selectedProject) {
-    lastProjectRef.current = selectedProject;
-    setSelectedSpec(null);
-    setContent(null);
-    setError(null);
-    setIsLoading(true);
-  }
+  useEffect(() => {
+    setSelectedSpec(null);
+    setContent(null);
+    setError(null);
+    setIsLoading(true);
+  }, [selectedProject]);

The lastProjectRef can then be removed entirely.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@console/src/ui/viewer/views/Spec/index.tsx` around lines 93 - 99, The
reset-of-state on project change is happening during render; move that logic
into a useEffect that depends on selectedProject instead of mutating
lastProjectRef in the render path. Inside the new useEffect, call
setSelectedSpec(null), setContent(null), setError(null) and setIsLoading(true)
when selectedProject changes, then remove lastProjectRef and any render-time
checks that previously compared it to selectedProject to avoid double renders
and Strict Mode issues. Ensure the effect runs only when selectedProject changes
by listing it in the dependency array.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@console/package.json`:
- Around line 2-4: The package.json "version" field was decreased from 6.11.0 to
6.10.3 which can break publishing; update the "version" value in package.json
(the "version" key) to be at least the previous release (e.g., 6.11.0) or to the
correct next semver per your release policy so the package metadata does not
rollback.

In `@installer/ui.py`:
- Around line 181-188: Replace the broken hardcoded GitHub URL
"https://github.com/maxritter/pilot-shell" with the correct repository URL
"https://github.com/maxritter/claude-pilot" everywhere: update the REPO_URL
constant, any user-facing message strings (e.g., the "⭐ Star this repo" text in
the finalize message and the license/trial messages built with
license_text.append and the output of _get_trial_time_str), ensure installer CLI
functions that format trial/license messages use the updated URL, and update
test expectations (e.g., in tests referencing REPO_URL) to the new URL so
assertions match.

---

Outside diff comments:
In `@installer/steps/finalize.py`:
- Around line 20-29: The current version parsing uses re.search(r" v(\S+)$",
result.stdout.strip()) which only matches a 'v' token at the end and will miss
strings like "Pilot Shell v1.2.3 (build abc)"; update the regex to find the
first v<version> token anywhere in the output (for example
re.search(r"\bv(\d+(?:\.\d+)*\S*)", result.stdout) or simply
re.search(r"v(\S+)", result.stdout)) and return match.group(1) as before; locate
the block that calls subprocess.run([str(pilot_path), "--version"], ...) and
replace the anchored regex with the more permissive one so it captures versions
followed by extra text.

---

Nitpick comments:
In `@console/src/ui/viewer/views/Spec/index.tsx`:
- Around line 93-99: The reset-of-state on project change is happening during
render; move that logic into a useEffect that depends on selectedProject instead
of mutating lastProjectRef in the render path. Inside the new useEffect, call
setSelectedSpec(null), setContent(null), setError(null) and setIsLoading(true)
when selectedProject changes, then remove lastProjectRef and any render-time
checks that previously compared it to selectedProject to avoid double renders
and Strict Mode issues. Ensure the effect runs only when selectedProject changes
by listing it in the dependency array.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4365ae4 and ff588fe.

⛔ Files ignored due to path filters (30)
  • launcher/__init__.py is excluded by !launcher/**
  • launcher/banner.py is excluded by !launcher/**
  • launcher/build.py is excluded by !launcher/**
  • launcher/cli.py is excluded by !launcher/**
  • launcher/config.py is excluded by !launcher/**
  • launcher/model_config.py is excluded by !launcher/**
  • launcher/settings_injector.py is excluded by !launcher/**
  • launcher/statusline/__init__.py is excluded by !launcher/**
  • launcher/statusline/formatter.py is excluded by !launcher/**
  • launcher/statusline/widgets.py is excluded by !launcher/**
  • launcher/tests/integration/test_license_flow.py is excluded by !launcher/**
  • launcher/tests/unit/statusline/test_formatter.py is excluded by !launcher/**
  • launcher/tests/unit/statusline/test_widgets.py is excluded by !launcher/**
  • launcher/tests/unit/test_banner.py is excluded by !launcher/**
  • launcher/tests/unit/test_cli.py is excluded by !launcher/**
  • launcher/updater.py is excluded by !launcher/**
  • launcher/wrapper.py is excluded by !launcher/**
  • pilot/hooks/hooks.json is excluded by !pilot/**
  • pilot/hooks/spec_stop_guard.py is excluded by !pilot/**
  • pilot/hooks/tests/test_spec_stop_guard.py is excluded by !pilot/**
  • pilot/package.json is excluded by !pilot/**
  • pilot/plugin.json is excluded by !pilot/**
  • pilot/rules/task-and-workflow.md is excluded by !pilot/**
  • pilot/scripts/mcp-server.cjs is excluded by !pilot/**
  • pilot/scripts/worker-service.cjs is excluded by !pilot/**
  • pilot/settings.json is excluded by !pilot/**
  • pilot/ui/index.html is excluded by !pilot/**
  • pilot/ui/viewer-bundle.js is excluded by !pilot/**
  • pilot/ui/viewer.css is excluded by !pilot/**
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (68)
  • .devcontainer/devcontainer.json
  • .github/ISSUE_TEMPLATE/bug_report.md
  • .github/ISSUE_TEMPLATE/config.yml
  • CHANGELOG.md
  • LICENSE
  • README.md
  • cliff.toml
  • console/package.json
  • console/src/services/worker-service.ts
  • console/src/ui/viewer/App.tsx
  • console/src/ui/viewer/components/ActivationModal.tsx
  • console/src/ui/viewer/components/Header.tsx
  • console/src/ui/viewer/components/LicenseGate.tsx
  • console/src/ui/viewer/hooks/useTheme.ts
  • console/src/ui/viewer/index.html
  • console/src/ui/viewer/layouts/DashboardLayout.tsx
  • console/src/ui/viewer/layouts/Sidebar/SidebarFooter.tsx
  • console/src/ui/viewer/layouts/Sidebar/SidebarLogo.tsx
  • console/src/ui/viewer/layouts/Topbar/TopbarActions.tsx
  • console/src/ui/viewer/layouts/Topbar/index.tsx
  • console/src/ui/viewer/styles/main.css
  • console/src/ui/viewer/viewer.html
  • console/src/ui/viewer/views/Settings/index.tsx
  • console/src/ui/viewer/views/Spec/index.tsx
  • console/tests/context/cross-session-isolation.test.ts
  • console/tests/ui/activation-modal.test.ts
  • console/tests/ui/license-gate.test.ts
  • console/tests/ui/project-selector.test.ts
  • docs/site/index.html
  • docs/site/public/manifest.json
  • docs/site/public/robots.txt
  • docs/site/src/components/ComparisonSection.tsx
  • docs/site/src/components/DemoSection.tsx
  • docs/site/src/components/FAQSection.tsx
  • docs/site/src/components/Footer.tsx
  • docs/site/src/components/HeroSection.tsx
  • docs/site/src/components/InstallSection.tsx
  • docs/site/src/components/Logo.tsx
  • docs/site/src/components/NavBar.tsx
  • docs/site/src/components/NotFound.tsx
  • docs/site/src/components/SEO.tsx
  • docs/site/src/components/WorkshopsSection.tsx
  • docs/site/src/content/blog/claude-code-hooks-guide.md
  • docs/site/src/content/blog/context-buffer-management.md
  • docs/site/src/content/blog/installation-guide.md
  • docs/site/src/content/blog/managing-context-long-sessions.md
  • docs/site/src/content/blog/mcp-servers-claude-code.md
  • docs/site/src/content/blog/model-selection.md
  • docs/site/src/content/blog/sandboxing-claude-code.md
  • docs/site/src/content/blog/spec-driven-development.md
  • docs/site/src/pages/BlogArticlePage.tsx
  • docs/site/src/pages/BlogPage.tsx
  • docs/site/src/pages/DocsPage.tsx
  • docs/site/src/pages/Index.tsx
  • docs/site/src/pages/docs/InstallationSection.tsx
  • docs/site/vite-plugin-sitemap.ts
  • install.sh
  • installer/__init__.py
  • installer/cli.py
  • installer/steps/claude_files.py
  • installer/steps/finalize.py
  • installer/steps/shell_config.py
  • installer/tests/unit/steps/test_claude_files.py
  • installer/tests/unit/steps/test_finalize.py
  • installer/tests/unit/test_install_sh.py
  • installer/ui.py
  • pyproject.toml
  • uninstall.sh

Comment on lines +181 to +188
license_text.append("https://pilot-shell.com", style="cyan")
else:
expires_at = license_info.get("expires_at") if license_info else None
time_str = _get_trial_time_str(days, expires_at)
license_text.append(" ⏳ ", style="yellow")
license_text.append(f"Trial ({time_str} remaining)", style="bold yellow")
license_text.append(" — Subscribe: ", style="dim white")
license_text.append("https://claude-pilot.com", style="cyan")
license_text.append("https://pilot-shell.com", style="cyan")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the new domain and GitHub repo are reachable

echo "Checking pilot-shell.com..."
curl -o /dev/null -s -w "pilot-shell.com HTTP status: %{http_code}\n" https://pilot-shell.com

echo "Checking GitHub repo..."
curl -o /dev/null -s -w "GitHub repo HTTP status: %{http_code}\n" https://github.com/maxritter/pilot-shell

echo "Checking install script..."
curl -o /dev/null -s -w "Install script HTTP status: %{http_code}\n" https://pilot-shell.com/install

Repository: maxritter/claude-pilot

Length of output: 238


🏁 Script executed:

# Search for GitHub URLs and repository references in the codebase
rg "github\.com" --type py -B2 -A2

# Also search for any README or documentation that might specify the correct repo
fd -e md -e txt | head -20 | xargs grep -l "github\|repo" 2>/dev/null || true

# Check if there are other references to pilot-shell or claude-pilot
rg "pilot-shell|claude-pilot" --type py -B1 -A1

Repository: maxritter/claude-pilot

Length of output: 15071


GitHub repository URL https://github.com/maxritter/pilot-shell is broken (404) — fix across all user-facing messages.

Trial and post-install users see messages pointing to https://github.com/maxritter/pilot-shell, but this repository doesn't exist. The URL appears hardcoded in:

  • installer/steps/claude_files.py (REPO_URL constant)
  • installer/steps/finalize.py ("⭐ Star this repo" message)
  • installer/ui.py (lines 181-188 — trial expired/remaining)
  • installer/cli.py (multiple trial/license messages)
  • Test assertions in installer/tests/unit/steps/test_claude_files.py

The current repository is maxritter/claude-pilot. Either update all references to the correct repository URL or ensure the pilot-shell repository is created and accessible before shipping.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@installer/ui.py` around lines 181 - 188, Replace the broken hardcoded GitHub
URL "https://github.com/maxritter/pilot-shell" with the correct repository URL
"https://github.com/maxritter/claude-pilot" everywhere: update the REPO_URL
constant, any user-facing message strings (e.g., the "⭐ Star this repo" text in
the finalize message and the license/trial messages built with
license_text.append and the output of _get_trial_time_str), ensure installer CLI
functions that format trial/license messages use the updated URL, and update
test expectations (e.g., in tests referencing REPO_URL) to the new URL so
assertions match.

@claude
Copy link

claude bot commented Feb 24, 2026

Claude finished @maxritter's task in 1m 15s —— View job


Incremental Code Review

  • Gather context and read CLAUDE.md
  • Review files changed in this push
  • Post incremental review feedback

Push: fix: update tagline to Pilot Shell makes it reliable (37f61cc)

Files reviewed: README.md, docs/site/index.html, docs/site/public/manifest.json, docs/site/src/components/Footer.tsx, docs/site/src/components/HeroSection.tsx, docs/site/src/components/Logo.tsx, docs/site/src/components/SEO.tsx, docs/site/src/pages/Index.tsx, installer/ui.py (launcher/pilot files are git-crypt encrypted — skipped)


New Issues

🔴 README example version downgraded to 6.10.3

README.md:134 — The pinned-version install example was changed from 6.11.06.10.3 in this push:

-export VERSION=6.11.0
+export VERSION=6.10.3
-curl -fsSL https://raw.githubusercontent.com/maxritter/claude-pilot/main/install.sh | bash
+curl -fsSL https://raw.githubusercontent.com/maxritter/pilot-shell/main/install.sh | bash

This compounds the existing package version downgrade: the README now actively directs users to install an older version. Since CHANGELOG.md lists [6.11.0] as today's release, the README example should reference 6.11.0, not 6.10.3. Fix this →


Fixed Issues

None of the previously reported issues are resolved by this push.


Still Open

  • 🔴 Version downgradepilot/plugin.json, pilot/package.json, console/package.json remain at 6.10.3 vs 6.11.0 in CHANGELOG (now also README.md:134)
  • 🔴 GitHub repo 404installer/steps/claude_files.py:31 and installer/steps/finalize.py:98 still reference https://github.com/maxritter/pilot-shell which CodeRabbit confirmed returns 404; confirm this repo exists before merge
  • 🟡 CHANGELOG history rewrite — historical entries still retroactively rename "Claude Pilot" to "Pilot Shell"
  • 🟡 Bundled stop guard refactor — behavioral change from #85 still merged into rename PR
  • 🟢 Demo repo linkREADME.md references maxritter/pilot-shell-demo; confirm GitHub repo has been renamed

Delta Notes

installer/ui.py — Trial/license subscribe messages now correctly use https://pilot-shell.com (website) instead of https://claude-pilot.com. No issues.

docs/site/ components — All branding, OG tags, schema.org structured data, and canonical URLs updated consistently from claude-pilot.compilot-shell.com. Tagline updated to "Pilot Shell makes it reliable." throughout. No issues.

README.md — All badge URLs, GitHub links, and text updated cleanly, except the version downgrade noted above.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/site/index.html (1)

85-119: ⚠️ Potential issue | 🟡 Minor

alternateName references a name that was never used — consider updating to the actual old name.

Line 87 has "alternateName": "Claude Code Pilot", but the project's previous name was "Claude Pilot", not "Claude Code Pilot". If this field is intended to preserve SEO discoverability for users searching for the old name, it should be "Claude Pilot". As-is, it neither matches the old brand nor the new one, providing no practical SEO benefit.

✏️ Suggested correction
-        "alternateName": "Claude Code Pilot",
+        "alternateName": "Claude Pilot",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/site/index.html` around lines 85 - 119, Update the JSON-LD
SoftwareApplication metadata by changing the "alternateName" field value from
"Claude Code Pilot" to the actual previous name "Claude Pilot" (the block
containing "@type": "SoftwareApplication", "name": "Pilot Shell", and
"alternateName"); ensure the "alternateName" string is exactly "Claude Pilot" to
preserve correct SEO/legacy name matching.
🧹 Nitpick comments (2)
docs/site/src/components/Footer.tsx (1)

93-100: Consider updating the Changelog URL subdomain for branding consistency.

The URL uses https://pilot.openchangelog.com/, but with the project now named Pilot Shell, consider updating it to https://pilot-shell.openchangelog.com/ for consistent branding. Openchangelog supports renaming subdomains directly in the Publish settings, so the change is straightforward. However, note that changing the subdomain will break old links unless redirects are set up (openchangelog does not provide automatic redirects for renamed subdomains).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/site/src/components/Footer.tsx` around lines 93 - 100, Update the
Changelog link in the Footer component: locate the anchor element that renders
"Changelog" (the <a> that currently has href="https://pilot.openchangelog.com/")
and change its href to "https://pilot-shell.openchangelog.com/"; keep the
existing target, rel, className and child <ScrollText /> unchanged and ensure
any tests or config that assert the old URL are updated accordingly.
README.md (1)

111-111: Consider clarifying ccp as a legacy alias.

After the rename, ccp (likely "Claude Code Pilot") is an opaque acronym to new users. If it's retained purely for backward compatibility, a brief parenthetical like (legacy alias) would prevent confusion.

✏️ Suggested wording
-After installation, run `pilot` or `ccp` in your project folder to start Pilot Shell.
+After installation, run `pilot` in your project folder to start Pilot Shell. The `ccp` alias is also available for backward compatibility.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` at line 111, Clarify that `ccp` is a legacy alias by updating the
README line that currently reads "After installation, run `pilot` or `ccp` in
your project folder to start Pilot Shell" to mention `ccp` as a
backward-compatible/legacy alias (e.g., "run `pilot` (or `ccp` — legacy
alias)"), so readers understand `pilot` is the primary command and `ccp` is
retained for compatibility; modify the sentence containing `pilot` and `ccp` to
include this parenthetical.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@docs/site/index.html`:
- Around line 85-119: Update the JSON-LD SoftwareApplication metadata by
changing the "alternateName" field value from "Claude Code Pilot" to the actual
previous name "Claude Pilot" (the block containing "@type":
"SoftwareApplication", "name": "Pilot Shell", and "alternateName"); ensure the
"alternateName" string is exactly "Claude Pilot" to preserve correct SEO/legacy
name matching.

---

Nitpick comments:
In `@docs/site/src/components/Footer.tsx`:
- Around line 93-100: Update the Changelog link in the Footer component: locate
the anchor element that renders "Changelog" (the <a> that currently has
href="https://pilot.openchangelog.com/") and change its href to
"https://pilot-shell.openchangelog.com/"; keep the existing target, rel,
className and child <ScrollText /> unchanged and ensure any tests or config that
assert the old URL are updated accordingly.

In `@README.md`:
- Line 111: Clarify that `ccp` is a legacy alias by updating the README line
that currently reads "After installation, run `pilot` or `ccp` in your project
folder to start Pilot Shell" to mention `ccp` as a backward-compatible/legacy
alias (e.g., "run `pilot` (or `ccp` — legacy alias)"), so readers understand
`pilot` is the primary command and `ccp` is retained for compatibility; modify
the sentence containing `pilot` and `ccp` to include this parenthetical.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2262b08 and 37f61cc.

⛔ Files ignored due to path filters (5)
  • launcher/banner.py is excluded by !launcher/**
  • launcher/cli.py is excluded by !launcher/**
  • pilot/scripts/worker-service.cjs is excluded by !pilot/**
  • pilot/ui/viewer-bundle.js is excluded by !pilot/**
  • pilot/ui/viewer.css is excluded by !pilot/**
📒 Files selected for processing (9)
  • README.md
  • docs/site/index.html
  • docs/site/public/manifest.json
  • docs/site/src/components/Footer.tsx
  • docs/site/src/components/HeroSection.tsx
  • docs/site/src/components/Logo.tsx
  • docs/site/src/components/SEO.tsx
  • docs/site/src/pages/Index.tsx
  • installer/ui.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • docs/site/src/components/HeroSection.tsx
  • docs/site/src/pages/Index.tsx
  • docs/site/public/manifest.json

…ole, and assets

Rename standalone "Pilot" to "Pilot Shell" in README FAQ, context preservation,
hooks, CLI, and testimonials sections. Rename "Pilot Console" to "Pilot Shell
Console" across docs, website, console UI, and installer. Update FAQ section on
website. Remove demo GIF files. Integrate recovered logo redesign and console
screenshot updates. Add spec task navigation and plan deduplication tests.
@claude
Copy link

claude bot commented Feb 24, 2026

Claude finished @maxritter's task in 4m 19s —— View job


Incremental Code Review

  • Gather context and read CLAUDE.md
  • Review files changed in this push
  • Post incremental review feedback

Push: fix(spec): complete Pilot Shell branding across README, website, console, and assets (ecde27a)

Files reviewed: .githooks/pre-commit, console/src/services/worker/http/routes/utils/planFileReader.ts, console/src/ui/viewer/layouts/DashboardLayout.tsx, console/src/ui/viewer/views/Spec/SpecContent.tsx, console/src/ui/viewer/views/Spec/SpecHeaderCard.tsx, console/src/ui/viewer/views/Spec/index.tsx, console/tests/ui/spec-task-navigation.test.ts, console/tests/worker/plan-deduplication.test.ts, console/tests/worker/ui-endpoints.test.ts, installer/steps/finalize.py, docs/site components, images (launcher/pilot files are git-crypt encrypted — skipped)


New Issues

🟡 Empty else-if branch in deduplicatePlans

console/src/services/worker/http/routes/utils/planFileReader.ts — The new deduplicatePlans function has an intentional no-op branch that reads as dead code:

if (planIsWorktree && !existingIsWorktree) {
  byName.set(plan.name, plan);       // prefer incoming worktree
} else if (!planIsWorktree && existingIsWorktree) {
  // ← empty: keep existing worktree (intentional no-op)
} else if (new Date(plan.modifiedAt).getTime() > ...) {
  byName.set(plan.name, plan);
}

The intent is clear from context, but an empty branch will confuse future readers. A minimal comment or restructure would help:

} else if (!planIsWorktree && existingIsWorktree) {
  // existing worktree copy is preferred — keep it
} else if (...)

Fix this →


🟡 Version regex in finalize.py still anchors to line end

installer/steps/finalize.py — The regex changed from r"Pilot v(.+)$"r" v(\S+)$", but the trailing $ anchor is still present. This differs from the install.sh fix in a prior push (which used s/.* v\([^ ]*\).*/\1/p — no end-anchor). If pilot --version ever outputs trailing content (e.g., a build tag or newline artifact), the Python regex will silently fail while the shell version would succeed.

# Current — still fragile if output has trailing content
match = re.search(r" v(\S+)$", result.stdout.strip())

# More robust (consistent with install.sh approach)
match = re.search(r" v(\S+)", result.stdout)

This was flagged as an outside-diff comment in the previous review; since finalize.py is now in scope for this push, noting it here. Fix this →


Fixed Issues

None of the previously reported issues are resolved by this push.


Still Open

  • 🔴 Version downgradeconsole/package.json is still 6.10.3; README.md:134 still shows export VERSION=6.10.3 vs 6.11.0 in CHANGELOG
  • 🔴 GitHub repo 404installer/steps/finalize.py (star repo message) and installer/steps/claude_files.py still reference https://github.com/maxritter/pilot-shell; confirm this repo exists
  • 🟡 CHANGELOG history rewrite — historical "Claude Pilot" entries still retroactively renamed
  • 🟡 Bundled stop guard refactor — behavioral change from #85 still merged into rename PR
  • 🟢 Demo repo linkREADME.md still references maxritter/pilot-shell-demo; confirm GitHub repo has been renamed

Delta Notes

planFileReader.tsdeduplicatePlans is a clean implementation. The worktree-preference logic is correct and the test suite in plan-deduplication.test.ts covers all meaningful permutations (empty, no dups, worktree vs main, order independence, recency tiebreaker). The function is correctly applied to getActivePlans, getAllPlans, getActiveSpecs, and getPlanStats.

Spec/index.tsx — task navigation is well-structured. handleTaskClick uses document.getElementById(\task-${n}`)which correctly matches theid="task-N"anchors added to

elements inSpecContent.tsx. The "Back to Tasks" floating button uses a scroll listener on document.querySelector("main")— this works given the currentDashboardLayout.tsxstructure where` is the scrollable container, but is worth noting as a layout coupling.

DashboardLayout.tsxh-screen + min-h-0 pattern is the standard fix for enabling overflow-y-auto on flex children. The change from min-h-screen to h-screen on the outer div is correct for constraining the viewport height.

.githooks/pre-commit — worktree skip logic is functionally correct: git rev-parse --git-dir returns .git in the main worktree and an absolute path like .git/worktrees/<name> in linked worktrees, so != ".git" correctly identifies linked worktrees. The leading --is-inside-work-tree check is redundant (pre-commit hooks always run inside a work tree) but harmless.

Version was rolled back to 6.10.3 during merge conflict resolution.
Restore to 6.11.0 in pilot/plugin.json, pilot/package.json,
console/package.json, and README install example. Fix JSON-LD
alternateName from "Claude Code Pilot" to "Claude Pilot".
@claude
Copy link

claude bot commented Feb 24, 2026

Claude finished @maxritter's task in 1m 9s —— View job


Incremental Code Review

  • Gather context and read CLAUDE.md
  • Review files changed in this push
  • Post incremental review feedback

Push: fix: restore version to 6.11.0 and fix SEO alternateName (7a04df0)

Files reviewed: README.md, console/package.json, docs/site/index.html (pilot/** files are git-crypt encrypted — skipped per policy)


New Issues

None introduced by this push.


Fixed Issues

✅ Resolved — Version downgrade in console/package.json

console/package.json:3 — Version restored from 6.10.36.11.0. Matches CHANGELOG.

✅ Resolved — Version in README.md pinned install example

README.md:130export VERSION=6.10.3export VERSION=6.11.0. Users will no longer be directed to install an outdated version.

✅ Resolved — alternateName SEO field in docs/site/index.html

docs/site/index.html:87"alternateName": "Claude Code Pilot""alternateName": "Claude Pilot". Now correctly references the actual previous name for legacy SEO discoverability.

The commit message indicates pilot/package.json and pilot/plugin.json were also restored to 6.11.0 — those files are encrypted and could not be directly verified, but assuming the commit is accurate this resolves the full version downgrade issue.


Still Open

  • 🔴 GitHub repo 404installer/steps/claude_files.py and installer/steps/finalize.py still reference https://github.com/maxritter/pilot-shell; confirm the repo exists at that URL before merge
  • 🟡 CHANGELOG history rewrite — historical "Claude Pilot" entries remain retroactively renamed to "Pilot Shell"
  • 🟡 Bundled stop guard refactor — behavioral change from #85 still merged into rename PR
  • 🟡 Empty else-if branch in deduplicatePlansconsole/src/services/worker/http/routes/utils/planFileReader.ts — add a comment to the intentional no-op branch
  • 🟡 Version regex end-anchor in finalize.pyre.search(r" v(\S+)$", ...) should drop the $ anchor for robustness
  • 🟡 React anti-pattern in Spec/index.tsxsetState in render body (via lastProjectRef comparison) should move into a useEffect
  • 🟢 Demo repo linkREADME.md references maxritter/pilot-shell-demo; confirm GitHub repo exists

Overall Status

The blocking version downgrade (🔴) is now resolved. The only remaining blocker before merge is confirming the https://github.com/maxritter/pilot-shell repo URL is live. The other open items are non-blocking improvements.


Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
README.md (1)

605-606: Tighten wording for clarity.

The sentence is a bit circular; a simpler phrasing reads better.

✍️ Possible rewording
-**Pull Requests** — New features, improvements, and bug fixes are welcome. You can improve Pilot Shell with Pilot Shell — a self-improving loop where your contributions make the tool that makes contributions better.
+**Pull Requests** — New features, improvements, and bug fixes are welcome. You can improve Pilot Shell with Pilot Shell — a self‑improving loop where your contributions improve the tool that helps you contribute.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 605 - 606, Replace the circular sentence in the Pull
Requests section that reads "You can improve Pilot Shell with Pilot Shell — a
self-improving loop where your contributions make the tool that makes
contributions better." with a concise, non‑recursive phrasing such as
"Contributions create a self‑improving loop: your pull requests help Pilot Shell
get better over time," ensuring you update the paragraph containing the "**Pull
Requests** — New features, improvements, and bug fixes are welcome." header to
use the new wording for clarity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.githooks/pre-commit:
- Around line 11-15: The current pre-commit hook unconditionally exits for any
linked worktree by checking git rev-parse --is-inside-work-tree and git
rev-parse --git-dir, which bypasses all gates; update the condition in the
.githooks/pre-commit script to perform an explicit opt-in instead (e.g., check
an env var like SKIP_PRE_COMMIT_WORKTREE or a branch-name prefix such as SPEC/),
so only when that env flag is set or the branch name matches the spec workflow
pattern the hook exits early; modify the existing worktree check block (the if
that calls git rev-parse --is-inside-work-tree and git rev-parse --git-dir) to
require the additional opt-in predicate before running exit 0.

In `@console/src/services/worker/http/routes/utils/planFileReader.ts`:
- Around line 174-195: The worktree detection in deduplicatePlans incorrectly
checks plan.filePath.includes("/.worktrees/") using a hardcoded forward slash,
which fails on Windows where path.join produces backslashes; update the check to
use a platform-safe test such as normalizing the path or using path.sep (e.g.,
normalize plan.filePath and existing.filePath or test for
`${path.sep}.worktrees${path.sep}`) so planIsWorktree and existingIsWorktree
correctly detect worktrees across OSes; ensure you import/use Node's path
utilities and apply the same logic to both plan.filePath and existing.filePath
before comparing.

In `@console/src/ui/viewer/views/Spec/SpecHeaderCard.tsx`:
- Around line 35-43: The task rows in SpecHeaderCard are using clickable divs
which aren’t keyboard-accessible and show interactive styles even when no
handler exists; update the elements that render task rows (inside SpecHeaderCard
where onTaskClick is referenced) to be semantic buttons when onTaskClick is
provided or, if you must keep the element, add role="button", tabIndex=0 and key
handlers (Enter/Space) and stopPropagation as needed, and conditionally apply
pointer/hover CSS only when onTaskClick is defined so rows are interactive
(focusable/clickable) only when the onTaskClick handler exists.

In `@README.md`:
- Around line 504-508: The blockquote contains an extra blank line that triggers
MD028; remove the empty line break inside the quote so each quoted paragraph is
contiguous (ensure no standalone line consisting only of '>' between the quoted
lines), e.g., merge the separated quote lines so every line in the blockquote
begins with '> ' and there are no blank '> ' lines separating the paragraphs in
README.md.

---

Nitpick comments:
In `@README.md`:
- Around line 605-606: Replace the circular sentence in the Pull Requests
section that reads "You can improve Pilot Shell with Pilot Shell — a
self-improving loop where your contributions make the tool that makes
contributions better." with a concise, non‑recursive phrasing such as
"Contributions create a self‑improving loop: your pull requests help Pilot Shell
get better over time," ensuring you update the paragraph containing the "**Pull
Requests** — New features, improvements, and bug fixes are welcome." header to
use the new wording for clarity.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 37f61cc and ecde27a.

⛔ Files ignored due to path filters (23)
  • docs/img/demo.gif is excluded by !**/*.gif
  • docs/img/logo.png is excluded by !**/*.png
  • docs/site/public/console/dashboard.png is excluded by !**/*.png
  • docs/site/public/console/memories.png is excluded by !**/*.png
  • docs/site/public/console/sessions.png is excluded by !**/*.png
  • docs/site/public/console/settings.png is excluded by !**/*.png
  • docs/site/public/console/specification.png is excluded by !**/*.png
  • docs/site/public/console/usage.png is excluded by !**/*.png
  • docs/site/public/console/vault.png is excluded by !**/*.png
  • docs/site/public/demo.gif is excluded by !**/*.gif
  • docs/site/public/favicon.ico is excluded by !**/*.ico
  • docs/site/public/favicon.png is excluded by !**/*.png
  • docs/site/public/logo.png is excluded by !**/*.png
  • docs/site/src/assets/box.png is excluded by !**/*.png
  • docs/site/src/assets/logo.png is excluded by !**/*.png
  • launcher/statusline/formatter.py is excluded by !launcher/**
  • launcher/tests/unit/statusline/test_formatter.py is excluded by !launcher/**
  • pilot/rules/testing.md is excluded by !pilot/**
  • pilot/rules/verification.md is excluded by !pilot/**
  • pilot/scripts/worker-service.cjs is excluded by !pilot/**
  • pilot/settings.json is excluded by !pilot/**
  • pilot/ui/viewer-bundle.js is excluded by !pilot/**
  • pilot/ui/viewer.css is excluded by !pilot/**
📒 Files selected for processing (23)
  • .githooks/pre-commit
  • README.md
  • console/src/services/worker/http/routes/utils/planFileReader.ts
  • console/src/ui/viewer/layouts/DashboardLayout.tsx
  • console/src/ui/viewer/views/Dashboard/index.tsx
  • console/src/ui/viewer/views/Spec/SpecContent.tsx
  • console/src/ui/viewer/views/Spec/SpecHeaderCard.tsx
  • console/src/ui/viewer/views/Spec/index.tsx
  • console/tests/ui/spec-task-navigation.test.ts
  • console/tests/worker/plan-deduplication.test.ts
  • console/tests/worker/ui-endpoints.test.ts
  • docs/site/src/components/DeepDiveSection.tsx
  • docs/site/src/components/DeploymentFlow.tsx
  • docs/site/src/components/FAQSection.tsx
  • docs/site/src/components/InstallSection.tsx
  • docs/site/src/components/WhatsInside.tsx
  • docs/site/src/content/blog/model-selection.md
  • docs/site/src/pages/DocsPage.tsx
  • docs/site/src/pages/docs/ConsoleSection.tsx
  • docs/site/src/pages/docs/ContextSection.tsx
  • docs/site/src/pages/docs/HooksSection.tsx
  • docs/site/src/pages/docs/ModelRoutingSection.tsx
  • installer/steps/finalize.py
✅ Files skipped from review due to trivial changes (2)
  • docs/site/src/pages/docs/ContextSection.tsx
  • docs/site/src/components/DeploymentFlow.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/site/src/pages/DocsPage.tsx
  • docs/site/src/content/blog/model-selection.md

Comment on lines +11 to +15
# --- Skip in worktrees (spec workflow commits are squash-merged later) ---
if [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ] && \
[ "$(git rev-parse --git-dir)" != ".git" ]; then
exit 0
fi
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid blanket pre-commit bypass for all worktrees.

This exits for any linked worktree, not just spec workflow commits, so it disables all test gates and artifact rebuilds for regular dev worktrees too. That increases the risk of untested changes or stale artifacts being committed. Consider making this skip explicit (env flag / branch prefix) so the default remains safe.

Suggested safer opt‑in gate
-# --- Skip in worktrees (spec workflow commits are squash-merged later) ---
-if [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ] && \
-   [ "$(git rev-parse --git-dir)" != ".git" ]; then
-  exit 0
-fi
+# --- Optional skip in worktrees (spec workflow commits are squash-merged later) ---
+if [ "${PRE_COMMIT_SKIP_WORKTREE:-0}" = "1" ]; then
+  if [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ] && \
+     [ "$(git rev-parse --git-dir)" != "$(git rev-parse --git-common-dir)" ]; then
+    exit 0
+  fi
+fi
📝 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
# --- Skip in worktrees (spec workflow commits are squash-merged later) ---
if [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ] && \
[ "$(git rev-parse --git-dir)" != ".git" ]; then
exit 0
fi
# --- Optional skip in worktrees (spec workflow commits are squash-merged later) ---
if [ "${PRE_COMMIT_SKIP_WORKTREE:-0}" = "1" ]; then
if [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ] && \
[ "$(git rev-parse --git-dir)" != "$(git rev-parse --git-common-dir)" ]; then
exit 0
fi
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.githooks/pre-commit around lines 11 - 15, The current pre-commit hook
unconditionally exits for any linked worktree by checking git rev-parse
--is-inside-work-tree and git rev-parse --git-dir, which bypasses all gates;
update the condition in the .githooks/pre-commit script to perform an explicit
opt-in instead (e.g., check an env var like SKIP_PRE_COMMIT_WORKTREE or a
branch-name prefix such as SPEC/), so only when that env flag is set or the
branch name matches the spec workflow pattern the hook exits early; modify the
existing worktree check block (the if that calls git rev-parse
--is-inside-work-tree and git rev-parse --git-dir) to require the additional
opt-in predicate before running exit 0.

Comment on lines +174 to +195
export function deduplicatePlans(plans: PlanInfo[]): PlanInfo[] {
const byName = new Map<string, PlanInfo>();
for (const plan of plans) {
const existing = byName.get(plan.name);
if (!existing) {
byName.set(plan.name, plan);
continue;
}
const planIsWorktree = plan.filePath.includes("/.worktrees/");
const existingIsWorktree = existing.filePath.includes("/.worktrees/");
if (planIsWorktree && !existingIsWorktree) {
byName.set(plan.name, plan);
} else if (!planIsWorktree && existingIsWorktree) {
} else if (
new Date(plan.modifiedAt).getTime() >
new Date(existing.modifiedAt).getTime()
) {
byName.set(plan.name, plan);
}
}
return Array.from(byName.values());
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Worktree detection uses hardcoded forward-slash separator — breaks on Windows.

Lines 182–183 use plan.filePath.includes("/.worktrees/") to distinguish worktree paths. Since filePath is built with path.join (line 103), it will contain backslashes on Windows (\.worktrees\), causing the check to always be false. Both copies would then fall through to the timestamp tiebreaker, silently losing the worktree-preference guarantee.

Consider using path.sep or normalizing to a common separator:

Suggested fix
-    const planIsWorktree = plan.filePath.includes("/.worktrees/");
-    const existingIsWorktree = existing.filePath.includes("/.worktrees/");
+    const worktreeSegment = `${path.sep}.worktrees${path.sep}`;
+    const planIsWorktree = plan.filePath.includes(worktreeSegment);
+    const existingIsWorktree = existing.filePath.includes(worktreeSegment);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@console/src/services/worker/http/routes/utils/planFileReader.ts` around lines
174 - 195, The worktree detection in deduplicatePlans incorrectly checks
plan.filePath.includes("/.worktrees/") using a hardcoded forward slash, which
fails on Windows where path.join produces backslashes; update the check to use a
platform-safe test such as normalizing the path or using path.sep (e.g.,
normalize plan.filePath and existing.filePath or test for
`${path.sep}.worktrees${path.sep}`) so planIsWorktree and existingIsWorktree
correctly detect worktrees across OSes; ensure you import/use Node's path
utilities and apply the same logic to both plan.filePath and existing.filePath
before comparing.

Comment on lines 35 to 43
export function SpecHeaderCard({
parsed,
spec,
onTaskClick,
}: {
parsed: ParsedPlan;
spec: SpecMeta;
onTaskClick?: (taskNumber: number) => void;
}) {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Make task rows keyboard-accessible and only interactive when a handler exists.

Clickable <div>s are not keyboard-accessible, and the pointer/hover styling implies interactivity even when onTaskClick is undefined. Use a semantic <button> (or add role, tabIndex, and key handlers) and conditionally apply interactive styles when a handler is present.

✅ Suggested fix (semantic button + conditional interactivity)
-        <div className="space-y-2">
-          {parsed.tasks.map((task) => (
-            <div
-              key={task.number}
-              className={`flex items-center gap-3 p-2 rounded-lg cursor-pointer transition-colors ${
-                task.completed
-                  ? "bg-success/10 hover:bg-success/15"
-                  : "bg-base-200/50 hover:bg-base-200"
-              }`}
-              onClick={() => onTaskClick?.(task.number)}
-            >
+        <div className="space-y-2">
+          {parsed.tasks.map((task) => {
+            const clickable = Boolean(onTaskClick);
+            return (
+              <button
+                type="button"
+                key={task.number}
+                disabled={!clickable}
+                onClick={() => onTaskClick?.(task.number)}
+                className={`w-full text-left flex items-center gap-3 p-2 rounded-lg transition-colors ${
+                  clickable ? "cursor-pointer" : "cursor-default"
+                } ${
+                  task.completed
+                    ? "bg-success/10 hover:bg-success/15"
+                    : "bg-base-200/50 hover:bg-base-200"
+                }`}
+              >
               <div
                 className={`w-5 h-5 rounded-md flex items-center justify-center ${
                   task.completed
                     ? "bg-success text-success-content"
                     : "bg-base-300"
                 }`}
               >
                 {task.completed ? (
                   <Icon icon="lucide:check" size={14} />
                 ) : (
                   <span className="text-xs text-base-content/50">
                     {task.number}
                   </span>
                 )}
               </div>
               <span
                 className={`text-sm ${task.completed ? "text-base-content/70" : "text-base-content"}`}
               >
                 Task {task.number}: {task.title}
               </span>
-            </div>
-          ))}
+              </button>
+            );
+          })}
         </div>

Also applies to: 83-112

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@console/src/ui/viewer/views/Spec/SpecHeaderCard.tsx` around lines 35 - 43,
The task rows in SpecHeaderCard are using clickable divs which aren’t
keyboard-accessible and show interactive styles even when no handler exists;
update the elements that render task rows (inside SpecHeaderCard where
onTaskClick is referenced) to be semantic buttons when onTaskClick is provided
or, if you must keep the element, add role="button", tabIndex=0 and key handlers
(Enter/Space) and stopPropagation as needed, and conditionally apply
pointer/hover CSS only when onTaskClick is defined so rows are interactive
(focusable/clickable) only when the onTaskClick handler exists.

Comment on lines 504 to 508
> "I stopped reviewing every line Claude writes. The hooks catch formatting and type errors automatically, TDD catches logic errors, and the spec verifier catches everything else. I review the plan, approve it, and the output is production-grade."

> "Other frameworks I tried added so much overhead that half my tokens went to the system itself. Pilot is lean — quick mode has zero scaffolding, and even /spec only adds structure where it matters. More of my context goes to actual work."
> "Other frameworks I tried added so much overhead that half my tokens went to the system itself. Pilot Shell is lean — quick mode has zero scaffolding, and even /spec only adds structure where it matters. More of my context goes to actual work."

> "The persistent memory changed everything. I can pick up a project after a week and Claude already knows my architecture decisions, the bugs we fixed, and why we chose certain patterns. No more re-explaining the same context every session."
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix MD028: remove the blank line inside the blockquote.

markdownlint flags a blank line inside the blockquote, which breaks blockquote formatting consistency.

🛠️ Suggested edit
 > "I stopped reviewing every line Claude writes. The hooks catch formatting and type errors automatically, TDD catches logic errors, and the spec verifier catches everything else. I review the plan, approve it, and the output is production-grade."
-
 > "Other frameworks I tried added so much overhead that half my tokens went to the system itself. Pilot Shell is lean — quick mode has zero scaffolding, and even /spec only adds structure where it matters. More of my context goes to actual work."
📝 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
> "I stopped reviewing every line Claude writes. The hooks catch formatting and type errors automatically, TDD catches logic errors, and the spec verifier catches everything else. I review the plan, approve it, and the output is production-grade."
> "Other frameworks I tried added so much overhead that half my tokens went to the system itself. Pilot is lean — quick mode has zero scaffolding, and even /spec only adds structure where it matters. More of my context goes to actual work."
> "Other frameworks I tried added so much overhead that half my tokens went to the system itself. Pilot Shell is lean — quick mode has zero scaffolding, and even /spec only adds structure where it matters. More of my context goes to actual work."
> "The persistent memory changed everything. I can pick up a project after a week and Claude already knows my architecture decisions, the bugs we fixed, and why we chose certain patterns. No more re-explaining the same context every session."
> "I stopped reviewing every line Claude writes. The hooks catch formatting and type errors automatically, TDD catches logic errors, and the spec verifier catches everything else. I review the plan, approve it, and the output is production-grade."
> "Other frameworks I tried added so much overhead that half my tokens went to the system itself. Pilot Shell is lean — quick mode has zero scaffolding, and even /spec only adds structure where it matters. More of my context goes to actual work."
> "The persistent memory changed everything. I can pick up a project after a week and Claude already knows my architecture decisions, the bugs we fixed, and why we chose certain patterns. No more re-explaining the same context every session."
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 505-505: Blank line inside blockquote

(MD028, no-blanks-blockquote)


[warning] 507-507: Blank line inside blockquote

(MD028, no-blanks-blockquote)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 504 - 508, The blockquote contains an extra blank
line that triggers MD028; remove the empty line break inside the quote so each
quoted paragraph is contiguous (ensure no standalone line consisting only of '>'
between the quoted lines), e.g., merge the separated quote lines so every line
in the blockquote begins with '> ' and there are no blank '> ' lines separating
the paragraphs in README.md.

@maxritter maxritter merged commit e99c4ed into main Feb 24, 2026
20 of 21 checks passed
@maxritter maxritter deleted the dev branch February 24, 2026 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant