| src | ||
| .gitignore | ||
| .oxfmtrc.json | ||
| .oxlintrc.json | ||
| bun.lock | ||
| bunfig.toml | ||
| CLAUDE.md | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
CireilClaw
A Discord bot powered by a Large Language Model (LLM) that functions as a personal assistant. It provides conversational AI capabilities with tool-based interactions, allowing users to interact through Discord messages in both private DMs and guild channels.
Features
-
Discord Integration: Responds to mentions in configured guilds and DMs from the owner
-
LLM-powered Conversations: Uses
@mariozechner/pi-aifor flexible LLM provider/model support -
Slash Commands:
/clear- Clear current session history and opened files (owner only)/close <file>- Close an opened file (owner only, with autocomplete)
-
Tool-based Actions: The AI can execute various tools:
attachment- Fetch/view image attachments (png, jpg, jpeg, webp, ≤7MB)brave-search- Web search using Brave Search API (requires API key)close-file- Remove file from opened files listexec- Execute sandboxed commandslist-open-files- List all currently opened filesno-reply- End the turn without respondingopen-file- Open file to include in system prompt (with offset/limit support)react- Add emoji reactions to messagesreply- Send Discord messages (with markdown splitting for long content)weather- Get weather information via OpenWeather API (requires API key)write- Write files with diff-based verification (using diff-match-patch)
-
Session Management: Persistent conversation history per channel with SQLite storage
- Sliding window (~30 messages) with automatic squashing
- Thread context walking to collect reply chains
-
Sandboxed Execution: Uses Bubblewrap (bwrap) for secure command execution with configurable modes
-
Memory System: Uses personality/core files (SOUL.md, IDENTITY.md, USER.md, MEMORY.md)
-
Rate Limit Handling: User-friendly messages with server-respected retry delays
-
Markdown Splitting: Preserves code blocks when splitting messages >2000 characters
Requirements
- Linux - Uses Bubblewrap (
bwrap) for sandboxing- NixOS - Automatically resolves tool dependencies via Nix store
- Generic Linux - Uses system-installed tools from
/usr,/bin,/lib
- Bun - JavaScript runtime
- Node.js 20+ (via Bun)
- Bubblewrap - Required for sandboxing (
bwrapcommand must be available)
Installation
# Clone the repository
git clone https://git.cutie.zone/lyssieth/cireilclaw
cd cireilclaw
# Install dependencies
bun install
Configuration
Create a configuration directory at ~/.cireilclaw/ with the following structure:
~/.cireilclaw/
├── config.toml # Configuration file
├── CORE.md # Core instructions
├── memories/ # Memory files directory
│ ├── SOUL.md
│ ├── IDENTITY.md
│ ├── USER.md
│ └── MEMORY.md
├── home/ # Sandbox home directory
└── skills/ # Read-only skills directory
config.toml
[discord]
token = "your-bot-token"
ownerId = "your-user-id"
allowedGuilds = ["guild-id-1", "guild-id-2"]
applicationId = "your-application-id"
[llm]
apiBase = "https://api.example.com/v1"
apiKey = "optional-api-key"
modelName = "provider/model-name"
# Optional: provider (auto-detected from modelName)
# provider = "openai"
# Optional: additional model parameters
# parameters = { temperature = 0.7 }
[sandbox]
# Sandbox mode: "nix" (NixOS) or "generic-linux" (other distros)
# Default: "nix"
mode = "generic-linux"
# Optional integrations
[integrations.brave]
apiKey = "your-brave-api-key" # Enables brave-search tool
[integrations.openweather]
apiKey = "your-openweather-api-key" # Enables weather tool
Sandbox Modes:
nix- Usesnix-storeto resolve dependencies and creates isolated/binwith symlinks (NixOS only)generic-linux- Binds system directories (/usr,/lib, etc.) and uses system-installed tools
Note: NixOS mode provides better isolation by only binding exact paths needed, while generic-linux mode binds broader system directories for compatibility.
The sessions.db SQLite database will be created automatically on first run.
Usage
# Run the bot
bun run dev
# Or run directly
bun src/index.ts
Development
# Run linter
bun run lint
# Format code
bun run fmt
Sandboxed Commands
The bot can execute the following commands in a sandboxed environment:
Shell:
bash
File viewing/searching:
cat,rg,fd,ls,head,tail,wc
Text processing:
sort,uniq,cut,awk,sed,tr,diff
File operations:
mkdir,rm,mv,cp,touch,chmod
File info:
file,du
Network:
curl
System info:
date,time,env,uptime
Linting:
markdownlint-cli2
Runtime:
bun
Project Structure
src/
├── index.ts # Main entry point
├── util.ts # Utilities (sandbox path mapping, allowed commands)
├── commands/
│ ├── index.ts # Slash command registry
│ ├── clear.ts # /clear command handler
│ └── close.ts # /close command handler + autocomplete
├── config/
│ └── config.ts # Configuration loader (TOML-based)
├── core/
│ ├── log.ts # Pino logger setup
│ ├── event-bus.ts # Event-driven architecture
│ └── event-set.ts # Typed event definitions
└── llm/
├── engine.ts # LLM provider abstraction and tool definitions
├── harness.ts # Main orchestration (Discord, sessions, turns)
├── workspace.ts # Memory file reading
├── markdown.ts # Markdown splitting for Discord limits
├── sandbox.ts # Sandboxed command execution (Bubblewrap)
└── tools/
├── index.ts # Tool handler registry
├── types.ts # TypeScript types
├── attachment.ts
├── brave-search.ts
├── close-file.ts
├── exec.ts
├── list-open-files.ts
├── no-reply.ts
├── open-file.ts
├── react.ts
├── reply.ts
├── weather.ts
└── write.ts
Events
The event bus handles the following events:
session-message- New user message in a sessiontool-call- LLM requested a tool calltool-result- Tool execution completedllm-message- LLM streaming messagemessage-updated- Discord message was editedmessage-deleted- Discord message was deletedheartbeat- Periodic heartbeat (every ~8 hours)shutdown- Graceful shutdown
Dependencies
Runtime:
@mariozechner/pi-ai- LLM provider abstraction layeroceanic.js- Discord API librarypino+pino-princess- Loggingsmol-toml- TOML configuration parsingulid- Unique ID generationzod- Runtime type validation@sinclair/typebox- Tool parameter schemasdiff-match-patch-es- Diff generation for write toolopenweather-api-node- Weather data API client
Dev:
bun- JavaScript runtimeoxfmt- Code formatteroxlint- Fast linter (type-aware)typescript- TypeScript compiler
License
Apache-2.0