Conversation
…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
…lot to pilot-shell
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.
# Conflicts: # README.md
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
Claude finished @maxritter's task in 4m 9s —— View job Code Review
SummaryThis is a comprehensive project rename from Claude Pilot → Pilot 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 FilesThree package files regressed from
The commit message for Action needed: These should all be 🟡 CHANGELOG History RewriteThe CHANGELOG rewrites historical entries — e.g., changing 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 🟡 Bundled Functional Change: Stop Guard Refactor
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 ( 🟢 Demo Repository Link
What Looks GoodBackward compatibility is handled well. Version parsing fix is correct. The sed pattern change from Rename coverage is comprehensive. A grep scan of non-launcher source files shows zero stale Test updates are consistent.
VerdictApprove after fixing the version downgrade in the three package files. The version mismatch between |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review infoConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (4)
📒 Files selected for processing (3)
WalkthroughRebrands 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
Sequence Diagram(s)mermaid Client->>Server: GET /plans Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
Claude finished @maxritter's task in 1m 20s —— View job Incremental Code Review
Push:
|
There was a problem hiding this comment.
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 | 🟡 MinorVersion parsing may fail if
pilot --versionincludes trailing tokens.
Anchoring to end can miss versions likePilot Shell v1.2.3 (build abc). Consider matching the firstv<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 auseEffect.Calling
setStatedirectly in the render body (outside auseEffect) 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
lastProjectRefcan 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
⛔ Files ignored due to path filters (30)
launcher/__init__.pyis excluded by!launcher/**launcher/banner.pyis excluded by!launcher/**launcher/build.pyis excluded by!launcher/**launcher/cli.pyis excluded by!launcher/**launcher/config.pyis excluded by!launcher/**launcher/model_config.pyis excluded by!launcher/**launcher/settings_injector.pyis excluded by!launcher/**launcher/statusline/__init__.pyis excluded by!launcher/**launcher/statusline/formatter.pyis excluded by!launcher/**launcher/statusline/widgets.pyis excluded by!launcher/**launcher/tests/integration/test_license_flow.pyis excluded by!launcher/**launcher/tests/unit/statusline/test_formatter.pyis excluded by!launcher/**launcher/tests/unit/statusline/test_widgets.pyis excluded by!launcher/**launcher/tests/unit/test_banner.pyis excluded by!launcher/**launcher/tests/unit/test_cli.pyis excluded by!launcher/**launcher/updater.pyis excluded by!launcher/**launcher/wrapper.pyis excluded by!launcher/**pilot/hooks/hooks.jsonis excluded by!pilot/**pilot/hooks/spec_stop_guard.pyis excluded by!pilot/**pilot/hooks/tests/test_spec_stop_guard.pyis excluded by!pilot/**pilot/package.jsonis excluded by!pilot/**pilot/plugin.jsonis excluded by!pilot/**pilot/rules/task-and-workflow.mdis excluded by!pilot/**pilot/scripts/mcp-server.cjsis excluded by!pilot/**pilot/scripts/worker-service.cjsis excluded by!pilot/**pilot/settings.jsonis excluded by!pilot/**pilot/ui/index.htmlis excluded by!pilot/**pilot/ui/viewer-bundle.jsis excluded by!pilot/**pilot/ui/viewer.cssis excluded by!pilot/**uv.lockis excluded by!**/*.lock
📒 Files selected for processing (68)
.devcontainer/devcontainer.json.github/ISSUE_TEMPLATE/bug_report.md.github/ISSUE_TEMPLATE/config.ymlCHANGELOG.mdLICENSEREADME.mdcliff.tomlconsole/package.jsonconsole/src/services/worker-service.tsconsole/src/ui/viewer/App.tsxconsole/src/ui/viewer/components/ActivationModal.tsxconsole/src/ui/viewer/components/Header.tsxconsole/src/ui/viewer/components/LicenseGate.tsxconsole/src/ui/viewer/hooks/useTheme.tsconsole/src/ui/viewer/index.htmlconsole/src/ui/viewer/layouts/DashboardLayout.tsxconsole/src/ui/viewer/layouts/Sidebar/SidebarFooter.tsxconsole/src/ui/viewer/layouts/Sidebar/SidebarLogo.tsxconsole/src/ui/viewer/layouts/Topbar/TopbarActions.tsxconsole/src/ui/viewer/layouts/Topbar/index.tsxconsole/src/ui/viewer/styles/main.cssconsole/src/ui/viewer/viewer.htmlconsole/src/ui/viewer/views/Settings/index.tsxconsole/src/ui/viewer/views/Spec/index.tsxconsole/tests/context/cross-session-isolation.test.tsconsole/tests/ui/activation-modal.test.tsconsole/tests/ui/license-gate.test.tsconsole/tests/ui/project-selector.test.tsdocs/site/index.htmldocs/site/public/manifest.jsondocs/site/public/robots.txtdocs/site/src/components/ComparisonSection.tsxdocs/site/src/components/DemoSection.tsxdocs/site/src/components/FAQSection.tsxdocs/site/src/components/Footer.tsxdocs/site/src/components/HeroSection.tsxdocs/site/src/components/InstallSection.tsxdocs/site/src/components/Logo.tsxdocs/site/src/components/NavBar.tsxdocs/site/src/components/NotFound.tsxdocs/site/src/components/SEO.tsxdocs/site/src/components/WorkshopsSection.tsxdocs/site/src/content/blog/claude-code-hooks-guide.mddocs/site/src/content/blog/context-buffer-management.mddocs/site/src/content/blog/installation-guide.mddocs/site/src/content/blog/managing-context-long-sessions.mddocs/site/src/content/blog/mcp-servers-claude-code.mddocs/site/src/content/blog/model-selection.mddocs/site/src/content/blog/sandboxing-claude-code.mddocs/site/src/content/blog/spec-driven-development.mddocs/site/src/pages/BlogArticlePage.tsxdocs/site/src/pages/BlogPage.tsxdocs/site/src/pages/DocsPage.tsxdocs/site/src/pages/Index.tsxdocs/site/src/pages/docs/InstallationSection.tsxdocs/site/vite-plugin-sitemap.tsinstall.shinstaller/__init__.pyinstaller/cli.pyinstaller/steps/claude_files.pyinstaller/steps/finalize.pyinstaller/steps/shell_config.pyinstaller/tests/unit/steps/test_claude_files.pyinstaller/tests/unit/steps/test_finalize.pyinstaller/tests/unit/test_install_sh.pyinstaller/ui.pypyproject.tomluninstall.sh
| 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") |
There was a problem hiding this comment.
🧩 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/installRepository: 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 -A1Repository: 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 finished @maxritter's task in 1m 15s —— View job Incremental Code Review
Push:
|
There was a problem hiding this comment.
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
alternateNamereferences 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 tohttps://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 clarifyingccpas 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
⛔ Files ignored due to path filters (5)
launcher/banner.pyis excluded by!launcher/**launcher/cli.pyis excluded by!launcher/**pilot/scripts/worker-service.cjsis excluded by!pilot/**pilot/ui/viewer-bundle.jsis excluded by!pilot/**pilot/ui/viewer.cssis excluded by!pilot/**
📒 Files selected for processing (9)
README.mddocs/site/index.htmldocs/site/public/manifest.jsondocs/site/src/components/Footer.tsxdocs/site/src/components/HeroSection.tsxdocs/site/src/components/Logo.tsxdocs/site/src/components/SEO.tsxdocs/site/src/pages/Index.tsxinstaller/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 finished @maxritter's task in 4m 19s —— View job Incremental Code Review
Push:
|
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 finished @maxritter's task in 1m 9s —— View job Incremental Code Review
Push:
|
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (23)
docs/img/demo.gifis excluded by!**/*.gifdocs/img/logo.pngis excluded by!**/*.pngdocs/site/public/console/dashboard.pngis excluded by!**/*.pngdocs/site/public/console/memories.pngis excluded by!**/*.pngdocs/site/public/console/sessions.pngis excluded by!**/*.pngdocs/site/public/console/settings.pngis excluded by!**/*.pngdocs/site/public/console/specification.pngis excluded by!**/*.pngdocs/site/public/console/usage.pngis excluded by!**/*.pngdocs/site/public/console/vault.pngis excluded by!**/*.pngdocs/site/public/demo.gifis excluded by!**/*.gifdocs/site/public/favicon.icois excluded by!**/*.icodocs/site/public/favicon.pngis excluded by!**/*.pngdocs/site/public/logo.pngis excluded by!**/*.pngdocs/site/src/assets/box.pngis excluded by!**/*.pngdocs/site/src/assets/logo.pngis excluded by!**/*.pnglauncher/statusline/formatter.pyis excluded by!launcher/**launcher/tests/unit/statusline/test_formatter.pyis excluded by!launcher/**pilot/rules/testing.mdis excluded by!pilot/**pilot/rules/verification.mdis excluded by!pilot/**pilot/scripts/worker-service.cjsis excluded by!pilot/**pilot/settings.jsonis excluded by!pilot/**pilot/ui/viewer-bundle.jsis excluded by!pilot/**pilot/ui/viewer.cssis excluded by!pilot/**
📒 Files selected for processing (23)
.githooks/pre-commitREADME.mdconsole/src/services/worker/http/routes/utils/planFileReader.tsconsole/src/ui/viewer/layouts/DashboardLayout.tsxconsole/src/ui/viewer/views/Dashboard/index.tsxconsole/src/ui/viewer/views/Spec/SpecContent.tsxconsole/src/ui/viewer/views/Spec/SpecHeaderCard.tsxconsole/src/ui/viewer/views/Spec/index.tsxconsole/tests/ui/spec-task-navigation.test.tsconsole/tests/worker/plan-deduplication.test.tsconsole/tests/worker/ui-endpoints.test.tsdocs/site/src/components/DeepDiveSection.tsxdocs/site/src/components/DeploymentFlow.tsxdocs/site/src/components/FAQSection.tsxdocs/site/src/components/InstallSection.tsxdocs/site/src/components/WhatsInside.tsxdocs/site/src/content/blog/model-selection.mddocs/site/src/pages/DocsPage.tsxdocs/site/src/pages/docs/ConsoleSection.tsxdocs/site/src/pages/docs/ContextSection.tsxdocs/site/src/pages/docs/HooksSection.tsxdocs/site/src/pages/docs/ModelRoutingSection.tsxinstaller/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
| # --- 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 |
There was a problem hiding this comment.
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.
| # --- 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.
| 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()); | ||
| } |
There was a problem hiding this comment.
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.
| export function SpecHeaderCard({ | ||
| parsed, | ||
| spec, | ||
| onTaskClick, | ||
| }: { | ||
| parsed: ParsedPlan; | ||
| spec: SpecMeta; | ||
| onTaskClick?: (taskNumber: number) => void; | ||
| }) { |
There was a problem hiding this comment.
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.
| > "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." |
There was a problem hiding this comment.
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.
| > "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.
Summary
claude-pilot.comtopilot-shell.commaxritter/claude-pilottomaxritter/pilot-shellCLAUDE_PILOT_*env var keys intentionally kept as-is)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
Summary by CodeRabbit
New Features
Chores
Tests
Documentation