Stabilize local dev daemon homes

Use a checkout-local .dev/paseo-home for root and worktree dev flows so development daemons do not collide with the packaged app home.

Split server, app, and desktop dev entrypoints, seed worktree homes from the source checkout metadata, and keep desktop dev on its own user-data directory and Expo port.
This commit is contained in:
Mohamed Boudra
2026-06-07 23:18:32 +07:00
parent d55e1622cb
commit 7c8b290e2f
11 changed files with 349 additions and 141 deletions
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
export PATH="$ROOT_DIR/node_modules/.bin:$PATH"
source "$SCRIPT_DIR/dev-home.sh"
export PASEO_LISTEN="${PASEO_LISTEN:-127.0.0.1:6768}"
configure_dev_paseo_home
EXPO_PORT="${EXPO_PORT:-8081}"
DAEMON_ENDPOINT="$(resolve_dev_daemon_endpoint)"
echo "══════════════════════════════════════════════════════"
echo " Paseo App Dev"
echo "══════════════════════════════════════════════════════"
echo " Metro: http://localhost:${EXPO_PORT}"
echo " Daemon: ${DAEMON_ENDPOINT}"
echo " Home: ${PASEO_HOME}"
echo "══════════════════════════════════════════════════════"
exec cross-env \
BROWSER="${BROWSER:-none}" \
APP_VARIANT=development \
EXPO_PUBLIC_LOCAL_DAEMON="$DAEMON_ENDPOINT" \
npm run start:expo --workspace=@getpaseo/app -- --port "$EXPO_PORT"
+4 -1
View File
@@ -5,6 +5,8 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PATH="$SCRIPT_DIR/../node_modules/.bin:$PATH"
source "$SCRIPT_DIR/dev-home.sh"
export PASEO_LISTEN="${PASEO_LISTEN:-127.0.0.1:6768}"
configure_dev_paseo_home
if [ -z "${PASEO_LOCAL_MODELS_DIR}" ]; then
@@ -17,6 +19,7 @@ echo " Paseo Dev Daemon"
echo "══════════════════════════════════════════════════════"
echo " Home: ${PASEO_HOME}"
echo " Models: ${PASEO_LOCAL_MODELS_DIR}"
echo " Listen: ${PASEO_LISTEN}"
echo "══════════════════════════════════════════════════════"
export PASEO_CORS_ORIGINS="${PASEO_CORS_ORIGINS:-*}"
@@ -26,4 +29,4 @@ if [ "${PASEO_SKIP_DEV_SERVER_BUILD:-0}" = "1" ]; then
exec npm run dev:server:watch
fi
exec npm run dev:server
exec sh -c 'npm run build:server-deps && npm run dev:server:watch'
+73 -13
View File
@@ -1,5 +1,9 @@
#!/bin/bash
default_dev_paseo_root() {
git rev-parse --show-toplevel 2>/dev/null || pwd
}
copy_json_tree() {
local source_dir="$1"
local target_dir="$2"
@@ -58,27 +62,83 @@ seed_worktree_paseo_home() {
echo " Seed: copied metadata from ${source_home}"
}
configure_dev_daemon_config() {
if [ -z "${PASEO_LISTEN:-}" ]; then
return
fi
mkdir -p "$PASEO_HOME"
node -e '
const fs = require("fs");
const [path, listen] = [process.argv[1], process.argv[2]];
let cfg = {};
try { cfg = JSON.parse(fs.readFileSync(path, "utf8")); } catch {}
cfg.version = cfg.version || 1;
cfg.daemon = cfg.daemon || {};
cfg.daemon.listen = listen;
cfg.daemon.cors = cfg.daemon.cors || {};
cfg.daemon.cors.allowedOrigins = ["*"];
fs.writeFileSync(path, JSON.stringify(cfg, null, 2));
' "$PASEO_HOME/config.json" "$PASEO_LISTEN"
}
resolve_dev_daemon_endpoint() {
if [ -n "${PASEO_DEV_DAEMON_ENDPOINT:-}" ]; then
echo "$PASEO_DEV_DAEMON_ENDPOINT"
return
fi
case "${PASEO_LISTEN:-127.0.0.1:6768}" in
0.0.0.0:*) echo "localhost:${PASEO_LISTEN#0.0.0.0:}" ;;
127.0.0.1:*) echo "localhost:${PASEO_LISTEN#127.0.0.1:}" ;;
*) echo "$PASEO_LISTEN" ;;
esac
}
configure_dev_paseo_home() {
if [ -n "${PASEO_HOME:-}" ]; then
export PASEO_HOME
if [ -n "${PASEO_DEV_SEED_HOME:-}" ]; then
seed_worktree_paseo_home "$PASEO_HOME"
fi
mkdir -p "$PASEO_HOME"
if [ "${PASEO_DEV_MANAGED_HOME:-0}" = "1" ] || [ -n "${PASEO_DEV_SEED_HOME:-}" ]; then
configure_dev_daemon_config
fi
return
fi
export PASEO_HOME
local git_dir
local git_common_dir
git_dir="$(git rev-parse --git-dir 2>/dev/null || true)"
git_common_dir="$(git rev-parse --git-common-dir 2>/dev/null || true)"
if [ -n "$git_dir" ] && [ -n "$git_common_dir" ] && [ "$git_dir" != "$git_common_dir" ]; then
local worktree_root
local worktree_name
worktree_root="$(git rev-parse --show-toplevel)"
worktree_name="$(basename "$worktree_root" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g; s/--*/-/g; s/^-//; s/-$//')"
PASEO_HOME="$HOME/.paseo-${worktree_name}"
local dev_root
dev_root="${PASEO_DEV_ROOT:-$(default_dev_paseo_root)}"
PASEO_HOME="$dev_root/.dev/paseo-home"
export PASEO_DEV_MANAGED_HOME=1
if [ -n "${PASEO_DEV_SEED_HOME:-}" ]; then
seed_worktree_paseo_home "$PASEO_HOME"
return
fi
PASEO_HOME="$(mktemp -d "${TMPDIR:-/tmp}/paseo-dev.XXXXXX")"
trap "rm -rf '$PASEO_HOME'" EXIT
mkdir -p "$PASEO_HOME"
configure_dev_daemon_config
}
configure_dev_command_env() {
if [ -z "${PASEO_LISTEN:-}" ]; then
if [ -n "${PASEO_SERVICE_DAEMON_PORT:-}" ]; then
export PASEO_LISTEN="0.0.0.0:${PASEO_SERVICE_DAEMON_PORT}"
else
export PASEO_LISTEN="127.0.0.1:6768"
fi
fi
configure_dev_paseo_home
}
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
if [ "$#" -gt 0 ]; then
configure_dev_command_env
exec "$@"
fi
configure_dev_paseo_home
fi
+1 -40
View File
@@ -1,43 +1,4 @@
#!/bin/bash
set -e
# Ensure node_modules/.bin is in PATH (for when script runs directly)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PATH="$SCRIPT_DIR/../node_modules/.bin:$PATH"
source "$SCRIPT_DIR/dev-home.sh"
configure_dev_paseo_home
# Share speech models with the main install to avoid duplicate downloads
if [ -z "${PASEO_LOCAL_MODELS_DIR}" ]; then
export PASEO_LOCAL_MODELS_DIR="$HOME/.paseo/models/local-speech"
mkdir -p "$PASEO_LOCAL_MODELS_DIR"
fi
echo "══════════════════════════════════════════════════════"
echo " Paseo Dev"
echo "══════════════════════════════════════════════════════"
echo " Home: ${PASEO_HOME}"
echo " Models: ${PASEO_LOCAL_MODELS_DIR}"
echo "══════════════════════════════════════════════════════"
npm run build:server
npm run build --workspace=@getpaseo/expo-two-way-audio
# Configure the daemon for the Portless app origin and let the app bootstrap
# through the daemon's Portless URL instead of a fixed localhost port.
APP_ORIGIN="$(portless get app)"
DAEMON_ENDPOINT="$(portless get daemon | sed -E 's#^https?://##')"
# Allow any origin in dev so Electron on random ports and Portless URLs all work.
# SECURITY: wildcard CORS is unsafe in production — only acceptable here because
# the daemon binds to localhost and this script is never used for production.
export PASEO_CORS_ORIGINS="*"
# Run both with concurrently
# BROWSER=none prevents auto-opening browser
# EXPO_PUBLIC_LOCAL_DAEMON configures the app to auto-connect to this daemon
concurrently \
--names "daemon,metro" \
--prefix-colors "cyan,magenta" \
"portless run --name daemon sh -c 'PASEO_SKIP_DEV_SERVER_BUILD=1 PASEO_LISTEN=0.0.0.0:\$PORT exec ./scripts/dev-daemon.sh'" \
"BROWSER=none APP_VARIANT=development EXPO_PUBLIC_LOCAL_DAEMON='${DAEMON_ENDPOINT}' portless run --name app npm run start:expo --workspace=@getpaseo/app"
exec npm run dev:server