Last active
July 24, 2025 01:02
-
-
Save kigster/4d74df02358c86c0b9eecf1120fb6450 to your computer and use it in GitHub Desktop.
BASH script that downloads and installs Claude Mac App & the CLI client via npm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# shellcheck disable=SC2154,SC1091,SC1090 | |
# vim: ft=bash | |
# | |
# AUTHOR: | |
# © 2025 Konstantin Gredeskoul, All rights reserved. | |
# LICENSE: | |
# MIT | |
# USAGE: | |
# Download the script to a local file called "install-claude-app-cli" and then: | |
# bash install-claude-app-cli | |
declare dmg url mnt | |
export dmg=Claude.dmg | |
export url="https://storage.googleapis.com/osprey-downloads-c02f6a0d-347c-492b-a752-3e0651722e97/nest/$dmg" | |
export mnt="/Volumes/Claude" | |
# shellcheck disable=SC2064 | |
trap "rm -f ${dmg}" EXIT | |
if [[ ! -d "${HOME}/.bashmatic" ]] ; then | |
bash -c "$(curl -fsSL https://bashmatic.re1.re); bashmatic-install -q" | |
fi | |
[[ -f "${HOME}/.bashmatic/init" ]] && source "${HOME}/.bashmatic/init" >/dev/null | |
function app-size() { | |
local app_path="$1" | |
du -sh "$app_path" | awk '{printf "%s", $1}' | |
} | |
function wait-for-command() { | |
local command="$1" | |
local timeout="$2" | |
local interval="$3" | |
local elapsed=0.0 | |
while ! eval "$command" >/dev/null 2>&1; do | |
sleep "$interval" | |
elapsed=$(echo "$elapsed + $interval" | bc) | |
if [[ $(echo "$elapsed >= $timeout" | bc) -eq 1 ]]; then | |
error "Reached timeout ($timeout seconds) waiting for $command to complete..." | |
return 1 | |
fi | |
done | |
} | |
function install-deps() { | |
h2 "Checking for Brew, and will install it if not there." | |
command -v brew >/dev/null || /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" | |
run "brew bundle" | |
command -v volta && volta setup | |
for file in $(util.shell-init-files) ; do | |
[[ -f ${file} ]] && { | |
# shellcheck disable=SC1090 | |
source "${file}" | |
break | |
} | |
done | |
run "volta install node" | |
run "volta pin node" | |
run "volta install yarn" | |
run "volta pin yarn" | |
} | |
if [[ -d /Applications/Claude.app ]] && command -v claude >/dev/null; then | |
# shellcheck disable=SC2154 | |
h1 "Claude.app is already installed. To re-install please run:" \ | |
"${txtylw}rm -rf /Applications/Claude.app" | |
exit 0 | |
fi | |
install-deps | |
[[ -s $dmg ]] && { | |
warning "Re-downloading $dmg even though a local copy exists..." | |
run.set-next show-output-on | |
run "rm -fv Claude.dmg*" | |
} | |
run.set-all abort-on-error show-output-off | |
run.set-next show-output-on | |
if [[ -d $mnt ]]; then | |
warning "Claude mount point $mnt already exists, unmounting it..." | |
run "diskutil unmount $mnt" | |
fi | |
run "wget --show-progress $url" | |
if [[ -s $dmg ]] ; then | |
h5 "Opening $dmg... Please wait..." | |
open $dmg >/dev/null 2>&1 & | |
progress.bar.auto-run 1.5 | |
wait-for-command "test -d $mnt && test -d $mnt/Claude.app" 5.0 0.2 || { | |
error "Timeout waiting for $dmg to be mounted..." | |
exit 4 | |
} | |
else | |
error "Can't find $dmg after downloading it." "Source URL was [$url]" | |
exit 2 | |
fi | |
declare app_size current_size | |
if [[ -d "${mnt}" && -d "${mnt}/Claude.app" ]]; then | |
app_size=$(app-size "${mnt}/Claude.app") | |
info "Total size of Claude.app is: ${bldylw}${app_size}" | |
success "Claude DMG was successfully mounted in $mnt..." | |
else | |
error "Failed mounting $dmg, no directory $mnt were found." | |
exit 3 | |
fi | |
h2bg "Installing Claude.app to /Applications...." | |
run "cp -rp $mnt/Claude.app /Applications" | |
h4 "Unmounting $dmg..." | |
run "diskutil unmount $mnt" | |
[[ -d /Applications/Claude.app ]] && command -v claude >/dev/null && { | |
current_size=$(app-size /Applications/Claude.app) | |
success "Claude.app is installed in /Applications" | |
echo | |
h3bg "Total size of the installed /Applications/Claude.app is: ${bldylw}${current_size}" | |
echo | |
sleep 1 | |
h4bg "To start the Desktop Mac App, run ${txtgrn}${bakylw} open /Applications/Claude.app " \ | |
"To run the CLI session in the terminal, run ${txtgrn}${bakylw} claude --help " | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment