by pid1 Labs

Discord channels for your Claude Code agents.

Aquila gives every agent its own Discord bot, its own channel, and its own working directory — then runs them. Message #backend and the agent working in that repo answers. Two commands from nothing to a running fleet.

npm install -g @pid1lab/aquila

aquila — zsh
$ aquila init backend=~/src/api frontend=~/src/web You'll create 2 Discord applications, one at a time. Paste each token as you go — a token is shown once, and only one fits on the clipboard. https://discord.com/developers/applications New Application → name it anything → Bot → Reset Token → copy backend token › MTUz•••••••••••••••••••• ✓ MTUz…Xq4A app "Orders API" Now create the next application (2 of 2). frontend token › MTUz•••••••••••••••••••• ✓ MTUz…Vb2C app "Storefront" ✓ backend: message content intent on ✓ frontend: message content intent on ✓ found server "acme-dev" ✓ owner 1021487254104973352 Install the remaining 1 bot — your server is pre-selected, so each is a single Authorize click: frontend https://discord.com/oauth2/authorize?… ✓ frontend: joined ✓ backend: shows as "backend" in the server ✓ frontend: shows as "frontend" in the server ✓ #backend → /home/you/src/api ✓ #frontend → /home/you/src/web ✓ discord channel plugin installed 2 agent(s) ready. Start them with: aquila up $ aquila up · backend starting (pid 91820) · frontend starting (pid 91821) ✓ backend connected → #backend ✓ frontend connected → #frontend
✦

One bot per agent

Each agent is a real Discord bot, so @backend autocompletes, presence and typing indicators are per-agent, and replies thread natively. Webhook impersonation gets you none of that.

◈

Isolation Discord enforces

Every channel is scoped so only its own agent can read it — cross-channel reads return 403. Not a rule in our routing code that a bug could leak through; a rule Discord applies.

◐

No snowflake hunting

The server id comes from the first bot's own guild list, and your user id from that server's owner. No Developer Mode, no right-click Copy ID, no pairing codes.

Quick start

  1. Install

    npm install -g @pid1lab/aquila

    Or run it without installing: bunx @pid1lab/aquila. You'll need Bun either way — the Discord channel plugin's own server runs on it — plus Claude Code, on Linux or macOS.

  2. Create a Discord server

    In the Discord client: + → Create My Own. Three clicks, once — not per agent. Bots can't create servers, so this one is yours.

  3. Provision

    aquila init backend=~/src/api frontend=~/src/web

    Run this before making any applications — Aquila walks you through them, asking for one bot token at a time and waiting for each. It then enables the Message Content intent, hands you a one-click install link per bot, creates a scoped channel each, and writes access policy and tool pre-approval.

  4. Create each application as it asks

    At the Developer Portal: New Application → name it anything → Bot → Reset Token → copy, then paste it back into Aquila. About 40 seconds each. Name them whatever you like; Aquila sets a server nickname so each bot displays as its agent name.

    Aquila asks for them one at a time on purpose. A token is shown once and can only be recovered by resetting it, so making several up front loses all but the last to the clipboard.

  5. Run them

    aquila up

    Returns in about a second. Each agent runs as a detached session with its own pty and its own bot token, and outlives your shell. Message #backend and it answers.

Commands

CommandWhat it does
aquila init <agent…>Provision bots and channels. Accepts name or name=path.
aquila add <agent> [path]Add one more agent to the server you already have.
aquila up [agent…]Start agents. Returns immediately; verifies each gateway actually connected.
aquila down [agent…]Stop agents. Confirms the process group actually exited.
aquila statusAgents, channels, and session state. Flags any config/reality drift.
aquila sessions [agent…]Conversations per agent, marking the one each is bound to.
aquila bind <agent> <id>Point an agent at a different conversation. Restarts resume it.
aquila sync [agent…]Opt agents into every channel their bot can see.
aquila allow [name…]Let other people trigger agents in shared channels, by name.
aquila move <agent> <path>Change working directory — carries settings, checks trust, restarts.
aquila set <agent> k=vChange a setting, warning when a restart is needed to apply it.

Useful flags

FlagEffect
--webPaste tokens into a browser form instead of the terminal.
--trustAccept Claude Code's folder-trust prompt for each agent's directory.
--adoptTake over an existing channel that already has the agent's name.
--renameAlso change the bot's global username (rate-limited; rarely wanted).

Every command and flag, plus how agents, bots, sessions and channels map to each other — read the docs.

A shared room

Agents can join a common channel alongside their private one. With requireMention on, each responds only when addressed — and because these are real bot users, @backend autocompletes in Discord's composer.

They can read each other there: channel history comes back unfiltered, including other agents' replies. They can't wake each other, so you stay the scheduler — ask one agent something, then ask another to build on it.

What Aquila can't do

Two things Discord won't allow. We'd rather say so here than have you find out halfway through setup.

It can't create the Discord application

There is no public endpoint. The Developer Portal drives private routes with a user token, and automating that means driving a user account — self-botting under Discord's terms, with real account-termination risk. Aquila doesn't do it, and neither should anything else you install. Budget about 40 seconds per agent.

It can't create the server

Discord closed POST /guilds to applications on 2025-07-15 — bots now get Bots cannot use this endpoint, and guilds that bots did own were transferred to real users. So you create the server. Three clicks, once, not per agent.

Everything else is automatic: intent flags, install links with your server pre-selected, scoped channels, access policy, tool pre-approval, and the sessions themselves.

Built on the official channel plugin

Aquila sits on top of Anthropic's discord channel plugin rather than replacing it — writing its config, and launching sessions with --channels. Per-agent isolation comes from giving each one its own state directory.