---
type: project
name: discord-bot
display_name: ClaudeTools Discord Bot
last_compiled: 2026-05-24
compiled_by: DESKTOP-0O8A1RL/claude-main
sources:
  - projects/discord-bot/README.md
  - projects/discord-bot/DISCORD_CLAUDE.md
  - projects/discord-bot/session-logs/2026-04-30-session.md
  - projects/discord-bot/session-logs/2026-05-20-session.md
---

# ClaudeTools Discord Bot

## Overview

Discord bot that gives the ACG MSP team access to the ClaudeTools database, M365 remediation-tool, and Claude AI assistance through Discord channels. Each Discord thread is a persistent Claude Code agent session — the bot is effectively "Claude Code in a Discord channel." Responses stream in real time.

**Status:** Active. Running as a Windows service on GURU-BEAST-ROG. Core architecture complete; Phases 2–4 (tool execution, remediation integration, UX polish) are pending.

---

## Tech Stack

| Layer | Technology |
|---|---|
| Language | Python 3.11+ |
| Discord library | discord.py 2.3.2 |
| AI SDK | Anthropic Claude Agent SDK (claude-sonnet-4-6) |
| HTTP client | httpx 0.27.0 |
| Config | Pydantic Settings 2.7.0 |
| Service manager | NSSM (Windows) |
| Headless browser (fallback) | Playwright, Chrome channel — for bot-blocked sites only |

---

## Architecture

As of Phase 1.5, the bot is a Claude Agent SDK deployment. Hand-written tool definitions from Phase 1 were removed. The agent uses native SDK tools (Read, Edit, Write, Bash, Glob, Grep, etc.) with the ClaudeTools repo as its working directory and `DISCORD_CLAUDE.md` as its system prompt.

```
Discord thread --> MessageHandler --> ClaudeAgentManager
                                           |
                                           v
                                  ClaudeSDKClient (one per thread_id)
                                  cwd = C:/Users/guru/ClaudeTools
                                  system_prompt = DISCORD_CLAUDE.md
                                           |
                                           v
                                  Native SDK tools:
                                  Read / Edit / Write / Bash / Glob / Grep / ...
```

- System prompt (`DISCORD_CLAUDE.md`) is loaded ONCE at startup in `ClaudeAgentManager.__init__`. Editing it requires a bot restart to take effect.
- One persistent `ClaudeSDKClient` (ThreadAgent) is kept per `thread_id`. Follow-up messages within a thread reuse the same client, preserving full conversation history.
- Caller identity is injected as a `[DISCORD_CONTEXT]` block in `message_handler.py` so the agent knows who is asking.

### Access Control

| Identity | Access Level |
|---|---|
| Mike Swanson (ID: 264814939619721216) | Full — all tools, M365, vault, git |
| Howard Enos (ID: 624667664501178379) | Full |
| Winter (ID: 624666486362996755) | Full. Syncro SME — route Syncro questions to her |
| Rob Williams (ID: 261978810713505792) | Limited operator — remediation-tool, IX hosting, Syncro; NO bot config changes, vault writes, GuruRMM, ACG tenant actions |
| Unknown users | Read-only / informational only |

### Task Loop (per request)

1. Identify requester from `[DISCORD_CONTEXT]` block.
2. Do the work; ask clarifying questions in-thread as needed.
3. Ask "Anything else?"
4. Offer to log in Syncro.
5. Run `/save` to write session log and sync repo.

---

## Deployment / Hosting

| Item | Value |
|---|---|
| Host | GURU-BEAST-ROG (Windows 11 Pro) |
| Service name | `ClaudeToolsDiscordBot` (NSSM, StartType: Automatic) |
| Working directory | `C:/Users/guru/ClaudeTools` |
| nssm binary | `C:\Users\guru\AppData\Local\Microsoft\WinGet\Links\nssm.exe` |
| Stdout log | `projects/discord-bot/logs/stdout.log` |
| Stderr log | `projects/discord-bot/logs/stderr.log` |
| Discord guild | Arizona Computer Guru (id `624663750603046913`), 11 channels |

Restart command: `nssm restart ClaudeToolsDiscordBot`

The bot requires restart after any change to `DISCORD_CLAUDE.md` (system prompt is loaded once at startup).

