Skip to content

Commit 7ac9709

Browse files
feat: add start-bridge.sh one-command launcher
Single script at repo root that sets up and launches everything: - Checks prerequisites (python3, pip, node, npm) - Installs engram core + engram-bridge[web] (editable, pip) - Installs frontend deps (npm install) - Creates default ~/.engram/bridge.json if missing - Builds frontend and starts backend (production) - Or runs vite HMR + backend in parallel (--dev) - Connects to existing Engram memory at ~/.engram/ Usage: ./start-bridge.sh # production ./start-bridge.sh --dev # development with HMR ./start-bridge.sh --build # force rebuild + production Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent bacdf49 commit 7ac9709

1 file changed

Lines changed: 278 additions & 0 deletions

File tree

start-bridge.sh

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
#!/usr/bin/env bash
2+
# ═══════════════════════════════════════════════════════════
3+
# start-bridge.sh — One-command setup & launch for Engram Bridge
4+
# ═══════════════════════════════════════════════════════════
5+
#
6+
# Run from the Engram repo root:
7+
#
8+
# ./start-bridge.sh # production (build frontend, serve from backend)
9+
# ./start-bridge.sh --dev # development (vite HMR + backend in parallel)
10+
# ./start-bridge.sh --build # force rebuild frontend, then production
11+
#
12+
# Environment variables (all optional):
13+
# ENGRAM_PORT=8200 # backend port
14+
# VITE_PORT=5173 # vite dev server port (--dev only)
15+
# ENGRAM_BRIDGE_CONFIG=~/.engram/bridge.json
16+
# ENGRAM_LOG_LEVEL=INFO
17+
#
18+
# ═══════════════════════════════════════════════════════════
19+
20+
set -euo pipefail
21+
22+
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
23+
BRIDGE_DIR="$ROOT_DIR/engram-bridge"
24+
WEBUI_DIR="$BRIDGE_DIR/engram_bridge/channels/web-ui"
25+
CONFIG_FILE="${ENGRAM_BRIDGE_CONFIG:-$HOME/.engram/bridge.json}"
26+
LOG_LEVEL="${ENGRAM_LOG_LEVEL:-INFO}"
27+
BACKEND_PORT="${ENGRAM_PORT:-8200}"
28+
VITE_PORT="${VITE_PORT:-5173}"
29+
30+
MODE="production"
31+
if [[ "${1:-}" == "--dev" ]]; then
32+
MODE="dev"
33+
elif [[ "${1:-}" == "--build" ]]; then
34+
MODE="build"
35+
fi
36+
37+
RED='\033[0;31m'
38+
GREEN='\033[0;32m'
39+
YELLOW='\033[1;33m'
40+
CYAN='\033[0;36m'
41+
BOLD='\033[1m'
42+
NC='\033[0m'
43+
44+
log() { echo -e "${CYAN}[engram]${NC} $*"; }
45+
ok() { echo -e "${GREEN}${NC} $*"; }
46+
warn() { echo -e "${YELLOW} !${NC} $*"; }
47+
err() { echo -e "${RED}${NC} $*"; }
48+
49+
# ── Cleanup on exit ──
50+
cleanup() {
51+
echo ""
52+
log "Shutting down..."
53+
jobs -p 2>/dev/null | xargs kill 2>/dev/null || true
54+
wait 2>/dev/null || true
55+
log "Done."
56+
}
57+
trap cleanup EXIT INT TERM
58+
59+
# ══════════════════════════════════════════════════════════
60+
# 1. Prerequisites
61+
# ══════════════════════════════════════════════════════════
62+
63+
check_prerequisites() {
64+
log "Checking prerequisites..."
65+
66+
# Python 3
67+
if ! command -v python3 &>/dev/null; then
68+
err "python3 not found. Install Python 3.10+ first."
69+
exit 1
70+
fi
71+
ok "python3 $(python3 --version 2>&1 | cut -d' ' -f2)"
72+
73+
# pip
74+
if ! python3 -m pip --version &>/dev/null; then
75+
err "pip not found. Install pip first."
76+
exit 1
77+
fi
78+
ok "pip available"
79+
80+
# Node.js
81+
if ! command -v node &>/dev/null; then
82+
err "node not found. Install Node.js 18+ first."
83+
exit 1
84+
fi
85+
ok "node $(node --version)"
86+
87+
# npm
88+
if ! command -v npm &>/dev/null; then
89+
err "npm not found. Install npm first."
90+
exit 1
91+
fi
92+
ok "npm $(npm --version)"
93+
}
94+
95+
# ══════════════════════════════════════════════════════════
96+
# 2. Install Python packages
97+
# ══════════════════════════════════════════════════════════
98+
99+
install_python() {
100+
log "Setting up Python packages..."
101+
102+
# Install Engram core (editable)
103+
if python3 -c "import engram" 2>/dev/null; then
104+
ok "engram already installed"
105+
else
106+
log "Installing engram..."
107+
pip3 install -e "$ROOT_DIR" --quiet 2>/dev/null || pip3 install -e "$ROOT_DIR"
108+
ok "engram installed"
109+
fi
110+
111+
# Install engram-bridge (editable, with web extras)
112+
if python3 -c "import engram_bridge" 2>/dev/null; then
113+
ok "engram-bridge already installed"
114+
else
115+
log "Installing engram-bridge[web]..."
116+
pip3 install -e "$BRIDGE_DIR[web]" --quiet 2>/dev/null || pip3 install -e "$BRIDGE_DIR[web]"
117+
ok "engram-bridge installed"
118+
fi
119+
}
120+
121+
# ══════════════════════════════════════════════════════════
122+
# 3. Install frontend dependencies
123+
# ══════════════════════════════════════════════════════════
124+
125+
install_frontend() {
126+
log "Setting up frontend..."
127+
128+
if [[ -d "$WEBUI_DIR/node_modules" ]]; then
129+
ok "node_modules exists"
130+
else
131+
log "Running npm install..."
132+
(cd "$WEBUI_DIR" && npm install --loglevel=warn)
133+
ok "frontend dependencies installed"
134+
fi
135+
}
136+
137+
# ══════════════════════════════════════════════════════════
138+
# 4. Build frontend
139+
# ══════════════════════════════════════════════════════════
140+
141+
build_frontend() {
142+
log "Building frontend..."
143+
(cd "$WEBUI_DIR" && npm run build)
144+
ok "frontend built → dist/"
145+
}
146+
147+
# ══════════════════════════════════════════════════════════
148+
# 5. Create default config if missing
149+
# ══════════════════════════════════════════════════════════
150+
151+
ensure_config() {
152+
if [[ -f "$CONFIG_FILE" ]]; then
153+
ok "config: $CONFIG_FILE"
154+
return
155+
fi
156+
157+
log "Creating default config at $CONFIG_FILE ..."
158+
mkdir -p "$(dirname "$CONFIG_FILE")"
159+
cat > "$CONFIG_FILE" <<'CONF'
160+
{
161+
"channel": "web",
162+
"web": {
163+
"host": "127.0.0.1",
164+
"port": 8200,
165+
"auth_token": ""
166+
},
167+
"default_agent": "claude-code",
168+
"agents": {
169+
"claude-code": {
170+
"type": "claude",
171+
"model": "claude-opus-4-6",
172+
"allowed_tools": ["Read", "Edit", "Write", "Bash", "Glob", "Grep"]
173+
}
174+
},
175+
"memory": {
176+
"provider": "simple",
177+
"auto_store": true
178+
}
179+
}
180+
CONF
181+
ok "config created: $CONFIG_FILE"
182+
}
183+
184+
# ══════════════════════════════════════════════════════════
185+
# 6. Start servers
186+
# ══════════════════════════════════════════════════════════
187+
188+
start_backend() {
189+
log "Starting backend on port $BACKEND_PORT ..."
190+
engram-bridge --channel web --log-level "$LOG_LEVEL" --config "$CONFIG_FILE" &
191+
BACKEND_PID=$!
192+
}
193+
194+
start_vite() {
195+
log "Starting Vite dev server on port $VITE_PORT ..."
196+
(cd "$WEBUI_DIR" && npm run dev -- --port "$VITE_PORT") &
197+
VITE_PID=$!
198+
}
199+
200+
wait_for_backend() {
201+
local max=30
202+
local i=0
203+
while ! curl -sf "http://127.0.0.1:$BACKEND_PORT/health" >/dev/null 2>&1; do
204+
sleep 1
205+
i=$((i + 1))
206+
if [[ $i -ge $max ]]; then
207+
err "Backend failed to start after ${max}s"
208+
exit 1
209+
fi
210+
done
211+
ok "backend ready"
212+
}
213+
214+
# ══════════════════════════════════════════════════════════
215+
# Main
216+
# ══════════════════════════════════════════════════════════
217+
218+
echo ""
219+
echo -e "${BOLD}═══════════════════════════════════════════${NC}"
220+
echo -e "${BOLD} Engram Bridge — setup & launch ${CYAN}($MODE)${NC}"
221+
echo -e "${BOLD}═══════════════════════════════════════════${NC}"
222+
echo ""
223+
224+
check_prerequisites
225+
echo ""
226+
install_python
227+
echo ""
228+
install_frontend
229+
echo ""
230+
ensure_config
231+
echo ""
232+
233+
case "$MODE" in
234+
build)
235+
build_frontend
236+
echo ""
237+
start_backend
238+
wait_for_backend
239+
echo ""
240+
echo -e "${GREEN}${BOLD} Ready!${NC} Open ${CYAN}http://127.0.0.1:$BACKEND_PORT${NC}"
241+
echo -e " Your Engram memory at ${CYAN}~/.engram/${NC} is connected."
242+
echo -e " Press ${BOLD}Ctrl+C${NC} to stop."
243+
echo ""
244+
wait
245+
;;
246+
247+
dev)
248+
start_backend
249+
wait_for_backend
250+
start_vite
251+
echo ""
252+
echo -e "${GREEN}${BOLD} Ready!${NC}"
253+
echo -e " Backend: ${CYAN}http://127.0.0.1:$BACKEND_PORT${NC} (API + WebSocket)"
254+
echo -e " Frontend: ${CYAN}http://localhost:$VITE_PORT${NC} (Vite HMR)"
255+
echo ""
256+
echo -e " Open the ${BOLD}Vite URL${NC} for development."
257+
echo -e " Your Engram memory at ${CYAN}~/.engram/${NC} is connected."
258+
echo -e " Press ${BOLD}Ctrl+C${NC} to stop both."
259+
echo ""
260+
wait
261+
;;
262+
263+
production)
264+
if [[ ! -f "$WEBUI_DIR/dist/index.html" ]]; then
265+
warn "Frontend not built yet — building now..."
266+
build_frontend
267+
echo ""
268+
fi
269+
start_backend
270+
wait_for_backend
271+
echo ""
272+
echo -e "${GREEN}${BOLD} Ready!${NC} Open ${CYAN}http://127.0.0.1:$BACKEND_PORT${NC}"
273+
echo -e " Your Engram memory at ${CYAN}~/.engram/${NC} is connected."
274+
echo -e " Press ${BOLD}Ctrl+C${NC} to stop."
275+
echo ""
276+
wait
277+
;;
278+
esac

0 commit comments

Comments
 (0)