Repository navigation
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·94 lines (77 loc) · 3.39 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·94 lines (77 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/usr/bin/env bash
#
# Installs the Claude Code CLI from Anthropic's official APT repository and
# prepares the configuration directory the feature points CLAUDE_CONFIG_DIR at.
#
# Expected environment variables, from this feature's own options:
#
# VERSION APT package version to install, or "latest".
# KEEPAPTSOURCE "true" to leave the APT source and signing key in the
# image.
#
# and from the Dev Container specification, injected by the CLI:
#
# _REMOTE_USER The account the container is attached as, and therefore
# the one Claude Code reads its configuration as.
# _REMOTE_USER_HOME Home directory of _REMOTE_USER.
set -euo pipefail
VERSION="${VERSION:-latest}"
KEEPAPTSOURCE="${KEEPAPTSOURCE:-true}"
FEATURE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
APT_KEYRING="/usr/share/keyrings/claude-code.asc"
APT_SOURCE="/etc/apt/sources.list.d/claude-code.list"
APT_REPOSITORY="https://downloads.claude.ai/claude-code/apt/stable stable main"
if [ "$(id -u)" -ne 0 ]; then
echo "(!) This feature must be installed as root." >&2
exit 1
fi
if ! command -v apt-get >/dev/null 2>&1; then
echo "(!) This feature requires a Debian/Ubuntu based image (apt-get not found)." >&2
exit 1
fi
export DEBIAN_FRONTEND=noninteractive
# Ensure the system has a CA bundle for HTTPS access to the APT repository.
if [ ! -e /etc/ssl/certs/ca-certificates.crt ]; then
apt-get update -y
apt-get install -y --no-install-recommends ca-certificates
fi
# Add the official Claude Code apt repository.
install -D -m 0644 "${FEATURE_DIR}/claude-code.asc" "${APT_KEYRING}"
echo "deb [signed-by=${APT_KEYRING}] ${APT_REPOSITORY}" > "${APT_SOURCE}"
apt-get update -y
# Install the requested version of the package, or the latest if none was specified.
if [ "${VERSION}" = "latest" ] || [ -z "${VERSION}" ]; then
package="claude-code"
else
package="claude-code=${VERSION}"
fi
apt-get install -y --no-install-recommends "${package}"
if [ "${KEEPAPTSOURCE}" != "true" ]; then
rm -f "${APT_SOURCE}" "${APT_KEYRING}"
fi
rm -rf /var/lib/apt/lists/*
username="${_REMOTE_USER:-root}"
CONFIG_DIR="/var/lib/claude-code"
CONFIG_GROUP="claude-code"
if ! passwd_entry="$(getent passwd "${username}")"; then
echo "(!) Remote user '${username}' was not found in the password database." >&2
exit 1
fi
# Create a dedicated group for the configuration directory, and add the remote user to it.
# This allows the remote user to access the configuration directory even if the remote user's UID is renumbered by `updateRemoteUserUID` option.
mkdir -p "${CONFIG_DIR}"
if ! getent group "${CONFIG_GROUP}" >/dev/null; then
groupadd --system "${CONFIG_GROUP}"
fi
usermod -aG "${CONFIG_GROUP}" "${username}"
# Transfer any existing configuration from the remote user's home directory to the mounted volume if it exists.
user_home="${_REMOTE_USER_HOME:-$(printf '%s' "${passwd_entry}" | cut -d: -f6)}"
if [ -n "${user_home}" ] && [ -d "${user_home}/.claude" ] && [ -z "$(ls -A "${CONFIG_DIR}")" ]; then
cp -a "${user_home}/.claude/." "${CONFIG_DIR}/"
fi
# Set the ownership and permissions of the configuration directory.
# The setgid bit keeps entries created later in the shared group.
chown -R "${username}:${CONFIG_GROUP}" "${CONFIG_DIR}"
chmod -R g+rwX "${CONFIG_DIR}"
chmod 2775 "${CONFIG_DIR}"
echo "Installed $(claude --version 2>/dev/null || echo 'claude-code')."