Skip to main content

Setup Guide

Complete instructions for getting Seraph fully running with all features.

Prerequisites​

RequirementWhy
Docker DesktopRuns backend, frontend, and sandbox containers
uvPython package manager (used by the daemon and scripts)
macOS 13+ (Ventura)Required for the native screen daemon (PyObjC, AppleScript)
Python 3.12+Daemon runtime (outside Docker)
OpenRouter accountLLM API access (powers the agent)

Configuration​

All settings live in .env.dev at the project root. The only required value is your API key:

OPENROUTER_API_KEY=<openrouter_api_key>

Optional model settings​

VariableDefaultDescription
DEFAULT_MODELopenrouter/anthropic/claude-sonnet-4LLM model for the agent (any OpenRouter model)
MODEL_TEMPERATURE0.7Sampling temperature
MODEL_MAX_TOKENS4096Max tokens per response
AGENT_MAX_STEPS10Max reasoning steps per turn
DEBUGfalseEnable debug logging

Optional runtime routing settings​

These control which model/profile a specific runtime path uses, plus how that path falls back if its primary target fails:

VariableDefaultDescription
LOCAL_MODEL(empty)Model id for the local runtime profile
LOCAL_LLM_API_BASE(empty)API base for the local runtime profile
LOCAL_RUNTIME_PATHS(empty)Comma-separated runtime paths or glob patterns that should prefer the local profile
RUNTIME_PROFILE_PREFERENCES(empty)Semicolon-separated `runtime_path=profile_a
RUNTIME_POLICY_INTENTS(empty)Semicolon-separated `runtime_path=intent_a
RUNTIME_POLICY_SCORES(empty)Semicolon-separated `runtime_path=intent_a:weight
RUNTIME_MODEL_OVERRIDES(empty)Comma-separated runtime_path=model or runtime_path=profile:model entries; runtime_path may be exact or a glob
RUNTIME_FALLBACK_OVERRIDES(empty)Semicolon-separated `runtime_path=model_a
PROVIDER_CAPABILITY_OVERRIDES(empty)Semicolon-separated `model_or_glob=capability_a
FALLBACK_MODEL(empty)Legacy single fallback target
FALLBACK_MODELS(empty)Comma-separated ordered global fallback chain
FALLBACK_LLM_API_BASE(empty)Optional API base override for fallback calls

Examples:

LOCAL_RUNTIME_PATHS=chat_agent,session_consolidation,daily_briefing
RUNTIME_PROFILE_PREFERENCES="chat_agent=local|default;session_consolidation=local|default"
RUNTIME_POLICY_INTENTS="chat_agent=local_first|reasoning|tool_use;session_title_generation=fast|cheap"
RUNTIME_POLICY_SCORES="chat_agent=reasoning:5|tool_use:4;session_title_generation=fast:5|cheap:3"
RUNTIME_MODEL_OVERRIDES=chat_agent=default:openai/gpt-4.1-mini,session_consolidation=default:openai/gpt-4o-mini
RUNTIME_FALLBACK_OVERRIDES="chat_agent=openai/gpt-4.1-mini|openai/gpt-4.1-nano;session_title_generation=openai/gpt-4o-mini|openai/gpt-4.1-mini"
PROVIDER_CAPABILITY_OVERRIDES="openrouter/anthropic/claude-sonnet-4=reasoning|tool_use;openai/gpt-4o-mini=fast|cheap;openai/gpt-4.1-mini=reasoning|tool_use"

Pattern-based examples for dynamic runtime paths:

LOCAL_RUNTIME_PATHS=mcp_*
RUNTIME_PROFILE_PREFERENCES="mcp_*=local|default"
RUNTIME_POLICY_INTENTS=mcp_*=local_first|tool_use
RUNTIME_POLICY_SCORES=mcp_*=tool_use:5
RUNTIME_MODEL_OVERRIDES=mcp_*=openai/gpt-4.1-mini,mcp_github_actions=local:ollama/coder
RUNTIME_FALLBACK_OVERRIDES="mcp_*=openai/gpt-4.1-mini|openai/gpt-4.1-nano;mcp_github_actions=openai/gpt-4o-mini|openai/gpt-4.1-mini"
PROVIDER_CAPABILITY_OVERRIDES=openai/gpt-4.1-mini=reasoning|tool_use;openai/gpt-4o-mini=fast|cheap

Current built-in runtime paths include chat_agent, onboarding_agent, strategist_agent, context_window_summary, session_title_generation, session_consolidation, daily_briefing, evening_review, activity_digest, and weekly_activity_review.

Optional scheduling settings​

These control when proactive features run (briefings, reviews, working hours):

VariableDefaultDescription
USER_TIMEZONEUTCYour timezone (e.g., America/New_York)
WORKING_HOURS_START9Hour (24h) when working hours begin
WORKING_HOURS_END17Hour (24h) when working hours end
MORNING_BRIEFING_HOUR8Hour for the daily morning briefing
EVENING_REVIEW_HOUR21Hour for the evening review
MEMORY_CONSOLIDATION_INTERVAL_MIN30Minutes between memory consolidation runs
GOAL_CHECK_INTERVAL_HOURS4Hours between goal progress checks
CALENDAR_SCAN_INTERVAL_MIN15Minutes between calendar scans
STRATEGIST_INTERVAL_MIN15Minutes between strategist ticks
ACTIVITY_DIGEST_HOUR20Hour for the daily screen activity digest
WEEKLY_REVIEW_HOUR18Hour for the Sunday weekly activity review
SCREEN_OBSERVATION_RETENTION_DAYS90Days to keep screen observations before cleanup
SCHEDULER_ENABLEDtrueEnable/disable background scheduler

Optional observer settings​

These control the observer system and proactive behavior:

VariableDefaultDescription
PROACTIVITY_LEVEL3Proactivity scale (1–5, higher = more proactive)
OBSERVER_GIT_REPO_PATH(empty)Path to a git repo for commit-aware context
DEEP_WORK_APPS(empty)Comma-separated extra app keywords that trigger deep work state

Optional timeout settings​

These control execution timeouts for agent and tool operations:

VariableDefaultDescription
AGENT_CHAT_TIMEOUT120Seconds before chat agent execution times out
AGENT_STRATEGIST_TIMEOUT60Seconds before strategist agent times out
AGENT_BRIEFING_TIMEOUT60Seconds before daily briefing / evening review times out
CONSOLIDATION_LLM_TIMEOUT30Seconds before memory consolidation LLM call times out
WEB_SEARCH_TIMEOUT15Seconds before web search times out
BROWSER_SITE_ALLOWLISTemptyComma-separated domain allowlist applied to browse_webpage and web_search; when set, only matching domains and subdomains are allowed
BROWSER_SITE_BLOCKLISTemptyComma-separated domain blocklist applied to browse_webpage and web_search in addition to internal/private network blocking

Optional context window settings​

These control how conversation history is trimmed before being sent to the LLM:

VariableDefaultDescription
CONTEXT_WINDOW_TOKEN_BUDGET12000Max tokens for conversation history
CONTEXT_WINDOW_KEEP_FIRST2Always keep first N messages (preserves onboarding context)
CONTEXT_WINDOW_KEEP_RECENT20Always keep last N messages

Optional delegation settings​

Recursive delegation is an experimental feature where the agent delegates to specialist sub-agents:

VariableDefaultDescription
USE_DELEGATIONfalseEnable orchestrator + specialist agents mode
DELEGATION_MAX_DEPTH1Max nesting depth (1 = orchestrator → specialists)
ORCHESTRATOR_MAX_STEPS8Max delegation steps for orchestrator

Optional LLM call logging settings​

These control per-call observability logging for all LiteLLM calls (direct and via smolagents):

VariableDefaultDescription
LLM_LOG_ENABLEDtrueEnable LLM call logging to JSONL file
LLM_LOG_CONTENTfalseInclude full messages and response text (large, privacy-sensitive)
LLM_LOG_DIR/app/logsDirectory for log files
LLM_LOG_MAX_BYTES52428800Max bytes per log file before rotation (default 50 MB)
LLM_LOG_BACKUP_COUNT5Number of rotated log files to keep

All settings with their defaults are defined in backend/config/settings.py.

Start the local direct stack​

This is the recommended path for browser development because it always loads the repo-root .env.dev before starting services.

./manage.sh -e dev local up

This starts:

  • backend (localhost:8004) — FastAPI + uvicorn reload
  • frontend (localhost:3001) — Vite dev server

Useful local commands:

./manage.sh -e dev local status
./manage.sh -e dev local logs backend
./manage.sh -e dev local logs frontend
./manage.sh -e dev local down

For live observation from a managed Codex/Desktop shell, use foreground mode and keep the session open:

./manage.sh -e dev local run

Managed command sessions can clean up background children after the command returns. In that environment, local up may briefly print successful backend/frontend PIDs and then leave no running services, no PID files, local status reporting stopped, and immediate curl failures on 127.0.0.1:8004 or 127.0.0.1:3001. Use local run when chatting with Seraph or watching live behavior because it keeps the stack attached while tailing backend, frontend, and daemon logs.

Before declaring the app ready for a live chat test, verify all three:

./manage.sh -e dev local status
curl -sS http://127.0.0.1:8004/health
curl -sS -I http://127.0.0.1:3001/

When finished, stop through the same lifecycle entry point:

./manage.sh -e dev local down

Local VLM/GPU topology for screenshot analysis and local Gemma routing:

Seraph frontend       http://127.0.0.1:3001
-> Seraph backend http://127.0.0.1:8004
-> Mac VLM wrapper http://127.0.0.1:8000
-> GPU model server http://192.168.1.26:8000/v1

The Mac VLM wrapper runs through Docker Compose from /Users/bigcube/Desktop/repos/vlm-screenshot-server; do not run the native Python wrapper for normal operation:

cd /Users/bigcube/Desktop/repos/vlm-screenshot-server
docker compose up -d --build

Verify both local services and the GPU edge before declaring the system ready:

cd /Users/bigcube/Desktop/repos/vlm-screenshot-server
docker compose ps
curl http://127.0.0.1:8000/health
curl http://127.0.0.1:8000/health/backend

cd /Users/bigcube/Desktop/repos/seraph
curl http://127.0.0.1:8004/health

Docker Desktop must be running on the Mac for this path. If /health/backend returns 502, Seraph and the wrapper can be up while the wrapper still cannot reach the GPU model server at 192.168.1.26:8000/v1.

Defaults for the local direct stack:

SettingDefault
Frontend port3001
Backend port8004
Workspace dir/tmp/seraph-dev-data
LLM log dir/tmp/seraph-dev-logs

Override them when needed:

LOCAL_FRONTEND_PORT=3100 LOCAL_BACKEND_PORT=8100 ./manage.sh -e dev local up

Start the Docker stack​

./manage.sh -e dev up -d

This starts four containers:

  • backend-dev (localhost:8004) — FastAPI + uvicorn
  • sandbox-dev — snekbox (sandboxed shell execution)
  • http-mcp — FastMCP HTTP request tool server (internal network only)
  • frontend-dev (localhost:3000) — Vite dev server

Verify everything is running:

# Health check
curl http://localhost:8004/health

# Open the UI
open http://localhost:3000

# Swagger API docs
open http://localhost:8004/docs

Screen daemon​

The native macOS daemon runs outside Docker and posts the active window context to the backend. This enables context-aware features like deep work detection.

warning

The daemon is a standalone native process — it is not managed by Docker. Stopping Docker services (./manage.sh -e dev down) does not stop the daemon. If the daemon was started with --ocr, it will continue capturing and analyzing screenshots even when the backend is down. Always stop the daemon explicitly when you're done.

Starting the daemon​

./daemon/run.sh --verbose

To start the daemon automatically with ./manage.sh -e dev up -d, set in .env.dev:

DAEMON_ENABLED=true
DAEMON_ARGS=--verbose

Stopping the daemon​

./manage.sh -e dev daemon stop

Or manually:

# Find the daemon process
ps aux | grep seraph_daemon | grep -v grep

# Kill it by PID
kill <pid>

Daemon status​

./manage.sh -e dev daemon status

Daemon management commands​

CommandDescription
./manage.sh -e dev daemon startStart the daemon
./manage.sh -e dev daemon stopStop the daemon
./manage.sh -e dev daemon statusCheck if the daemon is running
./manage.sh -e dev daemon logsView daemon logs

On first run, macOS will prompt for Accessibility permission (needed to read window titles):

  1. Open System Settings > Privacy & Security > Accessibility
  2. Click + and add your terminal app (Terminal, iTerm2, Warp, etc.)
  3. Toggle it on

This is a one-time grant. The daemon will then report the frontmost app and window title every 5 seconds.

Daemon options​

FlagDefaultDescription
--urlhttp://localhost:8004Backend base URL
--interval5Poll interval in seconds
--idle-timeout300Seconds of inactivity before skipping POSTs
--verboseoffLog every context POST

Optional: Screen Activity Tracking​

Screen analysis ingests local screenshot files from the configured screenshot folder, stores observations, and powers daily/weekly activity digests. Seraph does not own screenshot capture cadence for this path.

# Apple Vision (local, free, ~200ms per capture)
./daemon/run.sh --ocr --verbose

# OpenRouter cloud analysis (Gemini 2.5 Flash Lite, structured JSON, ~$1.30/mo)
OPENROUTER_API_KEY=<openrouter_api_key> ./daemon/run.sh --ocr --ocr-provider openrouter --verbose

# With custom app blocklist
./daemon/run.sh --ocr --ocr-provider openrouter --blocklist-file ~/blocklist.json --verbose
ProviderProsCons
apple-vision (default)Free, offline, fast (~200ms)Text-only, no layout understanding
openrouterStructured JSON output, understands layoutRequires API key, small cost

Screen analysis options​

FlagDefaultDescription
--ocroffEnable screenshot analysis on context switch
--ocr-providerapple-visionapple-vision (local) or openrouter (cloud, structured)
--ocr-modelgoogle/gemini-2.5-flash-liteModel for OpenRouter provider
--openrouter-api-key$OPENROUTER_API_KEYAPI key for OpenRouter provider
--blocklist-file(none)Path to JSON blocklist config (extends built-in defaults)

Screen Recording permission​

OCR requires the Screen Recording permission:

  1. Open System Settings > Privacy & Security > Screen & System Audio Recording (or Screen Recording on older macOS)
  2. Click + and add your terminal app
  3. Toggle it on

Note: Starting with macOS Sequoia (15.0), the system shows a monthly confirmation prompt asking if you want to continue allowing screen recording. This cannot be suppressed. If permission is revoked, the daemon continues in window-only mode.

Optional: Stdio MCP Proxy​

The stdio proxy wraps stdio-only MCP servers (like github-mcp-server or things-mcp) as HTTP endpoints so the Dockerized backend can connect to them. It runs natively on macOS so proxied tools can access system APIs (AppleScript, URL schemes, etc.).

Configuration​

Add entries to data/stdio-proxies.json:

{
"proxies": {
"things3": {
"command": "uvx",
"args": ["things-mcp"],
"port": 8100,
"enabled": true,
"description": "Things3 task manager"
}
}
}

Start the proxy​

./manage.sh -e dev proxy start

Then register the proxied server with the backend:

./mcp.sh add things3 http://host.docker.internal:8100/mcp --desc "Things3 task manager"

To start the proxy automatically with ./manage.sh -e dev up -d, set in .env.dev:

PROXY_ENABLED=true
PROXY_ARGS=--verbose

Optional: MCP Servers​

Seraph supports plug-and-play MCP server integration. Servers are configured in data/mcp-servers.json and can be managed three ways:

  • CLI: ./mcp.sh list, add <name> <url>, remove, enable, disable, test — when the backend is running, mcp.sh calls the API for live-reload; falls back to direct file editing when offline
  • Settings UI: Add/remove/toggle servers in the Settings panel
  • REST API: GET/POST /api/mcp/servers, PUT/DELETE /api/mcp/servers/{name}

No config file = no MCP tools, no errors. See data/mcp-servers.example.json for the format.

Things3 Example​

If you use Things3 for task management, Seraph can read and create tasks via MCP (22 tools).

  1. Install and start the MCP server as a LaunchAgent:

    ./scripts/install-things-mcp.sh
  2. Grant Full Disk Access to uvx (path shown by the script, typically /opt/homebrew/bin/uvx):

    • System Settings > Privacy & Security > Full Disk Access > + > enter the path
  3. Restart the service:

    launchctl kickstart -k gui/$(id -u)/com.seraph.things-mcp
  4. Register the server:

    ./mcp.sh add things3 http://host.docker.internal:9100/mcp --desc "Things3 task manager"
  5. Restart the backend and check for Connected to MCP server: 22 tools loaded in logs.

See Things3 MCP Integration for the full tool list, LaunchAgent management, and troubleshooting.

Optional: Google Calendar​

Seraph can read your Google Calendar as an observer data source. Upcoming events are included in the strategist's context, enabling calendar-aware proactive features (e.g., meeting detection, schedule-aware nudges). This is not a user-facing tool — the agent cannot create or modify calendar events directly.

Note: For full calendar management (create/edit/delete events), use a calendar MCP server instead.

1. Create OAuth credentials​

  1. Go to Google Cloud Console
  2. Create a new project (or use an existing one)
  3. Enable the Google Calendar API
  4. Go to APIs & Services > Credentials > Create Credentials > OAuth client ID
  5. Application type: Desktop app
  6. Configure the OAuth consent screen (External is fine for personal use; add yourself as a test user)
  7. Download the credentials JSON file

2. Mount the credentials​

Place the downloaded file at:

backend/config/google_credentials.json

This directory is volume-mounted into Docker at /app/config/, so the backend can access it at /app/config/google_credentials.json.

3. First-run OAuth flow​

On the first calendar scan, the backend will initiate an OAuth consent flow in the container logs. Follow the URL to authorize read access. A token file (google_calendar_token.json) is created automatically in the backend data directory.

After initial authorization, the token refreshes automatically. If no credentials are configured, the calendar source silently returns empty — no errors are raised.

Optional: GitHub MCP​

GitHub MCP integration is currently disabled (commented out in docker-compose.dev.yaml). The official github-mcp-server image only supports stdio transport, which doesn't work in a container network.

Two options are available:

  • Stdio proxy: Use the stdio proxy (mcp-servers/stdio-proxy/) to wrap github-mcp-server as an HTTP endpoint. Add it to data/stdio-proxies.json, start with ./manage.sh -e dev proxy start, then register with ./mcp.sh add github http://host.docker.internal:<port>/mcp.
  • GitHub's hosted MCP endpoint: https://api.githubcopilot.com/mcp/ — register directly with ./mcp.sh add github https://api.githubcopilot.com/mcp/ and configure a GitHub token via the Settings UI.

Optional: SKILL.md Skills​

Skills are zero-code markdown capability contributions that extend the agent's behavior. Drop a .md file in data/skills/ with YAML frontmatter and the agent gains new capabilities via prompt injection.

---
name: code-review
description: Reviews code for quality and best practices
requires:
tools: [read_file]
user_invocable: true
enabled: true
---

When asked to review code, follow these steps:
1. Read the file(s) mentioned
2. Check for security issues, performance problems, and style violations
3. Provide specific, actionable feedback

Skills can be managed via:

  • Settings UI: Toggle skills on/off in the Settings panel
  • REST API: GET /api/skills, PUT /api/skills/{name}, POST /api/skills/reload
  • Tool gating: Skills with requires.tools only activate when required tools are available
  • Extension doctor security scan: packaged skills, workflows, and prompt packs are rejected if they contain instruction-override, prompt/secret exfiltration, or approval-bypass phrases that look like executable prompt injection rather than documentation/examples

Eight bundled skills: daily-standup, code-review, goal-reflection, weekly-planner, morning-intention, evening-journal, moltbook (requires http_request), web-briefing (requires http_request + web_search).

Retired: Village Map Editor​

The standalone village map editor is retired and no longer part of the supported Seraph product surface. The active repo no longer ships the editor/ app.

Resetting everything​

To start completely fresh (useful for testing onboarding):

./reset.sh        # Reset dev environment (default)
./reset.sh prod # Reset prod environment

This stops containers, prunes Docker images/volumes, deletes all persistent data (database, memories, soul file, OAuth tokens, logs), and rebuilds from scratch.

Also clear browser state:

// In browser DevTools console
localStorage.clear()

Troubleshooting​

ProblemCauseFix
curl: (7) Failed to connect to localhost:8004Backend not running./manage.sh -e dev up -d and check ./manage.sh -e dev logs -f backend-dev
local up reports started, then local status says stopped and pids/ is emptyManaged Codex/Desktop command session cleaned up background children after the command returnedUse ./manage.sh -e dev local run for live observation, keep it open, verify health with curl -sS http://127.0.0.1:8004/health, and stop with ./manage.sh -e dev local down
OPENROUTER_API_KEY error in logsMissing or invalid API keySet OPENROUTER_API_KEY in .env.dev and rebuild: ./manage.sh -e dev up -d
Daemon: "No window title" / title is always NoneAccessibility permission not grantedGrant in System Settings > Privacy & Security > Accessibility
Daemon: "Backend not reachable"Backend not running or wrong URLStart backend first; check --url flag
Daemon still capturing after stopping servicesDaemon runs outside Docker and isn't stopped by docker compose downRun ./manage.sh -e dev daemon stop or kill <pid>
Daemon exits immediatelyMissing PyObjCRun cd daemon && uv pip install -r requirements.txt
Failed to connect to MCP serverThings3 MCP not runningCheck: curl http://localhost:9100/mcp; ensure LaunchAgent is loaded
unable to open database file (Things3)Full Disk Access not granted to uvxGrant FDA, then restart the things-mcp service
Google Calendar: "credentials not found"Missing google_credentials.jsonPlace OAuth credentials at backend/config/google_credentials.json
Google Calendar: OAuth flow failsContainer can't open browserCopy the auth URL from container logs and open it in your host browser