[BUG] claude install creates broken symlink: %h not expanded in path
Status Open
Reported on v2.1.220
Maintainer reply None cached
Workaround ✓ Mentioned in thread ↓
Activity 9 comments · opened Aug 3, 2026
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Broken symlink created by claude install
The claude install command (run by the official installer script) creates a broken symlink at ~/.local/bin/claude, pointing to:
%h/.local/share/claude/versions/<version>
instead of expanding %h to the actual home directory path.
The shell installer script (curl -fsSL https://claude.ai/install.sh) is correct — it downloads the binary and runs:
"$binary_path" install
The broken symlink is created by the binary's internal install subcommand.
Environment
- OS: Fedora 44
- Shell: bash
- Claude Code: 2.1.220
Workaround
ln -sf ~/.local/share/claude/versions/2.1.220 ~/.local/bin/claude
What Should Happen?
Expected behavior
claude -> /home/user/.local/share/claude/versions/2.1.220
Error Messages/Logs
## Actual behavior
file ~/.local/bin/claude
Output:
/home/user/.local/bin/claude: broken symbolic link to %h/.local/share/claude/versions/2.1.220
Steps to Reproduce
Steps to reproduce
curl -fsSL https://claude.ai/install.sh | bash
ls -la ~/.local/bin/claude
# claude -> %h/.local/share/claude/versions/2.1.220 (broken)
Claude Model
None
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.220
Platform
Anthropic API
Operating System
Other Linux
Terminal/Shell
Other
Additional Information
_No response_
Showing cached comments. Read the full discussion on GitHub ↗
2 Comments
#!/usr/bin/env bash
set -euo pipefail
INSTALL_ROOT="${HOME}/.local/share/claude/versions"
BIN_DIR="${HOME}/.local/bin"
LINK_PATH="${BIN_DIR}/claude"
info() {
printf '[info] %s
' "$1"
}
fail() {
printf '[fail] %s
' "$1" >&2
exit 1
}
[ -d "$INSTALL_ROOT" ] || fail "Install root not found: $INSTALL_ROOT"
mkdir -p "$BIN_DIR"
LATEST_VERSION="$({
find "$INSTALL_ROOT" -mindepth 1 -maxdepth 1 ( -type d -o -type f -o -type l ) -printf '%f
' 2>/dev/null || true
} | sort -V | tail -n 1)"
[ -n "$LATEST_VERSION" ] || fail "No installed Claude versions found in: $INSTALL_ROOT"
TARGET_PATH="${INSTALL_ROOT}/${LATEST_VERSION}"
[ -e "$TARGET_PATH" ] || [ -L "$TARGET_PATH" ] || fail "Target does not exist: $TARGET_PATH"
rm -f "$LINK_PATH"
ln -s "$TARGET_PATH" "$LINK_PATH"
info "Created symlink: $LINK_PATH -> $TARGET_PATH"
The issue is intermittent — the symlink doesn't break every time Claude is launched. Here's what I observed:
Reproduction hint: It might be related to the auto-update check running in a context where $HOME or the path resolution doesn't work as expected. The binary's internal install subcommand is what creates the broken symlink with literal %h instead of the resolved home path.
Temporary workaround:
ln -sf ~/.local/share/claude/versions/$(ls ~/.local/share/claude/versions/ | sort -V | tail -1) ~/.local/bin/claude