Documentation Index
Fetch the complete documentation index at: https://mintlify.com/remorses/kimaki/llms.txt
Use this file to discover all available pages before exploring further.
Channels and Threads
Kimaki uses Discord’s channel and thread features to organize AI coding sessions by project.
Channel Structure
Text Channels
Each project gets a text channel under the “Kimaki” category:
Discord Server
└── Kimaki (category)
├── #my-project
├── #website
└── #api-server
Channel names are derived from the project directory basename:
const channelName = path.basename(projectDirectory)
.toLowerCase()
.replace(/[^a-z0-9-]/g, '-')
.slice(0, 100)
Voice Channels (Optional)
Voice channels are created in a separate “Kimaki Audio” category:
Discord Server
├── Kimaki (category)
│ └── #my-project
└── Kimaki Audio (category)
└── 🔊 my-project
Voice channels enable real-time voice message transcription using Gemini API.
Channel Configuration
Database Storage
Channel configuration is stored in SQLite, not in the channel topic:
// channels table
{
channel_id: string // Discord channel ID
directory: string // Project directory path
channel_type: 'text' | 'voice'
app_id: string // Bot application ID
mention_mode: boolean // Require @mention to trigger
worktrees_enabled: boolean
verbosity: 'text-only' | 'text-and-essential-tools' | 'tools-and-text'
}
Creating Channels
Channels are created via:
- Setup wizard:
npx kimaki (interactive)
- CLI command:
kimaki project add /path/to/project
- Slash command:
/add-project in Discord
await createProjectChannels({
guild,
projectDirectory: '/path/to/project',
appId: 'bot-app-id',
enableVoiceChannels: true
})
Thread Lifecycle
Thread Creation
When a user sends a message in a project channel:
// discord-bot.ts: MessageCreate handler
1. Validate user permissions
2. Create thread from message:
- Name: first 80 chars of message
- Auto-archive: 1 day
3. Add user to thread (appears in sidebar)
4. Start OpenCode session
Thread Types
Standard Thread
User message → Create thread → Start session
Worktree Thread
If worktrees are enabled (channel setting or CLI flag):
1. Create thread with "⬦" prefix
2. Create git worktree:
- Branch: opencode/<sanitized-name>
- Directory: ../.worktrees/<name>
3. React with 🌳 emoji
4. Start session in worktree directory
Worktree status is tracked in SQLite:
// worktrees table
{
thread_id: string
worktree_name: string
worktree_directory: string
project_directory: string
status: 'pending' | 'ready' | 'error'
error_message?: string
}
Thread Mapping
Each thread maps to exactly one OpenCode session:
// thread_sessions table
{
thread_id: string // Discord thread ID
session_id: string // OpenCode session ID
}
This mapping persists across bot restarts. Replying to an old thread resumes the same session.
Message Flow in Threads
First Message (New Thread)
1. User sends message in #project channel
2. Bot creates thread from message
3. session-handler.ts:
- Creates new OpenCode session
- Stores thread → session mapping
- Starts AI response stream
Follow-up Messages (Existing Thread)
1. User sends message in thread
2. Bot looks up session ID for thread
3. If session found:
- Aborts current request (if running)
- Sends new prompt to existing session
4. If no session:
- Treats as notification thread
- Creates new session on reply
Message Queue
If a message arrives while AI is responding:
// Queue the message
const queue = messageQueue.get(threadId) || []
queue.push({
prompt,
userId,
username,
queuedAt: Date.now(),
images
})
// Abort current request
abortController.abort(new SessionAbortError({
reason: 'new-request'
}))
// New message processes immediately
// Queued messages auto-drain after completion
Thread-Level Features
Per-Thread Serial Processing
const threadMessageQueue = new Map<string, Promise<void>>()
// Chain messages to process in arrival order
const prev = threadMessageQueue.get(thread.id)
const task = (prev || Promise.resolve())
.then(() => processThreadMessage())
.finally(() => threadMessageQueue.delete(thread.id))
This ensures voice transcription + text messages are processed in Discord arrival order, not completion order.
Shell Commands
Messages starting with ! run shell commands instead of AI:
if (message.content?.startsWith('!')) {
const shellCmd = message.content.slice(1).trim()
const result = await runShellCommand({
command: shellCmd,
directory: worktreeDir || projectDir
})
await message.reply(result)
return
}
Example:
!git status
!npm run build
!ls -la
Mention Mode
Channels can require @mention to trigger sessions:
const mentionModeEnabled = await getChannelMentionMode(channelId)
if (mentionModeEnabled) {
const botMentioned = message.mentions.has(discordClient.user.id)
const isShellCommand = message.content?.startsWith('!')
if (!botMentioned && !isShellCommand) {
return // Ignore message
}
}
Useful for shared channels where the bot should only respond when explicitly called.
Worktree Management
Creating Worktrees
Worktrees are created automatically when:
- Channel has
worktrees_enabled setting
- CLI uses
--worktrees flag
- User runs
/new-worktree command
- CLI uses
--worktree <name> option
await createWorktreeWithSubmodules({
directory: projectDirectory,
name: worktreeName // e.g., "feature-auth"
})
// Creates:
// - Branch: opencode/feature-auth
// - Directory: ../.worktrees/feature-auth
// - Initializes submodules
Worktree Status Tracking
const worktreeInfo = await getThreadWorktree(threadId)
if (worktreeInfo?.status === 'pending') {
await message.reply('⏳ Worktree is still being created...')
return
}
if (worktreeInfo?.status === 'error') {
await message.reply(`❌ Worktree creation failed: ${error}`)
return
}
if (worktreeInfo?.status === 'ready') {
// Use worktree directory for session
sessionDirectory = worktreeInfo.worktree_directory
}
Merging Worktrees
Use /merge-worktree to merge back to main branch:
1. Verify thread has worktree
2. Switch to main/master branch
3. Merge worktree branch
4. Delete worktree branch
5. Remove worktree directory
Bot-Initiated Threads
Threads can be created programmatically:
# CLI command
kimaki send \
--channel 123456789 \
--prompt "Fix the bug in auth.ts" \
--worktree fix-auth
# GitHub Actions
env:
KIMAKI_BOT_TOKEN: ${{ secrets.KIMAKI_BOT_TOKEN }}
run: |
kimaki send \
--channel $CHANNEL_ID \
--prompt "Investigate issue ${{ github.event.issue.url }}"
The CLI creates a thread with a YAML marker in the embed footer:
start: true
worktree: "fix-auth"
username: "github-actions"
userId: "bot"
agent: "opencode"
model: "anthropic/claude-sonnet-4"
The bot’s ThreadCreate handler reads this marker and auto-starts the session.
Thread Cleanup
Threads auto-archive after 1 day of inactivity (Discord default). The session mapping persists in SQLite, so replying to an archived thread resumes the same session.
Manual cleanup:
// Delete thread → session mapping
DELETE FROM thread_sessions WHERE thread_id = ?
// Delete worktree mapping
DELETE FROM worktrees WHERE thread_id = ?
OpenCode sessions remain accessible in the OpenCode TUI even after thread deletion.
Best Practices
Dedicated Server
Create a dedicated Discord server for your agents:
- Keeps coding sessions separate from other servers
- Full control over permissions
- Clear organization with one server for all machines
Naming Conventions
- Text channels: Project name (e.g.,
#website, #api-server)
- Worktree threads: Prefixed with ”⬦” + feature name
- Voice threads: “Voice Message” + timestamp
Permission Management
Use the “Kimaki” role for team access:
// Create role in Discord
// Assign to trusted users
// Bot checks for:
- Server Owner
- Administrator
- Manage Server
- "Kimaki" role
Block access with “no-kimaki” role:
// Overrides all other permissions
// Implements "four-eyes principle"
// User must remove role to interact
Multi-Agent Orchestration
Allow other bots to trigger sessions:
// Assign "Kimaki" role to bot
// Bot messages will trigger sessions
// Enables orchestrator bots
By default, bot messages are ignored to prevent loops.
Troubleshooting
Thread Not Responding
- Check if channel has project directory configured
- Verify bot has permission to create threads
- Check
kimaki.log for errors
- Ensure OpenCode server is running for that directory
Worktree Creation Failed
- Check if project is a git repository
- Ensure no uncommitted changes in main branch
- Verify disk space for worktree directory
- Check git version (needs submodule support)
Session Mapping Lost
If thread → session mapping is lost (e.g., database deleted):
- New message in thread creates new session
- Old session remains in OpenCode TUI
- Use
/resume command to switch sessions