forked from aaddrick/claude-desktop-debian
-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathinstall-claude-desktop.sh
More file actions
executable file
·375 lines (333 loc) · 10.1 KB
/
install-claude-desktop.sh
File metadata and controls
executable file
·375 lines (333 loc) · 10.1 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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
#!/bin/bash
set -e
# Update this URL when a new version of Claude Desktop is released
CLAUDE_DOWNLOAD_URL="https://storage.googleapis.com/osprey-downloads-c02f6a0d-347c-492b-a752-3e0651722e97/nest-win-x64/Claude-Setup-x64.exe"
# Check for Debian-based system
if [ ! -f "/etc/debian_version" ]; then
echo "❌ This script requires a Debian-based Linux distribution"
exit 1
fi
# Print system information
echo "System Information:"
echo "Distribution: $(grep "PRETTY_NAME" /etc/os-release | cut -d'"' -f2)"
echo "Debian version: $(cat /etc/debian_version)"
if [[ -n "$WSL_DISTRO_NAME" ]]; then
echo "Running in WSL!"
# remove Windows paths from PATH
PATH=$(echo "$PATH" | sed 's|:/mnt/c[^:]*||g' | sed 's|^/mnt/c[^:]*:||')
export PATH
fi
# Function to check if a command exists
check_command() {
if ! command -v "$1" &> /dev/null; then
echo "❌ $1 not found"
return 1
else
echo "✓ $1 found"
return 0
fi
}
# Check and install dependencies
DEPS_TO_INSTALL=""
echo "Checking dependencies..."
dpkg -s "libnss3" >/dev/null 2>&1 || DEPS_TO_INSTALL="$DEPS_TO_INSTALL libnss3"
# Check availability of libasound2t64 and set package accordingly
if apt-cache show libasound2t64 >/dev/null 2>&1; then
PKG="libasound2t64"
else
echo "libasound2t64 not found. Falling back to libasound2..."
PKG="libasound2"
fi
# Add package if not already installed
dpkg -s "$PKG" >/dev/null 2>&1 || DEPS_TO_INSTALL="$DEPS_TO_INSTALL $PKG"
# Check system package dependencies
for cmd in p7zip wget wrestool icotool convert npx dpkg-deb; do
if ! check_command "$cmd"; then
case "$cmd" in
"p7zip")
DEPS_TO_INSTALL="$DEPS_TO_INSTALL p7zip-full"
;;
"wget")
DEPS_TO_INSTALL="$DEPS_TO_INSTALL wget"
;;
"wrestool"|"icotool")
DEPS_TO_INSTALL="$DEPS_TO_INSTALL icoutils"
;;
"convert")
DEPS_TO_INSTALL="$DEPS_TO_INSTALL imagemagick"
;;
"npx")
DEPS_TO_INSTALL="$DEPS_TO_INSTALL nodejs npm"
;;
"dpkg-deb")
DEPS_TO_INSTALL="$DEPS_TO_INSTALL dpkg-dev"
;;
"bwrap")
DEPS_TO_INSTALL="$DEPS_TO_INSTALL bubblewrap"
;;
esac
fi
done
# Install system dependencies if any
if [ -n "$DEPS_TO_INSTALL" ]; then
echo "Installing system dependencies: $DEPS_TO_INSTALL"
sudo apt update
# shellcheck disable=SC2086
sudo apt install -y $DEPS_TO_INSTALL
echo "System dependencies installed successfully"
fi
# Install electron globally via npm if not present
if ! check_command "electron"; then
echo "Installing electron via npm..."
sudo npm install -g electron
if ! check_command "electron"; then
echo "Failed to install electron. Please install it manually:"
echo "sudo npm install -g electron"
exit 1
fi
echo "Electron installed successfully"
fi
PACKAGE_NAME="claude-desktop"
ARCHITECTURE="amd64"
MAINTAINER="Claude Desktop Linux Maintainers"
DESCRIPTION="Claude Desktop for Linux"
# Create working directories
WORK_DIR="$(pwd)/build"
DEB_ROOT="$WORK_DIR/deb-package"
INSTALL_DIR="$DEB_ROOT/usr"
# Clean previous build
rm -rf "$WORK_DIR"
mkdir -p "$WORK_DIR"
mkdir -p "$DEB_ROOT/DEBIAN"
mkdir -p "$INSTALL_DIR/lib/$PACKAGE_NAME"
mkdir -p "$INSTALL_DIR/share/applications"
mkdir -p "$INSTALL_DIR/share/icons"
mkdir -p "$INSTALL_DIR/bin"
# Install asar if needed
if ! command -v asar &> /dev/null; then
echo "Installing asar package globally..."
sudo npm install -g asar
fi
# Download Claude Windows installer
echo "📥 Downloading Claude Desktop installer..."
CLAUDE_EXE="$WORK_DIR/Claude-Setup-x64.exe"
if ! wget -O "$CLAUDE_EXE" "$CLAUDE_DOWNLOAD_URL"; then
echo "❌ Failed to download Claude Desktop installer"
exit 1
fi
echo "✓ Download complete"
# Downloading sandbox script if it doesn't exist
echo "📥 Checking for sandbox script..."
mkdir -p "$HOME/sandboxes/"
SANDBOX_SCRIPT="$HOME/sandboxes/claude_sandbox.sh"
if [ ! -f "$SANDBOX_SCRIPT" ]; then
echo "Downloading sandbox script..."
if ! wget -O "$SANDBOX_SCRIPT" "https://raw.githubusercontent.com/emsi/claude-desktop/refs/heads/main/claude_sandbox.sh"; then
echo "❌ Failed to download sandbox script"
exit 1
fi
echo "✓ Download complete"
fi
chmod +x "$SANDBOX_SCRIPT"
# Extract resources
echo "📦 Extracting resources..."
cd "$WORK_DIR"
if ! 7z x -y "$CLAUDE_EXE"; then
echo "❌ Failed to extract installer"
exit 1
fi
# Extract version from nupkg filename
NUPKG_FILE=$(ls AnthropicClaude-*-full.nupkg 2>/dev/null | head -1)
if [ -n "$NUPKG_FILE" ]; then
VERSION=$(echo "$NUPKG_FILE" | sed -n 's/AnthropicClaude-\([0-9]\+\.[0-9]\+\.[0-9]\+\)-full\.nupkg/\1/p')
echo "✓ Version extracted from nupkg filename: $VERSION"
else
echo "❌ No nupkg file found"
exit 1
fi
if ! 7z x -y "$NUPKG_FILE"; then
echo "❌ Failed to extract nupkg"
exit 1
fi
echo "✓ Resources extracted"
# Extract and convert icons
echo "🎨 Processing icons..."
if ! wrestool -x -t 14 "lib/net45/claude.exe" -o claude.ico; then
echo "❌ Failed to extract icons from exe"
exit 1
fi
if ! icotool -x claude.ico; then
echo "❌ Failed to convert icons"
exit 1
fi
echo "✓ Icons processed"
# Map icon sizes to their corresponding extracted files
declare -A icon_files=(
["16"]="claude_13_16x16x32.png"
["24"]="claude_11_24x24x32.png"
["32"]="claude_10_32x32x32.png"
["48"]="claude_8_48x48x32.png"
["64"]="claude_7_64x64x32.png"
["256"]="claude_6_256x256x32.png"
)
# Install icons
for size in 16 24 32 48 64 256; do
icon_dir="$INSTALL_DIR/share/icons/hicolor/${size}x${size}/apps"
mkdir -p "$icon_dir"
if [ -f "${icon_files[$size]}" ]; then
echo "Installing ${size}x${size} icon..."
install -Dm 644 "${icon_files[$size]}" "$icon_dir/claude-desktop.png"
else
echo "Warning: Missing ${size}x${size} icon"
fi
done
# Process app.asar
mkdir -p electron-app
cp "lib/net45/resources/app.asar" electron-app/
cp -r "lib/net45/resources/app.asar.unpacked" electron-app/
cd electron-app
npx asar extract app.asar app.asar.contents
# Replace native module with stub implementation
echo "Creating stub native module..."
cat > app.asar.contents/node_modules/claude-native/index.js << EOF
// Stub implementation of claude-native using KeyboardKey enum values
const KeyboardKey = {
Backspace: 43,
Tab: 280,
Enter: 261,
Shift: 272,
Control: 61,
Alt: 40,
CapsLock: 56,
Escape: 85,
Space: 276,
PageUp: 251,
PageDown: 250,
End: 83,
Home: 154,
LeftArrow: 175,
UpArrow: 282,
RightArrow: 262,
DownArrow: 81,
Delete: 79,
Meta: 187
};
Object.freeze(KeyboardKey);
module.exports = {
getWindowsVersion: () => "10.0.0",
setWindowEffect: () => {},
removeWindowEffect: () => {},
getIsMaximized: () => false,
flashFrame: () => {},
clearFlashFrame: () => {},
showNotification: () => {},
setProgressBar: () => {},
clearProgressBar: () => {},
setOverlayIcon: () => {},
clearOverlayIcon: () => {},
KeyboardKey
};
EOF
# Copy Tray icons
mkdir -p app.asar.contents/resources
mkdir -p app.asar.contents/resources/i18n
cp ../lib/net45/resources/Tray* app.asar.contents/resources/
cp ../lib/net45/resources/*-*.json app.asar.contents/resources/i18n/
echo "Downloading Main Window Fix Assets"
cd app.asar.contents
wget -O- https://github.com/emsi/claude-desktop/raw/refs/heads/main/assets/main_window.tgz | tar -zxvf -
cd ..
# Repackage app.asar
npx asar pack app.asar.contents app.asar
# Create native module with keyboard constants
mkdir -p "$INSTALL_DIR/lib/$PACKAGE_NAME/app.asar.unpacked/node_modules/claude-native"
cat > "$INSTALL_DIR/lib/$PACKAGE_NAME/app.asar.unpacked/node_modules/claude-native/index.js" << EOF
// Stub implementation of claude-native using KeyboardKey enum values
const KeyboardKey = {
Backspace: 43,
Tab: 280,
Enter: 261,
Shift: 272,
Control: 61,
Alt: 40,
CapsLock: 56,
Escape: 85,
Space: 276,
PageUp: 251,
PageDown: 250,
End: 83,
Home: 154,
LeftArrow: 175,
UpArrow: 282,
RightArrow: 262,
DownArrow: 81,
Delete: 79,
Meta: 187
};
Object.freeze(KeyboardKey);
module.exports = {
getWindowsVersion: () => "10.0.0",
setWindowEffect: () => {},
removeWindowEffect: () => {},
getIsMaximized: () => false,
flashFrame: () => {},
clearFlashFrame: () => {},
showNotification: () => {},
setProgressBar: () => {},
clearProgressBar: () => {},
setOverlayIcon: () => {},
clearOverlayIcon: () => {},
KeyboardKey
};
EOF
# Copy app files
cp app.asar "$INSTALL_DIR/lib/$PACKAGE_NAME/"
cp -r app.asar.unpacked "$INSTALL_DIR/lib/$PACKAGE_NAME/"
# Create desktop entry
cat > "$INSTALL_DIR/share/applications/claude-desktop.desktop" << EOF
[Desktop Entry]
Name=Claude
Exec=claude-desktop %u
Icon=claude-desktop
Type=Application
Terminal=false
Categories=Office;Utility;
MimeType=x-scheme-handler/claude;
StartupWMClass=Claude
EOF
# Create launcher script
cat > "$INSTALL_DIR/bin/claude-desktop" << EOF
#!/bin/bash
electron /usr/lib/claude-desktop/app.asar "\$@"
EOF
chmod +x "$INSTALL_DIR/bin/claude-desktop"
# Create control file
cat > "$DEB_ROOT/DEBIAN/control" << EOF
Package: claude-desktop
Version: $VERSION
Architecture: $ARCHITECTURE
Maintainer: $MAINTAINER
Depends: nodejs, npm, p7zip-full
Description: $DESCRIPTION
Claude is an AI assistant from Anthropic.
This package provides the desktop interface for Claude.
.
Supported on Debian-based Linux distributions (Debian, Ubuntu, Linux Mint, MX Linux, etc.)
Requires: nodejs (>= 12.0.0), npm
EOF
# Build .deb package
echo "📦 Building .deb package..."
DEB_FILE="$(pwd)/claude-desktop_${VERSION}_${ARCHITECTURE}.deb"
if ! dpkg-deb --build "$DEB_ROOT" "$DEB_FILE"; then
echo "❌ Failed to build .deb package"
exit 1
fi
if [ -f "$DEB_FILE" ]; then
echo "✓ Package built successfully at: $DEB_FILE"
echo "🎉 Installing the package..."
sudo dpkg -i "$DEB_FILE"
echo "✅ Claude Desktop has been installed successfully!"
else
echo "❌ Package file not found at expected location: $DEB_FILE"
exit 1
fi