#!/bin/sh # Public connection bridge only; no Skill or paid resource is embedded. set -eu version=0.9.2 expected=f10fc344a349b57ce9b9da5282f8fa5dad13ef960a8578d348dd33392abd726b agent=${1:-claude-code} mode=${2:-connect} case "$agent" in claude-code|codex) ;; *) echo 'Choose claude-code or codex.' >&2; exit 1;; esac case "$mode" in connect|--doctor) ;; *) echo 'Usage: install [claude-code|codex] [--doctor]' >&2; exit 1;; esac command -v node >/dev/null 2>&1 || { echo 'Install Node.js 22+ first.' >&2; exit 1; } command -v curl >/dev/null 2>&1 || { echo 'Install curl first.' >&2; exit 1; } if command -v shasum >/dev/null 2>&1; then checksum() { shasum -a 256 "$1" | awk '{print $1}'; } elif command -v sha256sum >/dev/null 2>&1; then checksum() { sha256sum "$1" | awk '{print $1}'; } else echo 'Install shasum or sha256sum for SHA256 verification.' >&2; exit 1 fi stage=$(mktemp -d) trap 'rm -rf "$stage"' EXIT HUP INT TERM curl --fail --silent --show-error --proto '=https' --max-time 30 'https://claudemotion.tv/api/toolkit/installer/?version=0.9.2' -o "$stage/cli.mjs" [ "$(checksum "$stage/cli.mjs")" = "$expected" ] || { echo 'CLI checksum mismatch; nothing executed.' >&2; exit 1; } [ "$(node "$stage/cli.mjs" version)" = "$version" ] || { echo 'CLI version mismatch; nothing connected.' >&2; exit 1; } echo "Verified claudemotion $version (SHA256: $expected)" if [ "$mode" = '--doctor' ]; then node "$stage/cli.mjs" doctor --agent "$agent" exit $? fi # Avoid writing through symlinks or replacing unrelated files. [ ! -L .claudemotion ] || { echo 'Refusing a symlinked .claudemotion directory.' >&2; exit 1; } mkdir -p .claudemotion cli=".claudemotion/cli-$version.mjs" [ ! -L "$cli" ] || { echo 'Refusing a symlinked CLI.' >&2; exit 1; } if [ -e "$cli" ]; then [ "$(checksum "$cli")" = "$expected" ] || { echo 'Existing CLI differs; preserved. Choose another project.' >&2; exit 1; } else cp "$stage/cli.mjs" "$cli" chmod 600 "$cli" fi node "$cli" connect --agent "$agent" --project .