| 1 | #!/usr/bin/env bash |
| 2 | # Sets up an agent environment (a Claude Code cloud environment, Codex, a CI runner, a dev box) to work |
| 3 | # on __DIFFINERY_REPO__, as its Settings → Agent setup page on Diffinery shows: |
| 4 | # |
| 5 | # curl -fsSL __DIFFINERY_URL__/__DIFFINERY_REPO__/agent-setup.sh | bash |
| 6 | # |
| 7 | # 1. Installs the diffinery CLI and puts it on PATH (/usr/local/bin/diffinery when that's writable), |
| 8 | # skipping the download when the installed CLI is already the server's current build. |
| 9 | # 2. Runs `diffinery setup --repo __DIFFINERY_REPO__`: git and gh use the token in DIFFINERY_TOKEN (gh |
| 10 | # through GH_ENTERPRISE_TOKEN and GH_HOST), read from the environment each time and never written to |
| 11 | # disk; the repository is cloned unless it's there (DIFFINERY_NO_CLONE=1 skips that, and |
| 12 | # DIFFINERY_CLONE_DIR says where); then a self-test, one line per check, and a report to the page. |
| 13 | # |
| 14 | # Safe to run every time a session starts, fully non-interactive, and it never prints the token. |
| 15 | # This script holds no secret: Diffinery serves the same one to anyone, with the repository's name in it. |
| 16 | # It exits 1 when the CLI can't be installed or a check fails, so a broken setup isn't kept. Without |
| 17 | # DIFFINERY_TOKEN it sets up what it can, says what to add, and exits 0. |
| 18 | |
| 19 | if [ -z "${BASH_VERSION:-}" ]; then |
| 20 | echo "This script needs bash: curl -fsSL __DIFFINERY_URL__/__DIFFINERY_REPO__/agent-setup.sh | bash" >&2 |
| 21 | exit 1 |
| 22 | fi |
| 23 | set -uo pipefail |
| 24 | |
| 25 | server=__DIFFINERY_URL__ |
| 26 | repo=__DIFFINERY_REPO__ |
| 27 | cli_sha256=__DIFFINERY_CLI_SHA256__ |
| 28 | root=${DIFFINERY_INSTALL:-$HOME/.diffinery} |
| 29 | # Where the diffinery command is linked from, when it's writable (running as root). |
| 30 | link_dir=${DIFFINERY_LINK_DIR:-/usr/local/bin} |
| 31 | host=${server#*://} |
| 32 | page="$server/$repo/settings/agent-setup" |
| 33 | |
| 34 | if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then |
| 35 | green=$'\033[32m' red=$'\033[31m' bold=$'\033[1m' reset=$'\033[0m' |
| 36 | else |
| 37 | green='' red='' bold='' reset='' |
| 38 | fi |
| 39 | say() { printf '%s\n' "$*"; } |
| 40 | fail() { |
| 41 | say "${red}✗${reset} $*" |
| 42 | exit 1 |
| 43 | } |
| 44 | |
| 45 | say "${bold}Diffinery agent setup for $repo${reset}" |
| 46 | command -v curl >/dev/null || fail "curl is required" |
| 47 | command -v git >/dev/null || fail "git is required: install it in the setup script first (apt-get install -y git)" |
| 48 | original_path=$PATH |
| 49 | |
| 50 | sha256() { if command -v sha256sum >/dev/null; then sha256sum "$1"; else shasum -a 256 "$1"; fi | cut -d' ' -f1; } |
| 51 | |
| 52 | # 1. The CLI. |
| 53 | installed=$root/lib/diffinery.mjs |
| 54 | if [ -f "$installed" ] && [ "$(sha256 "$installed")" = "$cli_sha256" ] && "$root/bin/diffinery" --version >/dev/null 2>&1; then |
| 55 | say "${green}✓${reset} diffinery CLI: already the current build" |
| 56 | else |
| 57 | # With /usr/local/bin to link from (root in a container or VM), the CLI leaves startup files alone. |
| 58 | no_rc=${DIFFINERY_NO_MODIFY_PATH:-} |
| 59 | if [ -d "$link_dir" ] && [ -w "$link_dir" ]; then no_rc=1; fi |
| 60 | installer=$(curl -fsSL "$server/install") || fail "couldn't download $server/install: allow $host in the environment's network settings (Custom with $host, or Full)" |
| 61 | printf '%s\n' "$installer" | DIFFINERY_URL=$server DIFFINERY_INSTALL=$root DIFFINERY_NO_MODIFY_PATH=$no_rc bash || fail "the diffinery CLI didn't install (see above)" |
| 62 | fi |
| 63 | if [ -d "$link_dir" ] && [ -w "$link_dir" ]; then |
| 64 | ln -sfn "$root/bin/diffinery" "$link_dir/diffinery" || fail "couldn't link $link_dir/diffinery" |
| 65 | fi |
| 66 | |
| 67 | # 2. git, gh, the clone and the self-test. The original PATH is what the PATH check looks at. |
| 68 | export PATH="$root/bin:$PATH" |
| 69 | if [ -z "${DIFFINERY_TOKEN:-}" ]; then |
| 70 | # Without the token git still gets its credential helper, which reads DIFFINERY_TOKEN once it's set. |
| 71 | DIFFINERY_URL=$server diffinery auth setup-git >/dev/null 2>&1 || true |
| 72 | say "${red}✗${reset} DIFFINERY_TOKEN is not set: generate a token on $page and add the Environment variables shown there." |
| 73 | say " git and the CLI are set up and will use the token once it's in the environment; run this again then to check." |
| 74 | exit 0 |
| 75 | fi |
| 76 | if [ -n "${DIFFINERY_REPO:-}" ] && [ "$DIFFINERY_REPO" != "$repo" ]; then |
| 77 | say "note: DIFFINERY_REPO is $DIFFINERY_REPO, but this script sets up $repo" |
| 78 | fi |
| 79 | DIFFINERY_SETUP_PATH=$original_path diffinery setup --repo "$repo" --url "$server" |