Onboarding

Set yothere up properly: connect a brain, pick a work directory, grant consent, and install the runner.

Beta · access required

yothere is in invite-only beta. The commands below work once you have access.Request access and we'll get you set up.

A yothere install is “set up” when four things are true: a brain is connected, a safe work directory is chosen, unattended tool use is acknowledged, and the always-on runner is installed. This page walks that path and shows the commands that check and apply each piece. For the full env-var reference, see Configuration; to run it as a service, see Self-hosting.

Two ways to onboard

There are two entry points, and they do different jobs. Both are idempotent and safe to re-run.

  • yothere init is the fast scaffold. It creates the home layout, detects any brain already on the machine, and can run a live zero-key demo in about 30 seconds. Start here.
  • The onboarding step registry (python -m yothere.onboarding) is the single source of truth for whether an install is actually set up. Every surface, the CLI wizard, the cockpit first-run card, the voice setup tools, and doctor, renders the same ordered steps. Use it to bring a real install to done.
Note init scaffolds and demos; it does not, by itself, complete setup. The step registry below is what tracks whether the install is ready.

yothere init

yothere init creates the YOTHERE_HOME layout (threads/ data/ state/ logs/), reports any brain already configured (a remote brain URL, existing brains.yaml entries, or a claude CLI on PATH), and seeds brains.yaml only when none exists (a commented template plus a bundled zero-key demo brain). It is idempotent and never overwrites an existing file.

yothere init

yothere init --demo runs a live zero-key loop end to end. It starts the bundled demo brain on a local port, spawns one thread, and drives it through the real runner: spawn, work, blocked, reply, done. Nothing leaves your machine and no API key is required.

yothere init --demo

The onboarding steps

The step registry is the single source of truth for setup state. State derives entirely from files and env, so there is no separate progress database and the registry can never disagree with reality. The ordered steps:

Step What it sets Confirm before apply
brain writes a local-claude default into brains.yaml (or points at a remote brain) no
workdir the directory workers run jobs in (their file and tool scope) no
consent acknowledges unattended tool use yes
notifier how you get pinged when a thread needs you no
service installs the always-on runner and watchdog yes
mcp registers the yothere MCP server with a Claude client yes
voice optional cockpit voice (GEMINI_API_KEY) yes
first_thread spawns your first thread no

Each step is a {check, describe, apply} triple. check reports ok / missing / error from files and env, describe prints the exact change apply would make (file paths, unit names) so you can read it before consenting, and apply performs it. Steps that touch the system or store credentials or consent (consent, service, mcp, voice) are marked confirm-before-apply, and every consumer must confirm those first.

Drive the steps from the module:

# every step with its live state (exits non-zero until setup is complete)
python -m yothere.onboarding status

# apply one step; safe steps take structured args
python -m yothere.onboarding apply workdir --args '{"path": "~/code/my-project"}'

# confirm-before-apply steps prompt unless you pass --yes
python -m yothere.onboarding apply consent --yes

status prints each step and exits non-zero until the required steps pass (the optional voice step is not required). apply <step> runs one step, printing the plan and waiting for y on a confirm-before-apply step unless you pass --yes.

Note There is no yothere onboard subcommand. Onboarding is driven through the module (python -m yothere.onboarding); yothere init is the separate quick-start scaffold.

workdir: pick a safe directory

The harness runs every job against your work directory, and that directory is the file and tool scope for each headless worker turn. yothere refuses a work directory under ~/Documents or ~/Desktop. On macOS a launchd worker cannot read those paths under TCC, so it crash-loops on first file access. Pick a normal project or repo directory instead.

The consent step records that you accept the agent running tools unattended. With the local Claude brain, a worker turn runs claude -p --permission-mode bypassPermissions scoped to your work directory: inside a turn Claude may read and write files and run commands without per-action prompts, and it spends your own Claude plan or API quota. The acknowledgement is stored as RELAY_BYPASS_PERMISSIONS_ACK=1 in the env file. Blocked threads still stop and wait for your reply.

The home layout

Everything writable roots at YOTHERE_HOME (default ~/.yothere, falling back to an existing ~/.relay). Its contents:

Path What
venv/ the core virtualenv holding the wheel (runner, watchdog, CLI); a host-adapter convention, not created by yothere itself
venv-voice/ a second venv for the [voice] extra (heavy telephony deps), kept separate; host-adapter convention
bin/ generated service wrappers (written by service install)
threads/ the dir-per-thread fleet store
threads-archive/ archived threads (yothere kill --archive)
data/ cost ledger, router and scope learning logs, presence, watchdog state
state/ ping state, runner.lock, the rendered board, the VAPID key, push subscriptions, learned constraints
logs/ runner and watchdog logs
vault/ notes root (capture target, preset reads)
brains.yaml the named-brain registry
task-sources.yaml the brain-discovered task source (where your to-dos live)
auth.db users, sessions, and invites store (hosted mode only)

The env file the service wrappers source is $YOTHERE_HOME/relay.env (mode 600). The file name stays relay.env for back-compat even under the yothere home.

  • yothere binds its network surface to loopback by default and refuses work directories that would crash-loop a launchd worker, so the safe default needs no extra hardening.
  • consent, service, mcp, and voice never apply without an explicit confirmation (or --yes), because each touches the system or stores a credential or consent.
  • The consent record is a single env line you can revoke by removing it; it does not weaken the per-thread block-and-wait behavior, so a thread that needs your judgment still pauses.
  • If you host a network-facing cockpit, read the exposure gate in Self-hosting before you bind anything other than 127.0.0.1.