# Priority Forge Launch Agents

This directory contains macOS Launch Agent configuration files that automatically start and manage Priority Forge services.

## Overview

Priority Forge runs three services:
1. **Backend** - MCP server (port 3456)
2. **Frontend** - React development server (port 5173)
3. **Watchdog** - Health monitor that auto-restarts services if they crash

## Files

- `com.priority-forge.backend.plist.template` - Backend MCP server (template)
- `com.priority-forge.frontend.plist.template` - Frontend development server (template)
- `com.priority-forge.watchdog.plist.template` - Service health monitor (template)

These are **templates** — they contain `@@MARKER@@` placeholders for the node/npm binary paths, the install directory, `$HOME`, and a service `PATH`. `./setup.sh install-launchd` resolves the placeholders at install time and writes the rewritten plists into `~/Library/LaunchAgents/`. Do **not** copy the templates directly; launchd will exec the literal `@@NODE@@` string and the service will fail.

## Installation

### Prerequisites

1. Clone Priority Forge to a stable location (the install path is baked into the deployed plists)
2. Run `npm install` in the project root and `cd frontend && npm install`
3. Build the backend: `npm run build` (the backend plist runs `dist/index.js`)

### Setup

```bash
# 1. Install — resolves markers from the templates and loads the services.
./setup.sh install-launchd

# 2. Register MCP with Claude Code (stdio transport — required for main session tool loading)
npm run setup:mcp
# Choose option 3 (Claude Code CLI)

# 3. Verify
npm run verify
```

The installer:

- Resolves `node` and `npm` via `command -v` (so it works on Apple-Silicon Homebrew, Intel Homebrew, the official Node .pkg installer, nvm, Volta, fnm, and asdf), rather than hardcoding `/opt/homebrew/bin/node`.
- Substitutes `@@NODE@@`, `@@NPM@@`, `@@INSTALL_DIR@@`, `@@HOME@@`, and `@@PATH@@` in every `*.plist.template` and writes the result to `~/Library/LaunchAgents/`.
- Refuses to load any deployed plist that still has an unrewritten marker — fast-fail beats launchd silently exec'ing a literal `@@NODE@@`.

## Verification

Check that all services are running:

```bash
# Check process status
launchctl list | grep priority-forge

# Test backend health
curl http://localhost:3456/version

# Test frontend
curl http://localhost:5173
```

You should see three entries:
- `com.priority-forge.backend` (should show PID)
- `com.priority-forge.frontend` (should show PID)
- `com.priority-forge.watchdog` (should show PID)

## Logs

View service logs:

```bash
# Backend logs
tail -f ~/.local/share/priority-forge/.pids/launchd-backend.log
tail -f ~/.local/share/priority-forge/.pids/launchd-backend-error.log

# Frontend logs
tail -f ~/.local/share/priority-forge/.pids/launchd-frontend.log
tail -f ~/.local/share/priority-forge/.pids/launchd-frontend-error.log

# Watchdog logs
tail -f /tmp/priority-forge-watchdog.log
tail -f /tmp/priority-forge-watchdog-stdout.log
tail -f /tmp/priority-forge-watchdog-stderr.log
```

## Restarting Services

```bash
# Restart individual services
launchctl kickstart -k gui/$(id -u)/com.priority-forge.backend
launchctl kickstart -k gui/$(id -u)/com.priority-forge.frontend
launchctl kickstart -k gui/$(id -u)/com.priority-forge.watchdog

# Or use the setup script
./setup.sh restart
```

## Stopping Services

```bash
# Stop individual services
launchctl stop com.priority-forge.backend
launchctl stop com.priority-forge.frontend
launchctl stop com.priority-forge.watchdog

# Or use the setup script
./setup.sh stop
```

## Uninstallation

To completely remove Priority Forge launch agents:

```bash
# 1. Unload the services
launchctl unload ~/Library/LaunchAgents/com.priority-forge.backend.plist
launchctl unload ~/Library/LaunchAgents/com.priority-forge.frontend.plist
launchctl unload ~/Library/LaunchAgents/com.priority-forge.watchdog.plist

# 2. Remove plist files
rm ~/Library/LaunchAgents/com.priority-forge.*.plist

# Or use the setup script
./setup.sh uninstall-launchd
```

