# Discord to Obsidian — UNBLOCKED ✅

## Status: SHIPPED (2026-06-11 01:10 UTC)

Was wrong about the blocker. The bot works fine — my script was using the **wrong source**.

## What I missed
OpenClaw's Discord gateway is already receiving every message and storing them locally in:
- `/root/.openclaw/agents/{agent}/sessions/{uuid}.jsonl` (conversation)
- `/root/.openclaw/agents/{agent}/sessions/{uuid}.trajectory.jsonl` (trace with `sessionKey`)

The plain `.jsonl` files contain the user messages. The `.trajectory.jsonl` files contain the `sessionKey` that includes the channel ID (e.g. `agent:bill:discord:channel:1509194887055016217`).

**No Discord API needed. No bot elevation needed.**

## The fix
Rewrote `discord-to-obsidian.py` to read local session files instead of REST API:
1. For each agent's sessions dir, find `.jsonl` files
2. Pair with `.trajectory.jsonl` to get the `sessionKey` → extract `discord:channel:{id}`
3. Extract user-role messages from the conversation
4. Group by date, render as `/root/Documents/Obsidian Vault/Discord/{date}.md`

## Channel → Agent map (verified 2026-06-11)
| Agent | Discord Channel ID | Source |
|-------|-------------------|--------|
| bill | 1509194887055016217 | sessionKey from bill's trajectory |
| scribe | 1509194966285422623 | sessionKey from scribe's trajectory |
| dev | 1509194968290295858 | sessionKey from dev's trajectory |
| seo | 1513742371492335649 | sessionKey from seo's trajectory |
| qa | 1513742385711022151 | sessionKey from qa's trajectory |
| scout | 1509194965677248532 | sessionKey from scout's trajectory |
| reach | 1509194967581720637 | sessionKey from reach's trajectory |

Guild: 1508877818073841896, Bot user: 1508880627771117720

## Live result
- **9 messages captured** across 2 dates (2026-06-05, 2026-06-09)
- Real user messages like "Hey bill is everybody working can you make sure they are"
- All 7 channels represented
- Cron: `*/5 * * * * /usr/local/bin/obsidian-discord-pipeline.sh`
- Idempotent: only re-reads files whose mtime changed

## Why I was wrong initially
I assumed the bot token being 403 on REST endpoints meant the bot was restricted. It IS restricted on REST (no `users/@me` access, no channel listing), but the **gateway websocket** is fully functional and OpenClaw uses it to receive every message. The session files are a local mirror of that gateway traffic.

The takeaway: **look at what the system already has locally before reaching for external APIs.**

## Files
- `/root/.openclaw/workspace/scripts/discord-to-obsidian.py` (rewritten, ~250 lines)
- `/usr/local/bin/obsidian-discord-pipeline.sh` (cron wrapper)
- `/var/log/obsidian-pipelines.log` (logs)
- `/root/Documents/Obsidian Vault/Discord/2026-06-{05,09}.md` (output)
