grok-build-discord-bot
v0.1.0
Published
Discord bot bridging to Grok Build via the Agent Client Protocol (ACP), with live streaming replies
Readme
Grok Build — Discord Bot
Discord bot that bridges to Grok Build (xAI's coding agent) over the Agent Client Protocol (ACP) — JSON-RPC 2.0 on stdio — instead of polling a REST API.
Inspired by wgtechlabs/devin-discord-bot
and Anthropic's official discord channel plugin,
with one key difference: ACP streams session/update notifications push-based, so replies
render live via progressive message edits — no polling loop.
Discord message → discord.js → ACP client ──(stdio JSON-RPC)──> grok agent stdio
↑ live message edits ←── session/update stream ─────────┘Features
- Live streaming — agent text chunks progressively edit the reply (~1.2s cadence)
- Threaded sessions —
@mentionor/grok askspawns a thread; each thread = one ACP session - Tool-call visibility — each tool call is its own line message, edited as status changes
- Plan rendering — ACP
planupdates render as a checklist - Permission buttons —
session/request_permission→ Discord buttons (Allow/Reject), with timeout - Session persistence — thread→session map survives restarts via
session/load - Subscription quota — uses your
grok loginsession by default (SuperGrok / X Premium Plus), not API credits - Workspace sandboxing —
fs/*client requests are confined toGROK_CWD
Prerequisites
- Node.js ≥ 22
- Grok Build installed and authenticated:
curl -fsSL https://x.ai/cli/install.sh | bash grok login # browser auth → uses your subscription - A Discord application + bot token (Developer Portal)
- Enable Message Content privileged intent
- Invite with scopes
bot+applications.commandsand permissions: View Channels, Send Messages, Send Messages in Threads, Create Public Threads, Read Message History, Embed Links, Use Slash Commands
Setup
From a checkout:
npm install
cp .env.example .env # fill in DISCORD_BOT_TOKEN etc.
npm run dev # tsx, or: npm run build && npm startOr install the published package. It reads .env from the directory you
start it in (values already in the environment win). .env.example is in the
package and in this repo:
npm install -g grok-build-discord-bot
grok-build-discord-botAuth mode
| GROK_USE_API_KEY | Billing |
|---|---|
| false (default) | grok login subscription quota (SuperGrok / X Premium+) — the bot strips XAI_API_KEY from the child env so it can't accidentally switch you to credits |
| true | API credits from console.x.ai |
Usage
| Action | Where | Result |
|---|---|---|
| @Grok <task> | guild text channel | new thread + session, streams reply |
| any message | session thread | continues the session |
| any message | DM | session per DM channel |
| /grok ask <task> | anywhere | new session (thread in guilds) |
| /grok stop | session channel | session/cancel |
| /grok reset | session channel | drop mapping; next message starts fresh |
| /grok sessions | anywhere | list thread→session mappings |
| /grok status | anywhere | agent process + session stats |
Image attachments are forwarded as ACP image content blocks (≤ 8 MB).
Architecture
| File | Role |
|---|---|
| src/acp/grok-agent.ts | owns the grok agent stdio subprocess + ClientConnection; respawns on crash |
| src/acp/session-manager.ts | Discord channel ↔ sessionId map, JSON persistence, session/load resume |
| src/acp/fs-handlers.ts | fs/read_text_file/fs/write_text_file sandboxed to GROK_CWD |
| src/discord/markdown.ts | Discord markdown subset + fence-safe 2000-character chunking |
| src/discord/renderer.ts | streaming engine — those payloads → throttled edits, tool-call lines, plan view |
| src/discord/permissions.ts | permission requests → buttons → resolves the pending ACP request |
| src/discord/bot.ts | message/command routing, per-channel prompt queue, update dispatch |
One grok process serves all sessions — ACP multiplexes them over the single stdio stream.
Security notes
- Set
ALLOWED_USER_IDS— the bot runs an agent that can read/write files and run tools under your account. Empty = anyone who can reach the bot can use it. - Prefer a private server/DM; sharing the bot shares your Grok subscription quota.
GROK_ALWAYS_APPROVE=trueskips permission prompts entirely — convenient but dangerous.fs/*requests are jailed toGROK_CWD; run the bot in a container/VM for real isolation.
Dev
npm run typecheck
npm test
npx tsx scripts/acp-smoke.mts # end-to-end ACP handshake + prompt, no Discord neededReleasing
Publishing runs from .github/workflows/publish.yml
on a version tag, using npm trusted publishing. npm checks the workflow's OIDC
identity, so there is no NPM_TOKEN and no 2FA prompt. The package is published
with provenance.
One-time setup (npmjs.com)
On the package (or when creating grok-build-discord-bot): Settings → Trusted
Publisher → GitHub Actions.
| Field | Value |
|---|---|
| Organization / user | ngosangns |
| Repository | grok-build-discord-bot |
| Workflow filename | publish.yml |
| Environment | (leave empty) |
Allow direct npm publish. Publishers created after 3 Sep 2026 default to
staged publish only, and this workflow does not use npm stage publish.
The workflow filename is part of what npm trusts. Renaming it breaks publishing until the trusted publisher is updated to match.
Cutting a release
Bump
versioninpackage.jsonand merge that tomain.Tag the same commit and push the tag:
git tag v0.1.0 && git push origin v0.1.0
The workflow re-runs typecheck, tests and the build, refuses to continue if the
tag disagrees with package.json, then packs and publishes. The tarball must
contain dist/index.js (with the node shebang) and .env.example, and must
not contain source, data/, or .env.
workflow_dispatch accepts a dry-run input that packs and validates without
uploading. CI on main and pull requests does not publish.
