#!/bin/bash # Installs Takes and what it needs: the app, ffmpeg and Claude Code. One line in Terminal: # curl -fsSL https://gettakes.app/install | bash # Takes is not notarized (no paid Apple developer account). A browser download gets a quarantine # flag and macOS blocks the app; a download with curl gets no flag, so Takes opens at once. # Run it again to update. The export copies it to the root of the public repo; the gettakes.app # deploy serves this file from origin/main at /install (2026-10-05). set -euo pipefail say() { printf '\n\033[1m%s\033[0m\n' "$*"; } fail() { printf '\n%s\n' "$*" >&2; exit 1; } [ "$(uname -s)" = Darwin ] || fail "Takes runs on macOS only." [ "$(uname -m)" = arm64 ] || fail "Takes needs a Mac with Apple silicon (M1 or later)." v=$(sw_vers -productVersion) [ "${v%%.*}" -ge 15 ] || fail "Takes needs macOS 15 or later. This Mac has macOS $v." tmp=$(mktemp -d) trap 'hdiutil detach -quiet "$tmp/mnt" 2>/dev/null || true; rm -rf "$tmp"' EXIT bin="$HOME/.local/bin" mkdir -p "$bin" # 1. The app. say "Downloading Takes…" if [ -n "${TAKES_DMG:-}" ]; then cp "$TAKES_DMG" "$tmp/Takes.dmg" # a local build, for a test else curl -fL --progress-bar -o "$tmp/Takes.dmg" https://github.com/marvtub/takes-public/releases/latest/download/Takes.dmg; fi hdiutil attach -quiet -nobrowse -readonly -mountpoint "$tmp/mnt" "$tmp/Takes.dmg" # TAKES_APPS= installs there for a test and leaves a running Takes alone. apps=${TAKES_APPS:-/Applications} [ -w "$apps" ] || { apps="$HOME/Applications"; mkdir -p "$apps"; } if [ -z "${TAKES_APPS:-}" ] && pgrep -xq Takes; then say "Quitting Takes to replace it…" osascript -e 'quit app "Takes"' || true for _ in 1 2 3 4 5 6 7 8 9 10; do pgrep -xq Takes || break; sleep 1; done fi rm -rf "$apps/Takes.app" ditto "$tmp/mnt/Takes.app" "$apps/Takes.app" xattr -dr com.apple.quarantine "$apps/Takes.app" 2>/dev/null || true echo "Takes is in $apps." # 2. ffmpeg and ffprobe: static builds from ffmpeg.martin-riedl.de (linked from ffmpeg.org), # checked against their SHA-256. Skipped when ffmpeg is already there (Homebrew or other). if command -v ffmpeg >/dev/null || [ -x "$bin/ffmpeg" ] || [ -x /opt/homebrew/bin/ffmpeg ]; then echo "ffmpeg is already installed." else say "Downloading ffmpeg…" for tool in ffmpeg ffprobe; do url=$(curl -fsL -r 0-0 -o /dev/null -w '%{url_effective}' \ "https://ffmpeg.martin-riedl.de/redirect/latest/macos/arm64/release/$tool.zip") curl -fL --progress-bar -o "$tmp/$tool.zip" "$url" want=$(curl -fsSL "$url.sha256" | awk '{print $1}') got=$(shasum -a 256 "$tmp/$tool.zip" | awk '{print $1}') [ -n "$want" ] && [ "$want" = "$got" ] || fail "The $tool download does not match its checksum. Try again later." ditto -x -k "$tmp/$tool.zip" "$tmp/$tool" install -m 755 "$tmp/$tool/$tool" "$bin/$tool" done echo "ffmpeg is in $bin." fi # 3. Claude Code, with Anthropic's own installer, then sign in. claude=$(command -v claude || true) [ -n "$claude" ] || { [ -x "$bin/claude" ] && claude="$bin/claude"; } || true if [ -z "$claude" ]; then say "Installing Claude Code…" curl -fsSL https://claude.ai/install.sh | bash claude="$bin/claude" fi if "$claude" auth status 2>/dev/null | grep -q '"loggedIn": *true'; then echo "Claude Code is signed in." else say "Sign in to Claude Code. Your browser opens; come back here when you are done." "$claude" auth login