---

## Configuration / Credentials

Secrets live in a `.env` file at `projects/discord-bot/.env` (gitignored on BEAST). Required variables:

- `DISCORD_TOKEN` — Discord bot token (Discord Developer Portal)
- `DISCORD_GUILD_ID` — ACG Discord server ID
- `ANTHROPIC_API_KEY` — or use the local Claude Code OAuth credential
- `CLAUDETOOLS_API_KEY` — JWT token for ClaudeTools API (not yet active — Phase 2)
- `VAULT_PATH` — path to SOPS vault on BEAST (`D:\vault`)
- `CLAUDETOOLS_ROOT` — `D:\claudetools`

Vault access (for remediation-tool): `msp-tools/computerguru-*.sops.yaml`, `clients/<slug>/m365*.sops.yaml`. Use the vault wrapper at `C:/Users/guru/ClaudeTools/.claude/scripts/vault.sh`.

---

## Active Work / Open Items

**Phase 2 — ClaudeTools API Integration (not started)**
- HTTP client with JWT auth (`bot/services/claudetools_api.py`)
- Implement `query_claudetools_api` tool executor
- User role mapping (Discord ID -> ClaudeTools user)
- Audit logging to `/api/security-incidents`

**Phase 3 — Remediation-Tool Integration (not started)**
- Bash subprocess runner (Git Bash on Windows)
- Implement `run_breach_check` and `run_tenant_sweep` executors
- Progress streaming to Discord
- Artifact upload

**Phase 4 — Polish (not started)**
- Confirmation buttons for remediation actions
- Rich embeds for structured data
- Slash commands (`/breach-check`, `/query`, `/status`)
- Ephemeral messages for sensitive data

---

## Key Events / History

| Date | Event |
|---|---|
| 2026-04-30 | Phase 1 MVP implemented on Mac (Mike). Project structure, discord.py handler, streaming Claude client, tool definitions (placeholder), README. Commit `777ad52`. |
| 2026-04-30 | Architecture decision: Python over Node.js; Claude Agent SDK instead of raw Anthropic SDK; thread-based conversations. |
| 2026-05-20 | On BEAST (Mike). Reviewed and corrected bot operating rules in `DISCORD_CLAUDE.md`: reversed no-interaction rule, added headless constraint, defined task loop. Service restarted twice; reconnected clean. No code changes — instructions only. |
| 2026-05-20 | Confirmed bot model is `claude-sonnet-4-6` (per `bot/config.py`). Phase 1.5 architecture confirmed: `ClaudeAgentManager` with persistent per-thread `ClaudeSDKClient`. |

---

## Anti-Patterns / Warnings

[WARNING] The system prompt (`DISCORD_CLAUDE.md`) is loaded ONCE at startup. Any edit is silently ineffective until `nssm restart ClaudeToolsDiscordBot` is run.

[WARNING] The bot is headless — no human is at the BEAST console. Never attempt: visible/interactive browser windows, OAuth flows that need a browser, Windows credential prompts, UAC dialogs, or any interactive GUI. These will hang the service forever. Credentials must come from the SOPS vault non-interactively.

[WARNING] Headless Chrome (`web-fetch-chrome.py`) is the ONLY sanctioned browser use — it never opens a visible window and uses an isolated profile. Do not drive the human's interactive Chrome session.

[WARNING] Unknown Discord users get read-only/informational responses only. Do not grant file writes, git ops, system changes, M365 actions, or vault access to unrecognized IDs.

[WARNING] The `AskUserQuestion` SDK tool does not render in Discord. Ask clarifying questions as plain text messages only.

[INFO] Phase 2 tool execution is still placeholder. `execute_tool()` in `message_handler.py` is a stub. The bot cannot currently query the ClaudeTools API or run remediation scripts programmatically — it relies on the Claude agent using native file/bash tools against the repo.

---

## Backlinks

- `wiki/systems/beast.md` [unverified — may not exist yet] — GURU-BEAST-ROG host spec
- `wiki/projects/gururmm.md` — related ACG internal project
- `.claude/CLAUDE.md` — system prompt source for the main ClaudeTools coordinator session
- `projects/discord-bot/DISCORD_CLAUDE.md` — bot's own operating instructions / system prompt