## Customization

### Changing Ports

Edit the following in the .plist files:

**Backend (default: 3456):**
Set `PORT` environment variable in `com.priority-forge.backend.plist`

**Frontend (default: 5173):**
This is controlled by Vite. To change it, modify `frontend/vite.config.ts`

### Changing Installation Path

The deployed plists in `~/Library/LaunchAgents/` contain absolute paths, so moving the Priority Forge checkout to a different directory invalidates them. Re-run the installer from the new location to regenerate them:

```bash
cd /new/path/to/priority-forge
./setup.sh install-launchd
```

### Changing Node.js installation

The deployed backend plist contains the absolute path to the `node` binary that was on `PATH` when you ran the installer. If you switch Node versions (nvm switch, replace pkg install with Homebrew, etc.), re-run `./setup.sh install-launchd` so the plists pick up the new binary path.

### Picking up code changes after `git pull`

The backend plist runs the compiled `dist/index.js`. After a `git pull` (or any source edit), rebuild and kick the service:

```bash
npm run build
launchctl kickstart -k gui/$(id -u)/com.priority-forge.backend
```

The frontend service runs `npm run dev`, which has hot reload, so it picks up source changes automatically and doesn't need a kickstart.

## How It Works

### Backend Service
- Runs Node.js MCP server from `dist/index.js`
- Listens on port 3456
- Auto-starts on login (`RunAtLoad: true`)
- Restarts if it crashes (`KeepAlive: true`)

### Frontend Service
- Runs `npm run dev` in the `frontend/` directory
- Listens on port 5173
- Auto-starts on login
- Restarts on crash but not on successful exit

### Watchdog Service
- Runs a bash script that checks backend and frontend health every 30 seconds
- Pings backend at `http://localhost:3456/version`
- Pings frontend at `http://localhost:5173`
- Uses `localhost` (not `127.0.0.1`) so curl tries both IPv4 and IPv6 — Vite's default host binds IPv6 only on macOS, and the v4-forced probe would false-fail
- Sleeps 15s at startup before the first health check so it doesn't race the backend/frontend boot during `launchctl load`
- Auto-restarts services if health checks fail
- Logs all actions to `/tmp/priority-forge-watchdog.log`

## Troubleshooting

### Services won't start

1. Check logs for errors:
   ```bash
   cat ~/.local/share/priority-forge/.pids/launchd-backend-error.log
   cat ~/.local/share/priority-forge/.pids/launchd-frontend-error.log
   ```

2. Verify Node.js is installed and re-resolve the plist binary paths:
   ```bash
   command -v node          # any absolute path — Homebrew, pkg, nvm, etc.
   ./setup.sh install-launchd   # rewrites the deployed plists with the resolved path
   ```

3. Verify Priority Forge is built:
   ```bash
   ls dist/index.js
   ```

### Port conflicts

If ports 3456 or 5173 are already in use:

```bash
# Check what's using the port
lsof -i :3456
lsof -i :5173

# Kill the process if needed
kill -9 <PID>
```

### Path issues after moving Priority Forge

If you moved Priority Forge to a different directory:

1. Update all paths in the .plist files
2. Reload the services:
   ```bash
   launchctl unload ~/Library/LaunchAgents/com.priority-forge.*.plist
   launchctl load ~/Library/LaunchAgents/com.priority-forge.*.plist
   ```

### Services crash immediately

Check that:
- Dependencies are installed: `npm install` and `cd frontend && npm install`
- Backend is built: `npm run build`
- Permissions are correct: `chmod +x scripts/watchdog.sh`

## Development vs Production

These launch agents are configured for **development mode**:
- Frontend runs with hot reload (`npm run dev`)
- Backend runs compiled JavaScript
- Logs are verbose

For production deployment, consider:
- Building frontend: `cd frontend && npm run build`
- Serving static frontend files with nginx/caddy
- Running backend with production environment variables
- Implementing proper log rotation
- Using a process manager like PM2 for more robust service management

## Additional Resources

- [launchd man page](https://ss64.com/osx/launchctl.html)
- [Creating Launch Daemons and Agents](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html)
- Priority Forge main documentation: [../README.md](../README.md)
