feat: migrate Claude Code installation from npm to native installer - #427
Conversation
- Replace npm installation with curl-based native installer - Update Dockerfile to use https://claude.ai/install.sh - Modify update-claude-code.sh to use `claude update` command - Remove @anthropic-ai/claude-code from npm/global.json - Update documentation to reflect new installation method - Bump devcontainer image to 1.62.2 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📝 WalkthroughWalkthroughThe changes migrate Claude Code installation and updates from npm-based management to a native Claude installer. Configuration files, documentation, installation scripts, and dependency declarations are updated to reflect this shift away from npm and toward the native installation approach. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 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 |
🔍 AI Code Review (Local Hook)Models: Codex (gpt-5.2-codex) / Gemini (gemini-2.5-pro) 🤖 Codex ReviewFindings
Verdict ✨ Gemini ReviewHere is my review of the proposed code change. Findings
Verdict
|
PR Review - Claude Code Native Installer Migration概要このPRはClaude Codeのインストールをnpmからネイティブインストーラーへ移行する変更です。Issue #422の要件を適切に実装しています。 ✅ 良い点1. 包括的な実装
2. エラーハンドリングの改善
3. シンプル化更新スクリプトが大幅に簡素化され(58行から59行へ)、 🔍 改善提案1. Dockerfile: ユーザーコンテキストの問題(重要).devcontainer/Dockerfile:69-70で、 問題点: USER root
# この時点でHOME=/root になる
RUN curl -fsSL https://claude.ai/install.sh | bash \
&& echo 'export PATH="$HOME/.claude/local/bin:$PATH"' >> /home/vscode/.bashrc推奨修正: USER vscode
RUN curl -fsSL https://claude.ai/install.sh | bash \
&& echo 'export PATH="$HOME/.claude/local/bin:$PATH"' >> ~/.bashrcまたは、rootユーザーとして実行する場合はHOME環境変数を明示的に設定: USER root
RUN HOME=/home/vscode curl -fsSL https://claude.ai/install.sh | bash \
&& chown -R vscode:vscode /home/vscode/.claude2. セキュリティ: インストールスクリプトの検証
推奨: # スクリプトをダウンロードして検証してからインストール
curl -fsSL https://claude.ai/install.sh -o /tmp/claude-install.sh
# チェックサムまたは署名検証(可能であれば)
bash /tmp/claude-install.sh
rm /tmp/claude-install.shまたは、インストールスクリプトをリポジトリにコミットして内容を固定する方法も検討できます。 3. エラーメッセージの改善
推奨: current_version=$(claude --version 2>&1 | head -1 || echo "インストールされていないか、パスが通っていません")4. テストカバレッジPRのテストプランに以下を追加することを推奨します:
🐛 潜在的な問題5. Dockerfile行69: PATH設定の問題
検証が必要:
📝 ドキュメント6. マイグレーション手順の追加既存ユーザー向けに、npm版からネイティブ版への移行手順をREADMEまたはCHANGELOGに記載することを推奨します。 例: ## Migration from npm to Native Installer
既存のnpm版をアンインストールし、ネイティブインストーラーに移行してください:
\`\`\`bash
# npm版をアンインストール
npm uninstall -g @anthropic-ai/claude-code
# ネイティブ版をインストール
curl -fsSL https://claude.ai/install.sh | bash
\`\`\`🎯 総合評価
🚀 推奨アクション必須(マージ前)
推奨(マージ後でも可)
✅ 承認条件Dockerfileのユーザーコンテキスト問題(改善提案#1)を修正後、承認可能です。その他の提案は優先度が低いため、別PRでの対応でも問題ありません。 全体として、npmからネイティブインストーラーへの移行という重要な変更を適切に実装しており、コードの簡素化にも貢献しています。👍 参考: |
- Update post_pr_ai_review.py prompts to output in Japanese - Update codex-review.md skill prompt to Japanese - Ensures Codex and Gemini review comments on PRs are in Japanese Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🔍 PRレビュー結果📊 変更概要Claude Codeのインストール方法をnpm経由からネイティブインストーラーへ移行する変更です。 変更規模: +85行 / -113行 (8ファイル変更) ✅ 良い点
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @.devcontainer/Dockerfile:
- Around line 68-71: The installer is run as root so Claude is installed into
/root/.local/bin and the PATH appended points to the wrong directory; run the
installer as the vscode user (or set HOME=/home/vscode when invoking the
installer) so the binary installs to /home/vscode/.local/bin, then append the
correct PATH entry ($HOME/.local/bin) to the vscode user's shell rc (use
/home/vscode/.bashrc) and ensure ownership of installed files is vscode; look
for the RUN curl...| bash invocation and the echo 'export
PATH=...'/home/vscode/.bashrc to update invocation user, HOME, PATH target, and
file ownership (chown) accordingly.
In `@script/update-claude-code.sh`:
- Around line 23-52: Do not rely on the exit code of claude update; instead
capture versions and compare them to decide whether an update/reinstall is
needed: record current_version using the existing current_version command, run
claude update (but ignore its exit code), then fetch new_version with the same
claude --version call and compare current_version vs new_version to determine
success or whether to reinstall; optionally capture the stdout/stderr of the
claude update invocation to include in log_warn/log_info messages but never
branch solely on the exit status of claude update.
| # Install Claude Code using native installer (npm installation deprecated) | ||
| RUN curl -fsSL https://claude.ai/install.sh | bash \ | ||
| && echo 'export PATH="$HOME/.claude/local/bin:$PATH"' >> /home/vscode/.bashrc | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Claude Code native installer install.sh behavior root vs non-root HOME directory
💡 Result:
Claude Code’s native installer script (the curl …/install.sh | bash flow) installs into the invoking user’s home directory—it is **not a system-wide (/usr/local) installer.
-
The script “adds a symlink to the installation at
~/.local/bin/claude”. That~resolves from$HOMEof the user running the script. So:- Run normally (non-root): installs under your user’s home, e.g.
~/.local/bin/claude. [1] - Run with
sudo/ asroot: installs under root’s home, e.g./root/.local/bin/claude, and your normal user won’t see it in their~/.local/bin(unless you also adjust PATH). (This is the direct consequence of the installer targeting~/.local/bin.) [1]
- Run normally (non-root): installs under your user’s home, e.g.
-
The installer may print setup notes about adding
~/.local/binto PATH; issues have been reported around the exact PATH snippet it prints, reinforcing that it’s managing a per-user~/.local/bininstall rather than a global one. [2]
If you accidentally installed as root and want it under a specific user, rerun it as that user (or use something like sudo -u <user> -H bash -c 'curl -fsSL https://claude.ai/install.sh | bash' so HOME is the target user’s home).
Sources:
[1] Claude Code troubleshooting docs (native installer symlink location ~/.local/bin/claude, and local migration notes)
[2] GitHub issue reporting the installer’s PATH guidance for ~/.local/bin (shows installer’s per-user PATH expectations)
Install Claude Code as vscode to avoid HOME/path mismatch.
The installer runs as root, but the PATH is appended for /home/vscode. The native installer installs to ~/.local/bin (resolved from the invoking user's $HOME), so running it as root installs to /root/.local/bin. This binary is inaccessible to the vscode user. Additionally, the PATH variable in the original code ($HOME/.claude/local/bin) doesn't match the installer's actual output location ($HOME/.local/bin).
Proposed fix
# Install Claude Code using native installer (npm installation deprecated)
+USER vscode
RUN curl -fsSL https://claude.ai/install.sh | bash \
&& echo 'export PATH="$HOME/.local/bin:$PATH"' >> /home/vscode/.bashrc
+USER root🤖 Prompt for AI Agents
In @.devcontainer/Dockerfile around lines 68 - 71, The installer is run as root
so Claude is installed into /root/.local/bin and the PATH appended points to the
wrong directory; run the installer as the vscode user (or set HOME=/home/vscode
when invoking the installer) so the binary installs to /home/vscode/.local/bin,
then append the correct PATH entry ($HOME/.local/bin) to the vscode user's shell
rc (use /home/vscode/.bashrc) and ensure ownership of installed files is vscode;
look for the RUN curl...| bash invocation and the echo 'export
PATH=...'/home/vscode/.bashrc to update invocation user, HOME, PATH target, and
file ownership (chown) accordingly.
| # claudeコマンドの存在確認 | ||
| if ! command -v claude &> /dev/null; then | ||
| log_error "Claude CLI が見つかりません。" | ||
| log_info "インストール方法: curl -fsSL https://claude.ai/install.sh | bash" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # 現在のバージョンを取得 | ||
| current_version=$(jq -r ".dependencies[\"${PACKAGE}\"].version" "$GLOBAL_FILE") | ||
| current_version=$(claude --version 2>/dev/null | head -1 || echo "unknown") | ||
| log_info "現在のバージョン: ${current_version}" | ||
|
|
||
| # 最新バージョンを取得 | ||
| log_info "最新バージョンを確認中..." | ||
| latest_version=$(npm view "$PACKAGE" version 2>/dev/null) | ||
|
|
||
| if [[ -z "$latest_version" ]]; then | ||
| log_error "最新バージョンの取得に失敗しました" | ||
| exit 1 | ||
| fi | ||
|
|
||
| log_info "最新バージョン: ${latest_version}" | ||
|
|
||
| # バージョン比較 | ||
| if [[ "$current_version" == "$latest_version" ]]; then | ||
| log_success "Claude Code は既に最新バージョンです (${current_version})" | ||
| exit 0 | ||
| fi | ||
| # 更新を実行 | ||
| log_info "Claude Code を更新中..." | ||
|
|
||
| log_warn "バージョンが異なります: ${current_version} → ${latest_version}" | ||
|
|
||
| # 更新するかどうかを確認(CI環境では自動的に更新) | ||
| if [[ "${CI:-false}" != "true" ]] && [[ "${AUTO_UPDATE:-false}" != "true" ]]; then | ||
| read -p "更新しますか? (y/N): " -n 1 -r | ||
| echo | ||
| if [[ ! $REPLY =~ ^[Yy]$ ]]; then | ||
| log_info "更新をキャンセルしました" | ||
| exit 0 | ||
| if claude update; then | ||
| new_version=$(claude --version 2>/dev/null | head -1 || echo "unknown") | ||
| if [[ "$current_version" == "$new_version" ]]; then | ||
| log_success "Claude Code は既に最新バージョンです (${current_version})" | ||
| else | ||
| log_success "Claude Code を ${current_version} → ${new_version} に更新しました" | ||
| fi | ||
| else | ||
| log_warn "claude update に失敗しました。再インストールを試みます..." | ||
| if curl -fsSL https://claude.ai/install.sh | bash; then | ||
| new_version=$(claude --version 2>/dev/null | head -1 || echo "unknown") | ||
| log_success "Claude Code を再インストールしました (${new_version})" | ||
| else | ||
| log_error "Claude Code の更新に失敗しました" | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
claude update exit code behavior already up to date
💡 Result:
Anthropic’s docs confirm claude update exists (and is the recommended manual update path when auto-updates fail), but they do not document any “exit code contract” for the command—specifically, there’s no guarantee spelled out for what exit code you get when it reports “already up to date.” [1] [2]
Practical workaround (don’t rely on the exit code):
- Treat “already up to date” as a successful outcome in your wrapper script, and verify via version comparison.
Example (bash):
set -euo pipefail
before="$(claude --version | head -n1)"
out="$(claude update 2>&1 || true)"
after="$(claude --version | head -n1)"
if grep -qiE 'already up to date|no updates' <<<"$out"; then
exit 0
fi
# If it changed, also success
if [[ "$before" != "$after" ]]; then
exit 0
fi
# Otherwise treat as failure (unexpected state)
echo "$out" >&2
exit 1If you’re seeing “update available” prompts but Homebrew says everything is already up to date, that mismatch is a known/recurring packaging sync issue (brew lagging behind other release channels), so version-checking is especially important. [3]
Sources
- Claude Code docs (“Set up Claude Code” → manual update:
claude update). [1] - Claude Code troubleshooting (“Auto-updater issues” → “Update manually: Run
claude update”). [2] - GitHub issue: Claude indicates an update via brew, but
brew upgradereports already up to date. [3]
The script's reliance on claude update exit code is unreliable.
Anthropic does not document the exit code contract for claude update, so there is no guarantee what exit code is returned when already up to date. If claude update returns non-zero when already at the latest version (undocumented behavior), the script will incorrectly fall into the else block and trigger an unnecessary reinstallation. Compare versions before branching on the exit code, or capture the output and check for "already up to date" messages to avoid relying on the undocumented exit code behavior.
🤖 Prompt for AI Agents
In `@script/update-claude-code.sh` around lines 23 - 52, Do not rely on the exit
code of claude update; instead capture versions and compare them to decide
whether an update/reinstall is needed: record current_version using the existing
current_version command, run claude update (but ignore its exit code), then
fetch new_version with the same claude --version call and compare
current_version vs new_version to determine success or whether to reinstall;
optionally capture the stdout/stderr of the claude update invocation to include
in log_warn/log_info messages but never branch solely on the exit status of
claude update.
|
🎉 This PR is included in version 1.63.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Summary
https://claude.ai/install.shを使用してClaude Codeをインストールupdate-claude-code.shスクリプトをclaude updateコマンドベースに変更npm/global.jsonから@anthropic-ai/claude-codeを削除Test plan
claude updateコマンドが動作することを確認/update-claude-codeコマンドが正常に動作することを確認Related
Closes #422
🤖 Generated with Claude Code
Summary by CodeRabbit
Chores
Documentation