Skip to content

Assumptions and Deployments

William Koch edited this page Sep 30, 2026 · 12 revisions

Keryx is designed for one person on one machine. Review these assumptions before you decide where and how to run it.

  • One owner. There's no multi-user model anywhere. There's one OWNER_NAME (what the prompts call you; blank means "the owner"), one ALLOWED_CALLERS list, one PIN, one ~/.config/keryx, one memory, one Slack DM, and one set of API keys. A second person who can call the number and knows the PIN isn't a second user. To Keryx, they're you.
  • Tasks run as you. They run with your full user permissions and never stop to ask for approval, and Codex runs without its sandbox. So anyone who can reach Keryx can run commands on this machine. Don't put it on a host you share.
  • Quiet hours use the machine's local time. APPROVAL_QUIET_HOURS is compared with the machine's clock, so 23:00-07:00 means 11 PM to 7 AM on the host. If the host is in another time zone, set its TZ. Keryx has no time-zone setting of its own.
  • Running without a service manager is supported. SERVICE_MANAGER=none is a real mode. It's also what auto resolves to when the process isn't running as the installed unit, for example a keryx serve you started in a terminal, even on a machine where the service is installed too. auto checks how the process itself was started, not whether systemctl or launchctl is on PATH. In this mode everything works except restarting. If you ask Keryx on a call to restart itself, it refuses on purpose, because stopping the process would leave nothing to start it again. keryx restart also refuses when no unit is installed. This means a task that changes Keryx's code can't make the change take effect by restarting the service. keryx doctor reports which service manager it found, or that it found none.
  • PROJECTS_ROOT is ~/projects unless you set it, and Keryx never creates it. Its subdirectories are the projects you can point a task at by name, and a task with no project starts there. If it isn't a directory, for example on a machine that keeps its code somewhere else, such a task starts in DATA_DIR/workspace instead, which only you can read. So does a task whose project directory was removed after it was queued. keryx doctor warns while the root doesn't exist.
  • git is optional. A restart confirmation uses git describe to say which version was running before and after. Without git on PATH, or outside a checkout, the version shows as "unknown". Everything else still works.
  • The phone is the only channel on main, on macOS and Linux alike. Talking to Keryx locally on a Mac is in development on the feat/local-wakeword branch, and isn't part of main.
  • The service sees the PATH of the shell you installed it from. A service manager starts units with a bare PATH, so the installers write your shell's PATH into them, along with the directories Keryx uses. The units log under STATE_DIR. Install from the shell whose tools the tasks should have, and run the installer again after the PATH or the directories change. See Running as a Service.
  • The optional voice tools are yours to turn on. Slack, email answers, billing, and cluster stats are plugins. They're off until you install them, with keryx setup → Plugins or keryx plugins install NAME. They live with your own tools in DATA_DIR/tools, outside the repository. Everything there runs inside the service, as you. cluster_stats assumes you log in to each cluster through an ssh ControlMaster, and asks only while that login is open. See Custom Tools.
  • The phone channel needs a public hostname you control. That's a Cloudflare-routed name for cloudflared (used by the Linux installer and scripts/dev.sh), or a reserved ngrok domain (used by the macOS installer). Twilio must be able to reach the webhook, and the webhook URL must match PUBLIC_HOST exactly, or signature validation fails.
  • Keryx doesn't text unless you turn it on. SMS_ENABLED is false by default, because many Twilio accounts have no SMS permission for their region, and every send would fail. With texting off, a finished task reaches you by an announcement during a call, by a call back, or at the top of your next call. If you turned the send_to_slack plugin on, Slack is there when you ask for it. Keryx adjusts what it says to this setting: if you decline a call back, it tells you the answer will come in your next call. Outbound calls are unaffected, including the restart watchdog's alerts.

Related

  • Security Model — what the single-owner assumption means for who can reach what.
  • Running as a Service — the systemd and launchd units, and which one SERVICE_MANAGER refers to.

Clone this wiki locally