fix(installer): make pai/opencode work on fresh machines#100
fix(installer): make pai/opencode work on fresh machines#100Steffen025 merged 4 commits intomainfrom
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughReplaces the CLI runtime and messaging from Claude/ Changes
Sequence DiagramsequenceDiagram
participant User
participant Shell as Shell\n(bash|zsh|fish)
participant Wrapper as pai/opencode\nwrapper
participant Resolver as resolveOpenCodeExecutable()
participant Binary as opencode\nbinary
User->>Shell: run `pai` or `opencode`
Shell->>Wrapper: invoke wrapper function
Wrapper->>Resolver: resolve opencode path
alt found in ~/.local/bin
Resolver-->>Wrapper: "rgba(0,128,0,0.5) ~/.local/bin/opencode"
else found in ~/.opencode/tools
Resolver-->>Wrapper: "rgba(0,128,0,0.5) ~/.opencode/tools/opencode"
else found on PATH
Resolver-->>Wrapper: "rgba(0,128,0,0.5) opencode (PATH)"
else not found
Resolver-->>Wrapper: "rgba(255,0,0,0.5) not found -> error"
end
Wrapper->>Binary: exec resolved opencode with args
Binary-->>User: returns output
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 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 docstrings
🧪 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 |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
PAI-Install/engine/validate.ts (1)
229-229:⚠️ Potential issue | 🔴 CriticalCritical: Marker string mismatch causes validation to always fail.
The validation checks for
"# PAI alias"butactions.ts(line 797) andsteps-fresh.ts(lines 431-432) write"# PAI shell setup"as the marker. This means the shell alias validation will never find configurations written by the current installer.🐛 Proposed fix to match the installer's marker
- if (!content.includes("# PAI alias")) continue; + if (!content.includes("# PAI shell setup")) continue;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@PAI-Install/engine/validate.ts` at line 229, The validation currently checks for the wrong marker string ("# PAI alias") so it never matches installer output; update the check in validate.ts where it reads if (!content.includes("# PAI alias")) continue; to use the installer's marker ("# PAI shell setup") so the shell alias sections created by actions.ts and steps-fresh.ts are correctly detected..opencode/PAI/Tools/pai.ts (1)
476-493:⚠️ Potential issue | 🟠 MajorUpdate mechanism still installs Claude Code instead of OpenCode.
The
cmdUpdate()function (lines 476-493) attempts to install fromhttps://claude.ai/install.shand checks for updates againstclaude-code-diststorage, but pai.ts is located in.opencode/PAI/Tools/and configured to use~/.opencode/paths. The version check (line 169) and installation script need to be updated to either upgrade OpenCode or removed entirely if OpenCode self-updates. Update command usage (lines 14, 604, 631) also needs corresponding documentation changes.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.opencode/PAI/Tools/pai.ts around lines 476 - 493, The cmdUpdate() block currently invokes Claude's installer and checks/update storage named for Claude; change that to update OpenCode (or remove the installer call if OpenCode self-updates): replace the spawnSync call that runs "curl -fsSL https://claude.ai/install.sh | bash" (the claudeResult usage) with the correct OpenCode install/update command or omit it, and update any storage key or version-check logic that references "claude-code-dist" to the OpenCode equivalent (so the version check variable used earlier aligns with the ~/.opencode/ paths). Also keep the Bun upgrade logic (bunResult) but ensure log/error messages reference OpenCode instead of Claude, and update the command usage documentation strings or help text elsewhere in the file to reflect OpenCode update behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.opencode/PAI/Tools/pai.ts:
- Around line 132-147: The resolveOpenCodeExecutable function currently checks
PATH first via spawnSync(["opencode","--version"]) then LOCAL_OPENCODE_BIN and
COMPAT_OPENCODE_BIN, which conflicts with the installer shell wrapper order;
update resolveOpenCodeExecutable to first check existsSync(LOCAL_OPENCODE_BIN),
then existsSync(COMPAT_OPENCODE_BIN), and only then fall back to testing PATH
with spawnSync/exitCode and return "opencode" if found; keep the final
error(...) call unchanged and reference the same symbols
(resolveOpenCodeExecutable, LOCAL_OPENCODE_BIN, COMPAT_OPENCODE_BIN, spawnSync,
error).
In `@PAI-Install/engine/actions.ts`:
- Around line 794-795: The fish block in the aliasLine uses the invalid "and"
operator inside the if/else for the pai function; update the fisk function
definitions (opencode and pai) so the pai function uses a proper if/else branch
instead of "and" — e.g., in the pai function (which sets __pai_oldpwd, __pai_bun
and cds to paiDir) replace the lines "if test -x $__pai_bun\n\t\tand $__pai_bun
run .opencode/PAI/Tools/pai.ts $argv\n\telse\n\t\tand bun run
.opencode/PAI/Tools/pai.ts $argv\n\tend" with a normal if body that directly
invokes "$__pai_bun run .opencode/PAI/Tools/pai.ts $argv" in the if branch and
"bun run .opencode/PAI/Tools/pai.ts $argv" in the else branch (keeping the
surrounding cd and cd back to __pai_oldpwd), and update aliasLine to include
this corrected multi-line fish function string.
In `@PAI-Install/engine/steps-fresh.ts`:
- Line 431: The fish function uses the combinator "and" incorrectly inside the
pai function; update the pai function (and keep opencode unchanged) to call the
commands directly inside the if/else branches: after setting __pai_bun and
changing to the install dir, use "if test -x $__pai_bun" then execute
"$__pai_bun run .opencode/PAI/Tools/pai.ts $argv" in that branch, otherwise
execute "bun run .opencode/PAI/Tools/pai.ts $argv" in the else branch, and then
cd back to $__pai_oldpwd; remove the stray "and" tokens so the fish conditional
blocks contain plain command invocations.
---
Outside diff comments:
In @.opencode/PAI/Tools/pai.ts:
- Around line 476-493: The cmdUpdate() block currently invokes Claude's
installer and checks/update storage named for Claude; change that to update
OpenCode (or remove the installer call if OpenCode self-updates): replace the
spawnSync call that runs "curl -fsSL https://claude.ai/install.sh | bash" (the
claudeResult usage) with the correct OpenCode install/update command or omit it,
and update any storage key or version-check logic that references
"claude-code-dist" to the OpenCode equivalent (so the version check variable
used earlier aligns with the ~/.opencode/ paths). Also keep the Bun upgrade
logic (bunResult) but ensure log/error messages reference OpenCode instead of
Claude, and update the command usage documentation strings or help text
elsewhere in the file to reflect OpenCode update behavior.
In `@PAI-Install/engine/validate.ts`:
- Line 229: The validation currently checks for the wrong marker string ("# PAI
alias") so it never matches installer output; update the check in validate.ts
where it reads if (!content.includes("# PAI alias")) continue; to use the
installer's marker ("# PAI shell setup") so the shell alias sections created by
actions.ts and steps-fresh.ts are correctly detected.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 98bdefe1-8d89-4976-bcf9-99f32db198e1
📒 Files selected for processing (4)
.opencode/PAI/Tools/pai.tsPAI-Install/engine/actions.tsPAI-Install/engine/steps-fresh.tsPAI-Install/engine/validate.ts
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.opencode/PAI/Tools/pai.ts (1)
594-637:⚠️ Potential issue | 🟠 MajorHelp/output still points users at
k, not the installedpaicommand.Fresh installs only wire
pai()/opencode(), so the usage/examples here send users to a nonexistent command. Please finish the rename here and sweep the remaining user-facingkhints in this file.💡 Update the visible command name
- k Launch OpenCode (no MCPs, max performance) + pai Launch OpenCode (no MCPs, max performance) @@ - k update Update runtime dependencies + pai update Update runtime dependencies @@ - k update Update OpenCode + pai update Update OpenCode🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.opencode/PAI/Tools/pai.ts around lines 594 - 637, The help text returned by cmdHelp() still uses the old "k" CLI name; update the multi-line string in function cmdHelp() to replace all user-facing occurrences of "k" with "pai" (including flags, examples, COMMANDS list, MCP SHORTCUTS examples and any shorthand usages like "k -m", "k update", "k prompt", etc.), and then search this file for any remaining visible "k" hints outside cmdHelp() and replace them with "pai" so all user-facing guidance matches the installed command name.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.opencode/PAI/Tools/pai.ts:
- Around line 132-143: The resolver resolveOpenCodeExecutable currently returns
LOCAL_OPENCODE_BIN or COMPAT_OPENCODE_BIN based only on existsSync; change it to
also check that the file is executable (use fs.accessSync(path,
fs.constants.X_OK) or the equivalent) and only return those paths when the
executable bit is present; if accessSync throws or the check fails, fall through
to the PATH check (the spawnSync block). Also update the fs import to include
accessSync and constants so you can perform the X_OK check.
In `@PAI-Install/engine/actions.ts`:
- Around line 807-816: The current cleanup uses a broad regex on the variable
content that can delete user-added non-comment lines; change to use explicit
start and end markers and only remove between them: introduce a unique end
marker (e.g., "# end PAI shell setup") and update the first replace call that
currently references marker to match from the start marker to that end marker
only (non-greedy, across lines), then when appending the new block ensure you
write both the start marker and the matching end marker around aliasLine (use
the existing marker and aliasLine variables to build the block, e.g., `${marker}
— added by PAI installer\n${aliasLine}\n# end PAI shell setup`), and remove or
relax any other broad regexes that previously tried to clean variants (lines
calling replace(/^#\s*(?:PAI|CORE).../) etc.) so they no longer risk removing
user content—target only the explicit bracketed block for deletion.
- Around line 793-795: The fish `pai` wrapper in the aliasLine overwrites the
child process exit status by doing `cd $__pai_oldpwd` after running the tool;
fix it by capturing the child exit status immediately after the run command (use
Fish's $status, e.g. `set -l __pai_status $status`) and then restore the
directory and return/exit with that saved status (e.g. `cd $__pai_oldpwd` then
`return $__pai_status`); apply the same change to the other fish wrapper in the
code mentioned (steps-fresh's pai wrapper).
In `@PAI-Install/engine/steps-fresh.ts`:
- Around line 443-447: The PAI cleanup regex can run to EOF and misses legacy
markers; update the first content.replace so the PAI block match is explicitly
bounded by the next top-level comment OR the next shell/function block
(lookahead for "\n#" OR the next function starts such as pai(), opencode(),
function pai, function opencode) and make the alternation include older marker
variants (e.g. alias|shell setup|setup|installer|installed|PAI) so legacy
installer markers are removed; similarly ensure the other removals that target
pai()/opencode()/function pai/function opencode use those same bounded
lookaheads so they never greedily consume unrelated trailing shell code.
- Around line 430-431: The fish `pai` function currently runs the bun command
then does `cd $__pai_oldpwd` last, which masks the bun exit status; update the
`pai` function (function pai, variables __pai_oldpwd and __pai_bun) to capture
the child exit code into a local variable immediately after the bun/OpenCode
invocation (using set -l __pai_status $status), then perform `cd $__pai_oldpwd`,
and finally return that saved status (return $__pai_status) so the wrapper
preserves and propagates the original command's exit status.
---
Outside diff comments:
In @.opencode/PAI/Tools/pai.ts:
- Around line 594-637: The help text returned by cmdHelp() still uses the old
"k" CLI name; update the multi-line string in function cmdHelp() to replace all
user-facing occurrences of "k" with "pai" (including flags, examples, COMMANDS
list, MCP SHORTCUTS examples and any shorthand usages like "k -m", "k update",
"k prompt", etc.), and then search this file for any remaining visible "k" hints
outside cmdHelp() and replace them with "pai" so all user-facing guidance
matches the installed command name.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: a804dc6e-067e-4744-9c8d-afc82b65371b
📒 Files selected for processing (4)
.opencode/PAI/Tools/pai.tsPAI-Install/engine/actions.tsPAI-Install/engine/steps-fresh.tsPAI-Install/engine/validate.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- PAI-Install/engine/validate.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
PAI-Install/engine/steps-fresh.ts (1)
443-462: Cleanup regex could over-delete if shell config has non-standard content after PAI block.The lookahead boundary
(?=\n(?:#|pai\(\)|opencode\(\)|function\s+pai\b|function\s+opencode\b)|$)only stops at:
- Comments starting with
#- Function definitions (
pai(),opencode(),function pai,function opencode)- End of file
If a user has content like
alias ll='ls -la'orexport JAVA_HOME=...immediately after the PAI block (without a preceding comment), the regex will continue to EOF and delete that content.This is mitigated if the explicit end marker is added (per previous comment), which would allow using the more precise regex from actions.ts:
/\n?# PAI shell setup — added by PAI installer[\s\S]*?# end PAI shell setup\n?/g🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@PAI-Install/engine/steps-fresh.ts` around lines 443 - 462, The current cleanup regexes applied to content (the replace calls that remove pai()/opencode() blocks and PAI sections) use a lookahead that only stops at comments or specific function signatures, which can over-delete trailing non-comment shell lines like "alias ..." or "export ..."; update these replace invocations on content to either require and match an explicit end marker (use the same explicit marker pattern from actions.ts, e.g. the "PAI shell setup — added by PAI installer" start and matching "# end PAI shell setup" end) or broaden the lookahead to include common shell constructs (e.g. lines starting with alias, export, export -n, set, source, function definitions) so deletion stops correctly; adjust the regexes that target the PAI block and the pai()/opencode() function bodies accordingly so pai(), opencode(), and function pai/opencode patterns are preserved as anchors but safe against removing unrelated config lines.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@PAI-Install/engine/steps-fresh.ts`:
- Around line 430-432: The fish branch of aliasBlock in steps-fresh.ts is
missing the end marker "# end PAI shell setup", causing mismatched cleanup with
actions.ts; update the fish template (the template string assigned to aliasBlock
when shellName === "fish") to include the same end marker line used in
actions.ts after the generated functions so the start and end markers match the
cleanup regex and ensure both creation and removal work consistently.
---
Nitpick comments:
In `@PAI-Install/engine/steps-fresh.ts`:
- Around line 443-462: The current cleanup regexes applied to content (the
replace calls that remove pai()/opencode() blocks and PAI sections) use a
lookahead that only stops at comments or specific function signatures, which can
over-delete trailing non-comment shell lines like "alias ..." or "export ...";
update these replace invocations on content to either require and match an
explicit end marker (use the same explicit marker pattern from actions.ts, e.g.
the "PAI shell setup — added by PAI installer" start and matching "# end PAI
shell setup" end) or broaden the lookahead to include common shell constructs
(e.g. lines starting with alias, export, export -n, set, source, function
definitions) so deletion stops correctly; adjust the regexes that target the PAI
block and the pai()/opencode() function bodies accordingly so pai(), opencode(),
and function pai/opencode patterns are preserved as anchors but safe against
removing unrelated config lines.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 38c61367-b138-484a-bac5-e67597f757b0
📒 Files selected for processing (3)
.opencode/PAI/Tools/pai.tsPAI-Install/engine/actions.tsPAI-Install/engine/steps-fresh.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- PAI-Install/engine/actions.ts
Problem: fresh installs could finish but leave broken commands. pai failed when bun PATH was missing, opencode was not always resolvable, and pai launcher still tried to spawn claude. This PR hardens installer shell wiring and launcher resolution. Changes: add shell PATH wiring for ~/.bun/bin and ~/.local/bin, add opencode fallback wrapper function, make pai prefer explicit ~/.bun/bin/bun, keep shell block cleanup idempotent, update pai launcher to resolve and run opencode from PATH/local/compat locations, and add critical validation checks for shell path wiring and bun runtime presence. Related to #99 but broader because installer and validation also needed fixes.
Summary by CodeRabbit
New Features
Chores