#!/usr/bin/env bash # # neuron-dev-setup / install.sh # ───────────────────────────────────────────────────────────────────────────── # One-command onboarding for the Neuron CORE dev stack on a fresh Mac. # # Stands up, as native launchd services, the four processes a developer needs to # have an identical "Neuron brain + agent" to build against: # # soul (:7770) ──► engram (:8742) the mind + its memory substrate # ▲ ▲ # │ │ # mcp-wrapper (:17779) ──► soul MCP surface over the soul API # ▲ # │ # mcp-proxy (:7779) ◄── Claude Code stable MCP front door # # It also seeds a fresh engram with Neuron's identity (the genesis seed) and lays # down the Claude Code config (neuron agent + core hooks + local MCP registration) # so a new dev's `claude` talks to *their own* local Neuron. # # DESIGN RULES # * Idempotent: safe to re-run. Existing state is detected and reused. # * Templated: every path/port/user is derived from $HOME and config.env. # Nothing is hardcoded to another developer's machine. # * Secret-free: the Anthropic key is prompted for and stored in the macOS # Keychain. No key is ever written to a plist, this repo, or a logfile. # # USAGE # ./install.sh # full install # ./install.sh --dry-run # print what would happen, touch nothing # ./install.sh --skip-build # assume binaries already built (see --use-local) # ./install.sh --skip-services # lay down files but don't load LaunchAgents # ./install.sh --help # ───────────────────────────────────────────────────────────────────────────── set -euo pipefail # ── Locate ourselves ───────────────────────────────────────────────────────── SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TEMPLATES="${SCRIPT_DIR}/templates" # ── Flags ──────────────────────────────────────────────────────────────────── DRY_RUN=0; SKIP_BUILD=0; SKIP_SERVICES=0; USE_LOCAL_BINARIES=0 for arg in "$@"; do case "$arg" in --dry-run) DRY_RUN=1 ;; --skip-build) SKIP_BUILD=1 ;; --skip-services) SKIP_SERVICES=1 ;; --use-local) USE_LOCAL_BINARIES=1 ;; --help|-h) sed -n '2,40p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//' exit 0 ;; *) echo "unknown flag: $arg" >&2; exit 2 ;; esac done # ── Pretty logging ─────────────────────────────────────────────────────────── c_blue=$'\033[1;34m'; c_grn=$'\033[1;32m'; c_yel=$'\033[1;33m'; c_red=$'\033[1;31m'; c_off=$'\033[0m' step() { echo "${c_blue}▶${c_off} $*"; } ok() { echo "${c_grn}✓${c_off} $*"; } warn() { echo "${c_yel}!${c_off} $*"; } die() { echo "${c_red}✗ $*${c_off}" >&2; exit 1; } run() { if [ "$DRY_RUN" = 1 ]; then echo " [dry-run] $*"; else eval "$*"; fi; } # ── Load config ────────────────────────────────────────────────────────────── if [ -f "${SCRIPT_DIR}/config.env" ]; then # shellcheck disable=SC1091 source "${SCRIPT_DIR}/config.env" else # shellcheck disable=SC1091 source "${SCRIPT_DIR}/config.env.example" warn "No config.env found — using defaults from config.env.example." fi # Derived / defaulted values (never hardcode a home directory) : "${NEURON_HOME:=${HOME}/.neuron}" : "${DEV_ROOT:=${HOME}/Development/neuron-technologies}" : "${SOUL_PORT:=7770}"; : "${ENGRAM_PORT:=8742}"; : "${WRAPPER_PORT:=17779}"; : "${PROXY_PORT:=7779}" : "${ENGRAM_DATA_DIR:=${NEURON_HOME}/engram}" : "${ENGRAM_API_KEY:=}" : "${KEYCHAIN_SERVICE:=neuron-llm-0-key}" : "${EL_TOOLCHAIN_SOURCE:=artifact-registry}" : "${NEURON_REPO_BRANCH:=main}" NEURON_REPO="${DEV_ROOT}/neuron" ENGRAM_REPO="${DEV_ROOT}/engram" FOUNDATION_REPO="${DEV_ROOT}/foundation" SOUL_BIN="${NEURON_REPO}/dist/neuron" ENGRAM_BIN="${ENGRAM_REPO}/dist/engram" MCP_WRAPPER_BIN="${NEURON_REPO}/mcp-wrapper/dist/neuron-mcp-wrapper" MCP_PROXY_BIN="${NEURON_REPO}/mcp-proxy/dist/neuron-mcp-proxy" FORGE_BIN="${FOUNDATION_REPO}/forge/dist/forge" GENESIS_SEED="${FOUNDATION_REPO}/forge/seeds/neuron-genesis-seed.json" LAUNCHAGENTS="${HOME}/Library/LaunchAgents" CLAUDE_DIR="${HOME}/.claude" # Generate a local engram token if none was supplied. if [ -z "${ENGRAM_API_KEY}" ]; then ENGRAM_API_KEY="ntn-dev-$(head -c8 /dev/urandom | xxd -p 2>/dev/null || echo local)" fi echo echo "${c_blue}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c_off}" echo "${c_blue} Neuron CORE dev stack installer${c_off}" echo "${c_blue}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c_off}" echo " user : ${USER}" echo " NEURON_HOME : ${NEURON_HOME}" echo " source repos : ${DEV_ROOT}" echo " ports : soul=${SOUL_PORT} engram=${ENGRAM_PORT} wrapper=${WRAPPER_PORT} proxy=${PROXY_PORT}" echo " dry-run : ${DRY_RUN}" echo # render