#!/bin/bash # # Run a local `warp_tui` build. # # Selects the internal `local` channel when the `warp-channel-config` generator # is available (mirroring `./script/run`), otherwise falls back to the OSS # channel so contributors without repo access can still run the TUI. Unlike the # GUI `./script/run`, the TUI is a console binary, so there is no `.app` bundle # step. # # On macOS the binary is built with `cargo build` and then codesigned with a # stable "Apple Development" identity (mirroring `./script/macos/run`). Keychain # item ACLs key off the code signature, so a stable signature means rebuilds # don't re-prompt for your keychain password. Ad-hoc signatures from a plain # `cargo run` change on every build, which is what causes repeated prompts. # # Extra arguments are forwarded to `cargo` (e.g. `--release`); use `--` to # pass arguments through to the binary itself. set -e REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd)" cd "${REPO_ROOT}" ./script/install_channel_config || echo "Skipping internal channel config installation (no repo access)." if command -v warp-channel-config &>/dev/null; then BIN="warp-tui" CHANNEL="local" else BIN="warp-tui-oss" CHANNEL="oss" fi # Split cargo arguments from binary arguments (after `--`), tracking the profile # and target triple so we can locate the built binary (for codesigning on macOS) # and stage resources beside it, matching where Cargo actually writes the output. CARGO_ARGS=() BIN_ARGS=() PROFILE_DIR="debug" TARGET_TRIPLE="" while (( "$#" )); do case "$1" in --) shift BIN_ARGS=("$@") break ;; --release) PROFILE_DIR="release" CARGO_ARGS+=("$1") shift ;; --profile) if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then PROFILE_DIR="$2" CARGO_ARGS+=("$1" "$2") shift 2 else echo "Error: Argument for $1 is missing" >&2 exit 1 fi ;; --target) if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then TARGET_TRIPLE="$2" CARGO_ARGS+=("$1" "$2") shift 2 else echo "Error: Argument for $1 is missing" >&2 exit 1 fi ;; --target=*) TARGET_TRIPLE="${1#--target=}" CARGO_ARGS+=("$1") shift ;; *) CARGO_ARGS+=("$1") shift ;; esac done # Build with the `standalone` feature so `bundled_resources_dir()` resolves the # sibling `resources/` directory next to the executable at runtime (matching how # the packaged TUI is built in script/macos/bundle). Without it, the app can't # locate its bundled skills when run outside a `.app` bundle. Keep voice input # enabled for local macOS development while leaving Linux builds free of ALSA. TUI_FEATURES="standalone" if [[ "$(uname -s)" = "Darwin" ]]; then TUI_FEATURES="$TUI_FEATURES,voice_input" fi CARGO_ARGS+=(--features "$TUI_FEATURES") # Resolve Cargo's actual target directory rather than assuming ./target # (honors CARGO_TARGET_DIR / build.target-dir). TARGET_DIR="$(cargo metadata --no-deps --format-version 1 | jq -r .target_directory)" if [ -z "$TARGET_DIR" ] || [ "$TARGET_DIR" = "null" ]; then TARGET_DIR="${REPO_ROOT}/target" fi # Cargo writes to target// when building for an explicit # --target, and target/ otherwise. Mirror that layout so we stage # resources beside — and exec — the exact binary Cargo produced. BUILD_DIR="${TARGET_DIR}" if [ -n "${TARGET_TRIPLE}" ]; then BUILD_DIR="${BUILD_DIR}/${TARGET_TRIPLE}" fi BUILD_DIR="${BUILD_DIR}/${PROFILE_DIR}" # Stage bundled skills and the settings schema next to the binary so the # standalone TUI can resolve them at runtime, including activating the # modify-settings skill. The schema comes from the just-built TUI binary # itself and is for local development only; packaged TUI builds still # consume the canonical schema generated from the full app binary. License # generation remains skipped for local runs. prepare_tui_bundled_resources() { echo "Preparing bundled resources at ${BUILD_DIR}/resources (channel: ${CHANNEL})..." NO_LICENSES=1 SETTINGS_SCHEMA_EXECUTABLE="${BUILD_DIR}/${BIN}" \ "${REPO_ROOT}/script/prepare_bundled_resources" \ "${BUILD_DIR}/resources" "${CHANNEL}" } if [[ "$(uname -s)" = "Darwin" ]]; then echo "Building cargo build -p warp_tui --bin ${BIN} (channel: ${CHANNEL})" cargo build -p warp_tui --bin "${BIN}" "${CARGO_ARGS[@]}" prepare_tui_bundled_resources TUI_BIN_PATH="${BUILD_DIR}/${BIN}" SIGNING_CERT="$(security find-identity -p codesigning -v | grep "Apple Development" | awk '{print $2}' | head -1)" if [ -n "$SIGNING_CERT" ]; then echo "Codesigning ${TUI_BIN_PATH}..." codesign --force --sign "$SIGNING_CERT" "$TUI_BIN_PATH" else echo "Warning: no Apple Development signing identity found; skipping codesign (keychain may re-prompt on rebuilds)." >&2 fi exec "$TUI_BIN_PATH" "${BIN_ARGS[@]}" else echo "Building cargo build -p warp_tui --bin ${BIN} (channel: ${CHANNEL})" cargo build -p warp_tui --bin "${BIN}" "${CARGO_ARGS[@]}" prepare_tui_bundled_resources TUI_BIN_PATH="${BUILD_DIR}/${BIN}" echo "Running ${TUI_BIN_PATH}" exec "${TUI_BIN_PATH}" "${BIN_ARGS[@]}" fi