#!/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 -eREPO_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 ;; esacdone# 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"fiCARGO_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/<triple>/<profile> when building for an explicit# --target, and target/<profile> 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}"fiBUILD_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
#!/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/<triple>/<profile> when building for an explicit
# --target, and target/<profile> 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