Files
msd-core/scripts/bootstrap.sh
Jakub Zych b7e36d5d38
Some checks failed
Tests / PR mergeability (push) Successful in 18s
Tests / Base branch health (push) Successful in 11s
Tests / Detect test scope (push) Successful in 18s
Tests / lint-tests (push) Failing after 2m5s
Tests / plugin-validate (push) Successful in 55s
Tests / test (ubuntu-latest, 24, shard 1/3) (push) Failing after 20s
Tests / test (ubuntu-latest, 24, shard 2/3) (push) Failing after 19s
Tests / test (ubuntu-latest, 24, shard 3/3) (push) Failing after 19s
Tests / test (ubuntu-latest, 24) (push) Failing after 19s
Tests / test (inert CI) (push) Has been skipped
Tests / QA loop walk (smell ratchet) (push) Failing after 18s
Tests / Coverage gate (merged shards) (push) Has been skipped
Tests / Publish emitted-baseline artifact (push) Has been skipped
Duplicate auto-close sweep / sweep (push) Successful in 17s
CI timeout budget report / report (push) Failing after 14s
Close Draft PRs (sweep) / Sweep open draft PRs (push) Successful in 8s
Tests / conformance test (macos-latest, 24) (push) Has been cancelled
Tests / conformance test (windows-latest, 24, shard 1/3) (push) Has been cancelled
Tests / conformance test (windows-latest, 24, shard 2/3) (push) Has been cancelled
Tests / conformance test (windows-latest, 24, shard 3/3) (push) Has been cancelled
Tests / Required tests (push) Has been cancelled
Dismiss Unauthorized PR Approvals / dismiss-unauthorized-approval (push) Successful in 10s
feat: add curl-able bootstrap installer for msd.golem15.com
2026-10-07 23:51:21 +02:00

130 lines
4.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# MSD Core bootstrap — one-line install from the public repo.
#
# curl -fsSL https://msd.golem15.com | bash
# curl -fsSL https://msd.golem15.com | bash -s -- --codex --profile standard
#
# Clones (or updates) the MSD checkout into $MSD_HOME, builds it, and runs
# bin/install.js globally for the chosen runtime(s). Installs Claude Code
# first when it is the target runtime and `claude` is not on PATH.
#
# Everything lives inside main() so a truncated download never runs half a script.
main() {
set -euo pipefail
local repo="${MSD_REPO:-https://git.golem15.com/golem15/msd-core.git}"
local ref="${MSD_REF:-next}"
local home_dir="${MSD_HOME:-$HOME/.local/share/msd-core}"
local profile="${MSD_PROFILE:-full}"
local install_claude=true
local runtimes=()
while (($#)); do
case "$1" in
--claude|--codex|--opencode|--cursor|--zcode|--antigravity) runtimes+=("$1") ;;
--profile)
shift
(($#)) || { echo "ERROR: --profile requires a value." >&2; exit 2; }
profile="$1"
;;
--profile=*) profile="${1#--profile=}" ;;
--ref)
shift
(($#)) || { echo "ERROR: --ref requires a value." >&2; exit 2; }
ref="$1"
;;
--skip-claude-install) install_claude=false ;;
-h|--help)
cat <<'EOF'
MSD Core bootstrap
Usage: curl -fsSL https://msd.golem15.com | bash -s -- [options]
Options:
--claude, --codex, --opencode, --cursor, --zcode, --antigravity
Runtime(s) to install for (default: --claude)
--profile NAME Skill profile: core, standard or full (default: full)
--ref REF Branch or tag to install (default: next)
--skip-claude-install Do not install Claude Code when it is missing
Environment: MSD_HOME (checkout dir, default ~/.local/share/msd-core),
MSD_REPO, MSD_REF, MSD_PROFILE
EOF
exit 0
;;
*) echo "ERROR: unknown argument: $1 (try --help)" >&2; exit 2 ;;
esac
shift
done
((${#runtimes[@]})) || runtimes=(--claude)
case "$profile" in
core|standard|full) ;;
*) echo "ERROR: profile must be core, standard or full; got: $profile" >&2; exit 2 ;;
esac
say() { printf '\033[36m==>\033[0m %s\n' "$*"; }
command -v git >/dev/null 2>&1 || { echo "ERROR: git is required." >&2; exit 1; }
local node_major
node_major=$(node -p 'process.versions.node.split(".")[0]' 2>/dev/null || echo 0)
if ((node_major < 24)); then
cat >&2 <<EOF
ERROR: MSD needs Node.js 24 or newer (found: $(node --version 2>/dev/null || echo none)).
Install it, e.g. with nvm:
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
nvm install 24
then rerun this command.
EOF
exit 1
fi
if ! command -v jq >/dev/null 2>&1; then
printf '\033[33mWARNING:\033[0m jq is not installed; MSD workflows rely on it.\n' >&2
echo ' Install it (apt install jq / brew install jq) after this finishes.' >&2
fi
if [[ " ${runtimes[*]} " == *" --claude "* ]] && $install_claude \
&& ! command -v claude >/dev/null 2>&1 && [[ ! -x "$HOME/.local/bin/claude" ]]; then
say "Installing Claude Code"
curl -fsSL https://claude.ai/install.sh | bash
fi
if [[ -d "$home_dir/.git" ]]; then
say "Updating $home_dir ($ref)"
if [[ -n "$(git -C "$home_dir" status --porcelain --untracked-files=no)" ]]; then
echo "ERROR: $home_dir has local changes; commit or discard them first." >&2
exit 1
fi
git -C "$home_dir" fetch --quiet origin "$ref"
git -C "$home_dir" checkout --quiet --detach FETCH_HEAD
else
say "Cloning MSD into $home_dir ($ref)"
mkdir -p "$(dirname "$home_dir")"
git clone --quiet --branch "$ref" "$repo" "$home_dir"
fi
cd "$home_dir"
say "Installing dependencies and building"
npm ci --no-audit --no-fund --loglevel=error
npm run --silent build:hooks
local rt
for rt in "${runtimes[@]}"; do
say "Installing MSD for ${rt#--} (profile: $profile)"
node bin/install.js "$rt" --global "--profile=$profile"
done
cat <<EOF
MSD installed from $home_dir ($(git rev-parse --short HEAD)).
Update any time by rerunning: curl -fsSL https://msd.golem15.com | bash
EOF
if [[ " ${runtimes[*]} " == *" --claude "* ]] && ! command -v claude >/dev/null 2>&1; then
echo 'Add Claude Code to your PATH: export PATH="$HOME/.local/bin:$PATH"'
fi
}
main "$@"