Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ HOST=0.0.0.0
DISPATCH_PORT=6767
DATABASE_URL=postgres://dispatch:[email protected]:5432/dispatch
AUTH_TOKEN=change-me
MEDIA_ROOT=/tmp/dispatch-media
DISPATCH_BIN_DIR=/path/to/dispatch/bin
MEDIA_ROOT=~/.dispatch/media
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: "25.8.0"
node-version: "22"
cache: "npm"
cache-dependency-path: |
package-lock.json
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: "25.8.0"
node-version: "22"
cache: "npm"
cache-dependency-path: |
package-lock.json
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,10 @@ web/dist
.env.local
data
tmp-*.mjs
*.png
*.jpg
*.jpeg
*.gif
*.webp
artifacts/
.playwright-mcp/
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v25.8.0
v22
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
- Do not pin a fixed Vite port unless explicitly requested; let Vite choose an open port automatically.
- If multiple local Dispatch instances are running, always use the exact URL printed by the active Vite process for Playwright/manual checks.

## Temporary Files
- Never write temporary files (screenshots, test scripts, scratch files) to the repo root.
- Use `/tmp/` or `$DISPATCH_MEDIA_DIR` for ephemeral files.
- Playwright screenshots should be published via `dispatch-share`, not saved locally.

## Backend Testing Safety
- Treat `127.0.0.1:6767` as production by default; do not stop or kill the existing production server for ad-hoc testing.
- When backend changes need local validation, run a separate backend instance on a different port (for example `DISPATCH_PORT=8788 npm run dev`) and point validation tooling to that port.
Expand Down
5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
- Do not pin a fixed Vite port unless explicitly requested; let Vite choose an open port automatically.
- If multiple local Dispatch instances are running, always use the exact URL printed by the active Vite process for Playwright/manual checks.

## Temporary Files
- Never write temporary files (screenshots, test scripts, scratch files) to the repo root.
- Use `/tmp/` or `$DISPATCH_MEDIA_DIR` for ephemeral files.
- Playwright screenshots should be published via `dispatch-share`, not saved locally.

## Backend Testing Safety
- Treat `127.0.0.1:6767` as production by default; do not stop or kill the existing production server for ad-hoc testing.
- When backend changes need local validation, run a separate backend instance on a different port (for example `DISPATCH_PORT=8788 npm run dev`) and point validation tooling to that port.
Expand Down
7 changes: 7 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# TODO

## Deferred Improvements

- [ ] **Enforce AUTH_TOKEN in API middleware** β€” token exists in config but no handler validates it. Wire up bearer token check before exposing outside Tailscale.
- [ ] **Switch `launchctl load/unload` to `launchctl bootstrap/bootout`** β€” deprecated API in `install-launchd` and `uninstall-launchd`. Still works but may break in future macOS.
- [ ] **Add log rotation for `~/.dispatch/logs/dispatch.log`** β€” currently grows unbounded. Best option is rotating in `dispatch-launchd-wrapper` on restart since launchd holds the fd.
2 changes: 1 addition & 1 deletion bin/dispatch-deploy
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ spawn_diagnosis_agent() {
# Generate agent ID and session name
local agent_id="agt_$(openssl rand -hex 6)"
local session_name="dispatch_${agent_id}"
local media_dir="/tmp/dispatch-media/${agent_id}"
local media_dir="$HOME/.dispatch/media/${agent_id}"
mkdir -p "$media_dir"

local port
Expand Down
120 changes: 120 additions & 0 deletions bin/preflight
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/usr/bin/env bash
set -euo pipefail

# Preflight check for Dispatch dependencies.
# Run this on a new machine before install-launchd to see what's missing.

pass=0
fail=0
warn=0

ok() { pass=$((pass + 1)); printf " βœ“ %s\n" "$1"; }
fail() { fail=$((fail + 1)); printf " βœ— %s\n" "$1"; }
warn() { warn=$((warn + 1)); printf " ~ %s\n" "$1"; }

echo "Dispatch preflight check"
echo "========================"
echo ""

# --- Required ---

echo "Required:"

# Git
if command -v git &>/dev/null; then
ok "git $(git --version | awk '{print $3}')"
else
fail "git β€” install Xcode CLI tools: xcode-select --install"
fi

# NVM
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
if [[ -s "$NVM_DIR/nvm.sh" ]]; then
ok "nvm (at $NVM_DIR)"
# shellcheck disable=SC1090
. "$NVM_DIR/nvm.sh"

# Node (via NVM)
if command -v node &>/dev/null; then
NODE_MAJOR=$(node -v | sed 's/v\([0-9]*\).*/\1/')
if (( NODE_MAJOR >= 22 )); then
ok "node $(node -v)"
else
fail "node $(node -v) β€” need >= 22, run: nvm install 22"
fi
else
fail "node β€” run: nvm install 22"
fi
else
fail "nvm β€” install: brew install nvm (then add to ~/.zshrc)"
fi

# Docker
if command -v docker &>/dev/null; then
if docker info &>/dev/null; then
ok "docker (running)"
else
fail "docker installed but not running β€” start Docker Desktop"
fi
else
fail "docker β€” install: brew install --cask docker"
fi

# tmux
if command -v tmux &>/dev/null; then
ok "tmux $(tmux -V | awk '{print $2}')"
else
fail "tmux β€” install: brew install tmux"
fi

echo ""
echo "Optional:"

# GitHub CLI
if command -v gh &>/dev/null; then
if gh auth status &>/dev/null 2>&1; then
ok "gh $(gh --version | head -1 | awk '{print $3}') (authenticated)"
else
warn "gh $(gh --version | head -1 | awk '{print $3}') (not authenticated β€” run: gh auth login)"
fi
else
warn "gh β€” needed for releases, install: brew install gh"
fi

# Claude CLI
if command -v claude &>/dev/null; then
ok "claude ($(which claude))"
else
warn "claude β€” needed to spawn Claude agents"
fi

# Xcode (full, for simulators)
if xcode-select -p &>/dev/null; then
if xcrun simctl list devices &>/dev/null 2>&1; then
ok "xcode + simctl"
else
warn "xcode CLI tools present but simctl unavailable β€” install full Xcode for simulator support"
fi
else
warn "xcode β€” install from App Store for iOS Simulator support"
fi

# Tailscale
if command -v tailscale &>/dev/null || [[ -d "/Applications/Tailscale.app" ]]; then
ok "tailscale"
else
warn "tailscale β€” needed for remote access, install: brew install --cask tailscale"
fi

echo ""
echo "---"
printf "%d passed, %d failed, %d warnings\n" "$pass" "$fail" "$warn"

if (( fail > 0 )); then
echo ""
echo "Fix the failures above, then run bin/preflight again."
exit 1
else
echo ""
echo "Ready to install. Run: bin/install-launchd"
fi
Loading
Loading