Configuration
Who you are, where he runs, what he may spend, and what ships switched off.
Where settings live
Everything is in .env at the top of your checkout. ./setup.sh creates it from .env.example, which describes every setting with its default. The backend loads the file itself (a variable already set in its environment wins), and the start scripts never export it. Most values are read on every call; to be sure a change applies, run ./restart.sh backend. Never commit .env.
The essentials
./setup.sh asks for these three:
| Variable | What it is |
|---|---|
EDWARD_OWNER_NAME | What Edward calls you. Unset, he says “the owner”. |
ANTHROPIC_API_KEY | Your key from console.anthropic.com. Every model call uses it. |
TIMEZONE | Your IANA zone (America/New_York), until the app’s own setting (Edward tab → House → Locale) is loaded. |
About you
Read by backend/services/owner.py. The code never names its owner any other way.
| Variable | What it is |
|---|---|
EDWARD_OWNER_FULL_NAME, EDWARD_OWNER_ALIASES | Other names you go by, so he recognises you in messages. |
EDWARD_OWNER_HANDLES | Your phone numbers, emails and Apple ID: how he recognises your iMessages and your self-chat. Set it if he reads your messages. |
EDWARD_OWNER_EMAILS | Your email addresses: mail from these is yours, and he never emails you. |
EDWARD_HOUSEHOLD | The people at the household hub, comma-separated, you first. |
EDWARD_SENSITIVE_NAMES | Pets, family and anyone else whose mentions his memory upkeep must never retire on its own. |
This Mac
Read by backend/services/host_config.py.
| Variable | Default | What it is |
|---|---|---|
EDWARD_PUBLIC_BASE_URL | http://localhost:3000 | Where you open Edward (a tunnel’s https address). Links in pushes and texts use it. |
EDWARD_TUNNEL_LABEL | unset | Your tunnel’s LaunchAgent label, so the health check watches and restarts it. |
EDWARD_BACKEND_HOST | 0.0.0.0 | The backend listens on every interface so a hub on your network can reach it; 127.0.0.1 keeps it to this Mac. |
EDWARD_COOKIE_SECURE | on | The session cookie assumes HTTPS (or http://localhost). off only on a plain-HTTP network you trust. |
EDWARD_LAUNCHD_PREFIX | com.meet-edward | The LaunchAgents’ label prefix. |
EDWARD_BACKUP_DIR | ~/edward-backups | Where the nightly backup goes. A /Volumes/… path is a removable drive (skipped while unplugged; needs Full Disk Access). |
NEXT_PUBLIC_BASE_URL | the base URL | The app’s public origin for link previews, baked into the frontend build: after changing it, run bash frontend/deploy-build.sh and restart the frontend. |
The model and the money
EDWARD_LLM_PROVIDER=anthropic is the default: every call goes to the Claude API, with one route per purpose.
| Route | Used for | Model, effort |
|---|---|---|
chat | your conversations, ping replies, scheduled events | Sonnet 5.5, medium |
mind | every wake: follow-through, the nightly, free time, speaking up | Sonnet 5.5, medium |
pulse | deciding what the widget and screens show | Sonnet 5.5, medium |
background | memory extraction and upkeep, the noticer, photo descriptions | Haiku 5.5, high |
voice | spoken turns | Sonnet 5.5, low |
judge | evaluations | Opus 5.5, high |
Override any of them per purpose with EDWARD_CLAUDE_<PURPOSE>_MODEL, _EFFORT, _MAX_TOKENS, _THINKING_DISPLAY and _CACHE_TTL (for example EDWARD_CLAUDE_CHAT_MODEL).
| Variable | Default | What it bounds |
|---|---|---|
EDWARD_DAILY_SPEND_CAP_USD | 5 | Dollars over your local day. Background work stops at 60 % of it (EDWARD_BACKGROUND_SPEND_SHARE), Edward’s own turns at the cap, and your own turns may run EDWARD_INTERACTIVE_RESERVE_USD (3) past it. |
EDWARD_TURN_MAX_USD | 3.00 | One turn you asked for. |
EDWARD_AUTONOMOUS_TURN_MAX_USD | 1.00 | One turn you didn’t (a wake, a ping from a friend, an event). |
EDWARD_CREDITS_START_USD, EDWARD_CREDITS_START_DATE | unset | Set both to count prepaid credits down on the Fuel card (console.anthropic.com stays the authority). |
Every call is priced and shown in the app (Edward tab → Work → Usage) and at GET /api/health/spend.
The Codex fallback: EDWARD_LLM_PROVIDER=codex runs GPT through the Codex CLI’s ChatGPT login. That is not an official API for third-party apps, may break at any time and may conflict with OpenAI’s terms; use it at your own risk. OPENAI_API_KEY switches it to the public API.
Off by default, and the switch for each
A fresh install reads nothing private and reaches no one. Each feature below stays off, or does nothing, until you turn it on.
| What | How to turn it on |
|---|---|
| Every skill | Edward tab → Mind → Skills (Shell/Bash, Web Search, iMessage, Push Notifications, iOS Widget, Voice…) |
Reading your iMessages, and @Edward pings | Edward tab → Attention → Listening → Configuration → Messages; Full Disk Access; Messages on this Mac signed into your Apple ID; EDWARD_OWNER_HANDLES. Pings then follow EDWARD_PINGS (on). Read this first. |
| Mail.app | Listening → Configuration → Email; Full Disk Access; keep Mail.app running |
| Gmail | An OAuth client (GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET; gmail-setup.md), then Attention → Gmail → Watch my inbox |
| Noticing (speaking up unasked) | EDWARD_PROACTIVITY=shadow (decides, never speaks), then notice |
| Hands in your Chrome | Load chrome-extension/ unpacked in Chrome, then EDWARD_CHROME_HANDS=on |
| His shell, editor, your Chrome and the screens in friends’ pings | EDWARD_FRIENDS_FULL_TOOLSET=on, at a risk: a friend’s message then drives a shell that runs as you |
| Approvals for tainted turns | EDWARD_TAINT_APPROVALS=shadow (log only) or on |
| Voice | ELEVENLABS_API_KEY, ELEVENLABS_VOICE_ID |
| Push notifications | npx web-push generate-vapid-keys into VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY, then allow notifications in the app (HTTPS) |
| The hub’s pets and care | Copy backend/hub_seed.example.json to backend/hub_seed.json, describe your own, set EDWARD_HUB_SEED=hub_seed.json |
| The hub’s people | EDWARD_HOUSEHOLD (just you until set) |
| The household photo door (a photos-only login) | PHOTO_DOOR_PASSWORD_HASH: a bcrypt hash, in single quotes (.env.example has the command) |
| Twilio SMS and WhatsApp (a number of Edward’s own) | TWILIO_* and EDWARD_OWNER_HANDLES. Webhooks are refused without TWILIO_AUTH_TOKEN, and only your own numbers get an answer; EDWARD_TWILIO_ANSWER_ANYONE=on answers everyone, at a risk |
| The WhatsApp bridge | Run the whatsapp-mcp Go bridge yourself, then MCP_WHATSAPP_ENABLED=true |
| apple-mcp (a fallback for reading your calendar) | Install bun, clone apple-mcp, MCP_APPLE_ENABLED=true |
| Alexa and Home Assistant | ALEXA_SKILL_ID, HOME_ASSISTANT_URL, HOME_ASSISTANT_TOKEN. Inbound Alexa requests are not signature-checked yet: leave ALEXA_SKILL_ID unset unless you use the skill |
| Brave Search | BRAVE_SEARCH_API_KEY, only needed with the Claude server-side web tools off (EDWARD_SERVER_WEB_TOOLS=off) or on the Codex fallback |
| The knowledge graph | GRAPHITI_ENABLED=true (queues every new memory) and GRAPHITI_INGEST_ENABLED=true (fills the graph from the queue), then bash scripts/install-launchagents.sh --with-graph. Each memory costs a few background model calls |
| Hosted pages | HTML_HOSTING_URL and HTML_HOSTING_API_KEY. There is no default host |
| A daily cap on his own pushes | EDWARD_PUSH_BUDGET=<n> (none by default) |
| Deep health checks for a hub kiosk and for mail | EDWARD_HEALTH_HUB_KIOSK=1, EDWARD_HEALTH_EMAIL=1 |
| The Codex fallback | EDWARD_LLM_PROVIDER=codex (unofficial, at your own risk) |
On by default
Know these before you leave Edward running:
- The daily spend cap, $5 over your local day.
- Quiet hours, 22:00–07:00 (
EDWARD_QUIET_HOURS=22-7; equal hours mean none). Pushes and spoken lines wait for morning. - Two scheduled wakes a day: a silent nightly at 03:00, skipped when nothing happened, and one free-time run at 13:00 (about $0.50 at most) that reaches nobody.
- The surfaces pulse: a check every 15 minutes that runs a model turn only when the board, the calendar, a screen or the widget changed.
- The nightly backup at 03:30 to
~/edward-backups, on the same disk, unless you install with--without-backupor pointEDWARD_BACKUP_DIRelsewhere. Keep a copy off the Mac too. - The late-dose alert (
EDWARD_CARE_WATCH=on), which has nothing to watch until the hub has timed care items. - The egress secret scan and the shell sandbox. Their
offvalues are emergency switches only.
Everything else
The full annotated list is .env.example; the environment section of CLAUDE.md has the main ones with their defaults on one screen. Nothing reads GITHUB_TOKEN, USPS_API_USER_ID or the LangSmith variables any more.
The iPhone widget has its own token, set up in Widget, screen & hub.