Quick start

For the terminal-comfortable: install, start, choose a password.

You need

  • A Mac with Apple silicon that can stay on (a Mac mini makes a good host)
  • The Xcode command-line tools (xcode-select --install) and Homebrew
  • An Anthropic API key

1. Install

git clone https://github.com/ben4mn/meet-edward.git && cd meet-edward
./setup.sh          # installs everything, asks for your name, API key and time zone

./setup.sh is safe to run again; each step checks what is already there. It stops before installing anything on an Intel Mac or in a Rosetta shell. It installs python@3.12, postgresql@16 and node with Homebrew, builds pgvector from source for Postgres 16, creates the edward database, makes backend/.venv with pinned dependencies, installs Playwright’s headless shell, runs npm ci, builds two small Swift helpers (media and EventKit), and writes .env from .env.example.

FlagWhat it adds
--with-test-dbthe backend tests’ own Postgres cluster on :5433
--launchagentsruns scripts/install-launchagents.sh at the end
--no-helpersskips building the Swift helpers
--non-interactivenever prompts; takes EDWARD_OWNER_NAME, ANTHROPIC_API_KEY and TIMEZONE from the environment

2. Start Edward, one of two ways

Always on (the usual choice for the Mac that hosts him). launchd starts him now and at every login, and restarts him if he stops:

bash scripts/install-launchagents.sh

It installs the backend (:8000), the frontend (:3000), a health check every five minutes plus a deeper one at 08:00, a nightly backup at 03:30 (to ~/edward-backups unless EDWARD_BACKUP_DIR says otherwise) and a daily memory report, labelled com.meet-edward.*. It takes --with-graph, --without-backup, --dry-run and --uninstall. If you started Edward by hand from this checkout, it stops that copy first.

By hand. He runs until you stop him or the Mac restarts:

./restart.sh        # backend :8000, frontend :3000

With the agents loaded, ./restart.sh (or ./restart.sh backend|frontend) restarts through launchd. It only restarts its own checkout’s Edward: in a second clone it refuses (exit 78) to touch agents that run another one.

The first start takes a few minutes: the backend downloads its embedding model and sets up the database, and the frontend runs its first production build. ./restart.sh waits up to 2 minutes for the backend and 4 for the frontend, then says “still starting” and exits 0. Logs: /tmp/edward-backend.log and /tmp/edward-frontend.log.

3. Choose a password, on the Mac itself

Open http://localhost:3000 on the Mac that runs Edward. The first visit asks for a password and a one-time setup code:

cat backend/.setup_code

The backend writes the code when it starts with no password set; only your macOS user can read it, and it is deleted once the password is set. Until then the API answers nothing but the sign-in pages, and the setup request must come from a page at localhost on this Mac. No screen on the Mac? Forward the port and read the code over ssh:

ssh -L 3000:localhost:3000 you@my-mac.local
ssh you@my-mac.local cat <your checkout>/backend/.setup_code

4. After you sign in

  1. Edward tab → Mind → Skills. Every skill starts off on a fresh install. Turn on what Edward may use: Shell/Bash (his computer: bash and the editor), Web Search, iMessage, Push Notifications, iOS Widget.
  2. House → Locale. Check your time zone: reminders, quiet hours and “today” follow it.
  3. macOS permissions (System Settings → Privacy & Security), only for what you use:
    • Full Disk Access for the python setup.sh prints at the end: iMessage, Mail, Contacts, Calendar and Reminders are read from their databases through it. Started by hand with ./restart.sh, macOS charges your terminal app instead, so grant that too.
    • Automation: macOS asks the first time Edward sends a message or drives Chrome.
    • Calendars and Reminders (for changes): run bash backend/scripts/eventkit_request_access.sh while sitting at the Mac.

Reaching him from your phone

Installing the PWA, push notifications and the microphone all need HTTPS. Put a tunnel (Cloudflare Tunnel, Tailscale, ngrok) or a reverse proxy in front of port 3000, set EDWARD_PUBLIC_BASE_URL to that address, and name the tunnel’s LaunchAgent in EDWARD_TUNNEL_LABEL so the health check watches it. The backend listens on every interface so devices on your network (a hub) can reach it; EDWARD_BACKEND_HOST=127.0.0.1 keeps it to this Mac. Behind a tunnel, leave uvicorn’s FORWARDED_ALLOW_IPS unset: sign-in limits read the client from the tunnel’s own headers.

Is it working?

  • GET /api/health/report (signed in) says what works: turns and tool failures, pings, the calendar, mail, the last memory report, spend, and whether the app’s time zone matches the Mac’s.
  • GET /api/health/spend shows today’s Claude spend against the cap.
  • The watchdog writes to ~/.edward-health/health.log.

Common issues

Signing in loops back to the login page

The session cookie is Secure, which assumes HTTPS (browsers make an exception for http://localhost). Use HTTPS, or set EDWARD_COOKIE_SECURE=off on a plain-HTTP network you trust.

Messages, Mail or Calendar can’t be read

Full Disk Access is tied to the python binary’s path, so brew upgrade python@3.12 silently breaks it: grant the new path and re-run bash scripts/install-launchagents.sh and bash backend/scripts/eventkit_request_access.sh.

pgvector is missing after a Postgres reinstall

brew reinstall postgresql@16 removes the pgvector built from source. Run ./setup.sh again.


Next: Configuration (every setting, and what ships off), or Upgrading from March if you ran the March 2026 release. The README is the canonical version of this page.