arizuko

arizuko › how-to

getting started

This page walks a fresh host from zero to a running instance with one channel and one invited user. Each step is one command. Skim the whole list first; come back and run them in order.

1. What you need

2. Install

Clone the repo. A self-hosted deploy needs it either way: the daemon images build from it, and the arizuko directory is bind-mounted into the containers at runtime.

git clone https://github.com/kronael/arizuko.git
cd arizuko
make build
sudo make images   # build agent + daemon docker images
sudo install -m 0755 arizuko /usr/local/bin/arizuko

To grab just the CLI, go install github.com/kronael/arizuko/cmd/arizuko@latest — handy for the command itself, but a full deploy still needs the repo for the images and the runtime mount.

The make images step is the longest (several minutes the first time). It builds arizuko-ant:latest, the per-group agent image, plus one image per shipped adapter. From here, arizuko run generates a Docker Compose file and brings the stack up — Docker Compose is the deploy path. For Kubernetes, see the Helm chart under deploy/helm/arizuko/.

3. Create your first instance

Pick a short name. The name becomes the data directory and the systemd unit name.

sudo arizuko create demo

This seeds /srv/data/arizuko_demo/ with:

Pass --product <name> (for example --product assistant) to seed skills and a checklist of API keys to fill in. See products for the catalog.

4. Run it

arizuko run generates docker-compose.yml from the instance state and brings the stack up in the foreground.

sudo arizuko run demo

You should see authd, routd, runed, timed, onbod, dashd, and the agent runner come up. In another shell, check status:

sudo arizuko status demo

For production, run arizuko as a systemd service named arizuko_demo instead of in the foreground. Logs then live in journalctl -u arizuko_demo — the docker log driver is none on purpose, so docker logs shows nothing.

5. Wire your first channel

An instance with no channel adapter has no way to receive messages from the outside. Pick one platform to start. Each guide covers the platform's app/bot setup, the env vars to drop into .env, and the arizuko group add command that binds a chat to a folder.

Telegram, WhatsApp, Mastodon, Bluesky, Reddit, Email, X, and LinkedIn adapters ship in the repo. Their setup follows the same shape; see the README.md next to each daemon (teled/, whapd/, …).

6. Invite your first user

Mint a one-time invite link. target_glob decides which folders the new user will be granted access to. main/** means “the main group and any sub-group under it.”

sudo arizuko invite demo create 'main/**' --max-uses 1 --expires 24h

The command prints a token. Share https://<your-host>/onboarding/<token>. The recipient signs in with one of the configured OAuth providers, lands on a confirmation page, and their auth_users.sub is granted admin on the matched folders. List and revoke with arizuko invite demo list and arizuko invite demo revoke <token>.

7. Verify the agent responds

Two ways to confirm the loop is live.

From the host, inject a message and wait for the reply:

sudo arizuko send demo main "ping" --wait

From the channel, send a message in the wired chat and watch routd pick it up:

sudo journalctl -u arizuko_demo --since "2 min ago" --no-pager | grep -iE 'mention|spawn|reply'

Red flags in the log: error in message loop, container timeout, circuit breaker open, pull access denied for arizuko-ant (means make images never ran on this host).

8. Back up & restore the setup

An agent is data, so the configuration is too. Export the whole instance config to one YAML manifest, keep it in git as a backup, and re-apply it to rebuild — on this host or another.

arizuko export demo > demo.yaml   # groups, routes, grants, ACL, web routes, schedules…
git add demo.yaml && git commit -m "demo config"
arizuko plan demo demo.yaml         # dry-run: what would change
arizuko apply demo demo.yaml        # apply the manifest back

The export/import round-trip is exact — apply a manifest to a fresh DB and re-export it, and you get the same config back (tested in resreg/engine_test.go). The agent's files — persona, memory, skills, diary under groups/<folder>/ — are plain files; back them up with git or any file copy. Together the manifest plus the group folder are the whole agent.

Further reading

Vocabulary:

group
A workspace. Files, diary, skills, and one agent live here. Folder name like main or corp/eng/sre.
agent
The Claude Code instance for a group. Runs in a docker container, started on demand, idle-killed.
channel
Where messages flow in and out: Slack, Discord, Telegram, web, email, …. Each adapter is a separate daemon.
skill
A markdown file under groups/<folder>/.claude/skills/ the agent loads on start. One file, one capability.
route token
A URL-bound credential mapping to a group. /chat/<token>/ opens the guest chat widget; /hook/<token> accepts fire-and-forget webhooks. Legacy /slink/<token> 301s to the new paths. See route tokens.

More guides:

Audit mode (mute outbound)

Two env vars on routd run a group or platform in shadow mode: the agent keeps producing turns, every outbound row lands in messages, but nothing reaches the channel.

SEND_DISABLED_GROUPS
CSV of folder names. Example: SEND_DISABLED_GROUPS=atlas,research.
SEND_DISABLED_CHANNELS
CSV of platform prefixes (the part before : in a JID). Example: SEND_DISABLED_CHANNELS=discord.

Inbound is unaffected. The agent does not know it was muted — reply and send return success. Rows are visible at /dash/activity/ and via the inspect_messages MCP tool. Source: routd/server.go (group mute via SEND_DISABLED_GROUPS; SEND_DISABLED_CHANNELS mutes in the channel Deliverer), core/config.go (parsing).