# Connect this machine to Zonx — agent quickstart

You are (most likely) an AI coding agent whose human asked you to connect
this machine to Zonx, the enterprise AI messenger. This page is the
machine-readable version of <https://zonx.ai/install>. Everything below runs
in an ordinary terminal; nothing needs sudo.

## 0 · Review, then install the CLI

Download the installer, read it so you can tell your human what it does,
then run it:

```sh
curl -fsSL https://zonx.ai/sh -o zonx-install.sh
cat zonx-install.sh          # ~160 lines; installs one binary to ~/.local/bin
sh zonx-install.sh
```

The installer detects OS/arch (macOS/Linux · arm64/amd64), downloads the
`zonx` CLI over HTTPS, verifies its sha256 against the published
`checksums.txt`, and installs it to `~/.local/bin/zonx`. Safe to re-run.

## 1 · Sign your human in

```sh
zonx human login
```

Show your human the verification URL and code the command prints, and wait
for them to approve it in a browser. Codes are short-lived, but if one
expires unapproved the CLI mints a fresh one automatically — just show
your human the new code.

## 2 · Ask your human two things, then create the agent

Ask — don't pick for them:

- **A name** for their agent (suggest `assistant`).
- **Which workspace** it lives in:

```sh
zonx human workspaces list
```

If there's exactly one workspace, use it and just confirm. Then:

```sh
zonx setup --name <their-name> --workspace <their-ws-id> --env-dir .
```

This creates the agent on the platform and writes `<name>.env` in the
current directory: bootstrap token, agent id, platform URL, workspace id.
Treat the env file as a secret.

If setup says the account has no eligible workspace, your human needs a
workspace admin to invite them first — relay that and stop.

## 3 · Run the agent

The CLI has a built-in runtime for Claude Code and Codex, and it is the
default — no code to write. It gives the brain the chat tools (read
messages, threads, call transcripts, files), one resumable session per
chat, and credential isolation. `zonx run` picks whichever is on PATH
(Claude Code first); name it explicitly with `--runtime claude` or
`--runtime codex`.

Two rules that keep it working:

- Run it from a **dedicated empty directory**, passed to `--workdir` as an
  **absolute path**. Never from a code repository: its `CLAUDE.md`/`AGENTS.md`,
  hooks and tools would turn every chat message into a long-running coding
  task.
- Turns get a **30-minute budget** by default; a turn that runs out posts the
  fallback "my reply command failed" text.

**Claude Code** needs its subscription token once. This is a step for **your
human, in their own terminal** — it opens a browser, and the token must not
pass through your session log. Ask them to run it and tell you when it's done:

```sh
env -u ANTHROPIC_API_KEY -u ANTHROPIC_AUTH_TOKEN claude setup-token
echo 'CLAUDE_CODE_OAUTH_TOKEN=<the printed token>' >> <name>.env
```

Do not set or unset `ANTHROPIC_API_KEY` or any other credential yourself.
**Codex** needs only its ChatGPT login (`codex login`). Then:

```sh
mkdir -p "$HOME/zonx-agents/<name>"
zonx run --runtime codex --env-file "$PWD/<name>.env" --workdir "$HOME/zonx-agents/<name>"
```

(`--runtime claude` for Claude Code.) Run it in the foreground first. Before
it registers, `zonx run` checks that the provider can actually launch from the
PATH it was given — `codex` is a Node script, so both `codex` and `node` must
be on it — and runs `--version`; a miss exits non-zero with the missing
executable, the PATH it searched, and the fix. A good start prints
`persistent instance … live`, `brain: …` with the provider's resolved path,
and `sandbox reach: …`. The agent never appears online with a brain that
cannot start, so no DM ever gets the fallback text for that reason.
`zonx doctor` runs the same check in its **Providers** section.

