VoidBot is a Discord-native assistant for GameCult.
It can answer from archived Discord history, indexed GameCult repos, and Aetheria lore, then hand deeper work off to Codex when Discord stops being a sane place to do it. The current build already supports real Discord replies, semantic retrieval, source and lore indexing, and Codex handoff flows.
## What VoidBot Can Do
- answer owner questions through a Discord-safe `codex exec` lane
- use real MCP tools for archived Discord history, repo search, lore lookup, and owner notifications
The durable local state is split on purpose: Postgres holds jobs, audit events, and interaction memory, while `.voidbot/` keeps artifacts, archives, logs, and detached indexing status.
VoidBot now keeps queue state, audit events, and interaction memory in Postgres. `npm run stack:start` will launch the local Docker Postgres container automatically for the default local DSN, but you can start it yourself if you want the database up first:
```bash
docker compose -f infra/postgres/docker-compose.yml up -d
Qdrant is the recommended vector backend now. It avoids the pain that comes from stuffing everything into local JSON and then acting surprised when the file turns into a small moon.
Windows helper path:
```bash
npm run qdrant:setup
```
Normal day-to-day startup after that:
```bash
npm run qdrant:up
```
Or run Qdrant manually:
```powershell
docker pull qdrant/qdrant
docker volume create voidbot_qdrant_storage
docker run -p 6333:6333 -p 6334:6334 -v voidbot_qdrant_storage:/qdrant/storage qdrant/qdrant
If `DISCORD_APPLICATION_ID` and `DISCORD_GUILD_ID` are set, the bot registers slash commands into that guild on startup.
For `owner_codex`, the worker also needs a working local Codex CLI. If plain `codex` is not invokable from Node on your machine, point `CODEX_EXECUTABLE` and `CODEX_EXEC_ARGS` at the actual install.
## Example Questions
Things you can ask right now:
-`@Void what did we decide about the website roadmap last year?`
-`@Void summarize prior discussion about ship movement in nautical`
-`/ask provider:local_llm question: where is the MCP server registering search_sources?`
-`/ask provider:local_llm question: what does Aetheria lore say about FTL corporations?`
-`/search-history query: favorite algorithm`
## How The Main Flows Work
### Owner Discord flow
Default mode is `local_exec_owner_only`:
1. The owner uses `@Void ...` or `/ask`.
2. The bot queues an auto-approved owner job.
3. The worker runs `codex exec` in a read-only, Discord-safe lane.
4. Codex can call Void MCP tools such as `search_history`, `get_message_context`, `search_sources`, `get_source_context`, and `list_indexed_repos`.
5. If the answer is short and safe, the worker posts it back to Discord.
6. If the task needs broader tools, file edits, or a deeper investigation, the worker posts a handoff notice and writes a bundle under `.voidbot/artifacts/<job-id>/`.
`/queue-codex` skips the direct-reply attempt and forces the handoff path.
### Manual fallback
`manual_package` still exists when you want the stricter, explicit workflow:
1. Queue a job.
2. Approve it with `/approve-job`.
3. Let the worker write `request.md` and `request.json`.
4. Run the deeper work manually.
5. Approve any final public reply separately.
### Local Ollama flow
The `local_llm` provider uses Ollama chat completion plus a bounded host-managed read-only tool loop. It can use:
-`search_history`
-`get_message_context`
-`search_sources`
-`get_source_context`
-`list_indexed_repos`
Unlike the owner Codex lane, this is not MCP. It is a tighter host-controlled loop and deliberately excludes side-effecting tools.
Project, repo, and lore questions are now source-grounded by policy: if the prompt matches indexed repo/project cues, Void must touch the source-side lookup tools before answering confidently.
- matching channels are ingested on `MessageCreate`
- edits are re-upserted
- deletes remove indexed chunks
-`/reindex-channel` replays the most recent 100 messages from the current indexed channel
- exported logs can be backfilled later
Channel selection is controlled by:
-`INDEX_ALL_CHANNELS=true` or `INDEXED_CHANNEL_IDS=...`
-`EXCLUDED_CHANNEL_IDS`
-`EXCLUDED_CHANNEL_NAMES`
Backfill old exports with:
```bash
npm run rag:backfill -- --input /path/to/discord-logs
```
Useful flags:
-`--no-recursive`
-`--all-channels`
### Source repos and lore
Source indexing is incremental when you run it. The pipeline crawls the repo, compares the current documents to the archived source snapshot, deletes vectors for changed or removed source IDs, and upserts only the changed chunks.
Configure:
-`SOURCE_REPO_ROOT`
-`SOURCE_REPO_PATTERNS`
-`SOURCE_REPO_INCLUDE_PREFIXES`
-`RAG_SOURCE_ARCHIVE_PATH`
-`RAG_SOURCE_QUERY_INSTRUCTION`
Index everything that matches your repo patterns:
```bash
npm run rag:index-sources
```
Target specific repos:
```bash
npm run rag:index-sources -- --repo gamecult-site,AetheriaLore
```
Force a clean reindex for specific repos:
```bash
npm run rag:index-sources -- --repo AetheriaLore --force
That keeps `AetheriaLore` focused on the useful subtree instead of indexing every random byproduct in the repo.
### Git push hook for source indexing
If you want local pushes to kick off source reindexing automatically:
```bash
npm run rag:install-push-hooks
```
Git does not provide a client-side `post-push` hook, so VoidBot installs a chained `pre-push` hook instead. That hook returns quickly, launches a detached incremental reindex for the pushed repo, and preserves any existing `pre-push` hook by backing it up to `pre-push.voidbot.prev` and running it first.
That gives you a real polling path instead of an attached session silently rotting while you wonder whether it hung.
## Codex Integration
This repo includes a project-scoped `.codex/config.toml`, so Codex sessions opened in `E:\Projects\VoidBot` can use Void's MCP tools automatically.
If you want the same MCP server available from Codex outside this repo:
```bash
npm run codex:mcp:install
```
Current MCP tools:
-`search_history`
-`get_message_context`
-`search_sources`
-`get_source_context`
-`list_indexed_repos`
-`notify_owner`
Notes:
- read-only retrieval tools work in unattended `codex exec` runs
- side-effecting MCP tool calls still run into approval limits in unattended mode
- the owner Discord lane handles notifications through a host-mediated notification intent instead
To remove the shared Codex registration later:
```bash
npm run codex:mcp:remove
```
## Maintenance
If you change the embedding backend or model, rebuild the vector index from the archived corpora:
```bash
npm run rag:rebuild
```
If you still have an old mixed local JSON vector store from earlier builds, migrate it once before moving on:
```bash
npm run rag:migrate-vector-layout
```
## Commands
Current slash commands:
-`/ask`
-`/queue-codex`
-`/approve-job`
-`/reject-job`
-`/provider-status`
-`/search-history`
-`/summarize-channel`
-`/reindex-channel`
-`/set-style`
Some commands are full working paths. Some are still thin MVPs. They exist because the structure is real, not because the system is pretending to be finished.