diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 96b3dea840..f7b2fcdf23 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,21 +53,38 @@ To run Altimate Code in the root of the opencode repo itself: bun dev . ``` -### Building a "localcode" +### Building and running a local binary -To compile a standalone executable: +The easiest way to build and run a compiled binary locally: ```bash -./packages/opencode/script/build.ts --single +cd packages/opencode + +# Build for current platform + run +./script/local.sh + +# Run without rebuilding (fast iteration) +./script/local.sh --skip-build + +# Pass flags to altimate-code +./script/local.sh -- --help ``` -Then run it with: +Or use the package.json scripts: ```bash -./packages/opencode/dist/opencode-/bin/opencode +bun run build:local # just build for current platform +bun run local # build + run ``` -Replace `` with your platform (e.g., `darwin-arm64`, `linux-x64`). +The script handles platform detection, `NODE_PATH` setup for native modules +like `@altimateai/altimate-core`, and binary resolution automatically. + +To compile all platform targets (CI/release): + +```bash +bun run build +``` - Core pieces: - `packages/opencode`: Altimate Code core business logic & server. diff --git a/packages/opencode/package.json b/packages/opencode/package.json index d8b0312950..69c91626ba 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -9,6 +9,8 @@ "typecheck": "tsgo --noEmit", "test": "bun test --timeout 30000", "build": "bun run script/build.ts", + "build:local": "bun run script/build.ts --single --skip-install", + "local": "./script/local.sh", "dev": "bun run --conditions=browser ./src/index.ts", "db": "bun drizzle-kit" }, diff --git a/packages/opencode/script/local.sh b/packages/opencode/script/local.sh new file mode 100755 index 0000000000..13810633fa --- /dev/null +++ b/packages/opencode/script/local.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# Build and run altimate-code locally from a compiled binary. +# +# Usage: +# ./script/local.sh # build + run +# ./script/local.sh --skip-build # run without rebuilding +# ./script/local.sh -- --help # pass flags to altimate-code +# +# The script: +# 1. Builds a single-platform binary (current OS/arch) via `bun run script/build.ts --single --skip-install` +# 2. Sets NODE_PATH so the compiled Bun binary can find @altimateai/altimate-core +# 3. Launches the binary with any trailing arguments + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PKG_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" + +# Parse script flags (everything before --) +SKIP_BUILD=false +ARGS=() +while [[ $# -gt 0 ]]; do + case "$1" in + --skip-build) SKIP_BUILD=true; shift ;; + --) shift; ARGS=("$@"); break ;; + *) ARGS+=("$1"); shift ;; + esac +done + +# --- Build --- +if [ "$SKIP_BUILD" = false ]; then + echo "Building for current platform..." + # Run in subshell to avoid changing the working directory + (cd "$PKG_DIR" && bun run script/build.ts --single --skip-install) +fi + +# --- Resolve binary --- +OS="$(uname -s | tr '[:upper:]' '[:lower:]')" +ARCH="$(uname -m)" + +# Detect Rosetta 2: if the shell runs under Rosetta on Apple Silicon, +# uname -m reports x86_64 but bun builds a native arm64 binary. +if [ "$OS" = "darwin" ] && [ "$ARCH" = "x86_64" ]; then + if sysctl -n sysctl.proc_translated 2>/dev/null | grep -q 1; then + ARCH="arm64" + fi +fi + +case "$ARCH" in + aarch64|arm64) ARCH="arm64" ;; + x86_64) ARCH="x64" ;; +esac + +BINARY="$PKG_DIR/dist/@altimateai/altimate-code-${OS}-${ARCH}/bin/altimate" +if [ ! -f "$BINARY" ]; then + echo "error: binary not found at $BINARY" >&2 + echo "Available builds:" >&2 + ls "$PKG_DIR/dist/@altimateai/" 2>/dev/null || echo " (none)" >&2 + exit 1 +fi + +# --- Run --- +export NODE_PATH="$PKG_DIR/node_modules${NODE_PATH:+:$NODE_PATH}" +# Use ${ARGS[@]+"${ARGS[@]}"} to avoid "unbound variable" on bash 3.2 (macOS default) +exec "$BINARY" ${ARGS[@]+"${ARGS[@]}"}