It registers the instance, heartbeats, long-polls for updates, replies, and
reads the call transcript when someone mentions the agent about a call. Once
it works, make it durable — see [Keeping it running](#keeping-it-running):
stop the foreground run (the agent holds an exclusive lock), install the
launchd plist or systemd unit, and only then DM the agent.

**What the agent can reach** — tell your human this: the Zonx chat tools and
the files under its workdir. Not configured: network access, GitHub, and any
other external service or credential, even when your human's own shell has
`gh` logged in. The runner states this to the agent in every turn, so when
asked for a private backlog it answers "not configured for this agent; the
machine owner can enable it" rather than inventing a permission failure.

`zonx listen` is a read-only tap on the same update stream if you want to
watch it first.

**A custom brain instead? (advanced)** `--exec <command>` receives the message
on stdin plus `ZONX_*` env vars (`ZONX_MESSAGE_TEXT`, `ZONX_SENDER`,
`ZONX_CHAT_ID`, …) and its stdout becomes the reply — but it has no chat
tools, no per-chat session, and no credential isolation. Do not drive
`codex exec` or `claude -p` through it; that is what `--runtime` is for. The
first word of the command gets the same launch check at startup. The raw API
is documented too — `zonx spec dump -o zonx-api.yaml` — the loop is: register
instance (bootstrap token) → heartbeat → poll updates → post `reply.final`
events.

## Keeping it running

`zonx run` is a foreground process. `nohup … &` is not durable — a
coding-agent harness reaps detached processes, and nothing restarts one after a
reboot. Hand it to the init system. Both recipes below set `PATH` explicitly,
and that line is the point: launchd starts jobs with
`/usr/bin:/bin:/usr/sbin:/sbin` and systemd user units get a similar default —
no Homebrew, no `~/.local/bin`, no npm prefix. `codex` (and an npm-installed
`claude`) is a Node script whose first line is `#!/usr/bin/env node`, so
**two** executables must be on the service PATH: the provider and `node`.
Homebrew on Apple silicon puts both in `/opt/homebrew/bin`; Intel macOS and
most Linux installs use `/usr/local/bin`; nvm uses
`~/.nvm/versions/node/<version>/bin`. `dirname "$(command -v node)"` prints
the directory to add.

`zonx run` verifies this before it registers and exits with the missing
executable, the PATH it searched, and this fix. Reproduce the check in the
terminal under launchd's default PATH before installing a unit:

```sh
env PATH=/usr/bin:/bin:/usr/sbin:/sbin "$HOME/.local/bin/zonx" doctor
```

Use absolute paths throughout — for the env file `setup` wrote
(`realpath <name>.env`), the workdir, and the binary.

**macOS (launchd)** — `~/Library/LaunchAgents/ai.zonx.<name>.plist`. Replace
`/Users/YOU` with the home directory (launchd does not expand `~`),
`/ABSOLUTE/PATH/TO/<name>.env` with the env file, and `/opt/homebrew/bin` with
the directory that holds the provider and `node`:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>ai.zonx.<name></string>
  <key>ProgramArguments</key>
  <array>
    <string>/Users/YOU/.local/bin/zonx</string>
    <string>run</string>
    <string>--restart-on-update</string>
    <string>--runtime</string><string>codex</string>
    <string>--env-file</string><string>/ABSOLUTE/PATH/TO/<name>.env</string>
    <string>--workdir</string><string>/Users/YOU/zonx-agents/<name></string>
  </array>
  <key>WorkingDirectory</key><string>/Users/YOU/zonx-agents/<name></string>
  <key>EnvironmentVariables</key>
  <dict>
    <key>PATH</key><string>/Users/YOU/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
    <key>HOME</key><string>/Users/YOU</string>
  </dict>
  <key>RunAtLoad</key><true/>
  <key>KeepAlive</key><true/>
  <key>StandardOutPath</key><string>/Users/YOU/Library/Logs/zonx-<name>.log</string>
  <key>StandardErrorPath</key><string>/Users/YOU/Library/Logs/zonx-<name>.log</string>
</dict>
</plist>
```

```sh
mkdir -p ~/Library/Logs
plutil -lint ~/Library/LaunchAgents/ai.zonx.<name>.plist                  # catch typos first
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.zonx.<name>.plist  # start
tail -f ~/Library/Logs/zonx-<name>.log                                    # logs
launchctl kickstart -k gui/$(id -u)/ai.zonx.<name>                        # restart
launchctl bootout gui/$(id -u)/ai.zonx.<name>                             # stop
```

**Linux (systemd user unit)** — `~/.config/systemd/user/zonx-<name>.service`,
with `/usr/local/bin` replaced by the directory that holds the provider and
`node`:

```ini
[Unit]
Description=Zonx agent <name>
After=network-online.target

[Service]
WorkingDirectory=%h/zonx-agents/<name>
Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=%h/.local/bin/zonx run --restart-on-update --runtime codex --env-file /ABSOLUTE/PATH/TO/<name>.env --workdir %h/zonx-agents/<name>
Restart=always
RestartSec=5

[Install]
WantedBy=default.target
```

```sh
loginctl enable-linger "$USER"             # keep it running after logout
systemctl --user daemon-reload
systemctl --user enable --now zonx-<name>  # start
journalctl --user -u zonx-<name> -f        # logs
systemctl --user restart zonx-<name>       # restart
systemctl --user stop zonx-<name>          # stop
```

A healthy log reads `persistent instance … live`, then `brain: …` with the
provider's resolved path and `sandbox reach: …`. If it ends with
`--runtime codex: cannot launch /opt/homebrew/bin/codex — its interpreter
"node" is not on PATH`, the PATH line is wrong for this machine: fix it,
restart the unit, and only then DM the agent. `--restart-on-update` lets the
runner exit cleanly when the CLI updates itself; `KeepAlive` / `Restart=always`
start the new build.

## 4 · Hand back to your human

The agent introduces itself in a DM to your human as soon as it connects —
that's their proof it's alive. From there they can answer in that DM, add
the bot to any chat, or @mention it in channels (open
<https://web.zonx.ai>). You answer through the `zonx run` process.

## Reference

- `zonx --help` · `zonx docs` · `zonx doctor` · `zonx ui` (dashboard; `L` = listen)
- Installer source: <https://zonx.ai/sh> — human-readable page: <https://zonx.ai/install>
