Skip to content

siisee11/discode

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

395 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Discode

Discode

English

Bridge AI agent CLIs to Discord for remote monitoring and control.

Derived from DoBuDevel/discord-agent-bridge. This project preserves original authorship and builds on top of the upstream work.

TypeScript Bun License: MIT Tests

Overview

Discoding - run AI coding CLIs locally and relay them to Discord.

I built this after experimenting with OpenClaw. Even with full system permissions, I realized I preferred conversational control over full autonomy.

Instead of building another dashboard, I wired my AI CLI to Discord.

Discode runs your AI agent in tmux and simply relays output to Discord - no wrappers, no hidden execution layers, no cloud dependency.

  • Local-first
  • Relay-only architecture
  • Persistent tmux sessions
  • Single daemon managing multiple projects

Discode Demo

Features

  • Multi-Agent Support: Works with Claude Code, Gemini CLI, and OpenCode
  • Auto-Discovery: Automatically detects installed AI agents on your system
  • Real-Time Streaming: Sends agent outputs to Discord/Slack through event hooks
  • Project Isolation: Each project gets a dedicated Discord channel
  • Single Daemon: One Discord bot connection manages all projects
  • Session Management: Persistent tmux sessions survive disconnections
  • Rich CLI: Intuitive commands for setup, control, and monitoring
  • Type-Safe: Written in TypeScript with dependency injection pattern
  • Well-Tested: 129 unit tests with Vitest

Supported Platforms

Platform Supported Notes
macOS Yes Developed and tested
Linux Expected Should work (tmux-based), not yet tested
Windows (WSL) Expected Should work with tmux installed in WSL, not yet tested
Windows (native) No tmux is not available natively

Prerequisites

  • Bun: Version 1.3 or higher
  • tmux: Version 3.0 or higher
    • Basic tmux proficiency (session/window/pane navigation, attach/detach) is recommended
  • Discord Bot: Create a bot following the Discord Bot Setup Guide
    • Required permissions: Send Messages, Manage Channels, Read Message History, Embed Links, Add Reactions
    • Required intents: Guilds, GuildMessages, MessageContent, GuildMessageReactions
  • Slack (optional): Use Slack instead of Discord by following the Slack Setup Guide
  • AI Agent: At least one of:

Installation

Global install (npm or Bun)

npm install -g @siisee11/discode
bun add -g @siisee11/discode

Binary install (no Bun/Node runtime required)

curl -fsSL https://discode.chat/install | bash

Fallback:

curl -fsSL https://raw.githubusercontent.com/siisee11/discode/main/install | bash

From source

git clone https://github.com/siisee11/discode.git
cd discode
bun install
bun run build

For local runtime switching and development workflows, see DEVELOPMENT.md.

Uninstall

discode uninstall

Full cleanup (remove config/state/logs and installed bridge plugins too):

discode uninstall --purge --yes

Quick Start

1. Setup Discord Bot

# One-time onboarding
discode onboard

The onboard command prompts for your bot token, auto-detects the Discord server ID, lets you choose a default AI CLI, asks whether to enable OpenCode allow permission mode, and asks for telemetry opt-in. You can verify or change settings later:

discode config --show              # View current configuration
discode config --server SERVER_ID  # Change server ID manually

Note: onboard is required for initial configuration — it auto-detects the server ID by connecting to Discord. The config command only updates individual values without auto-detection.

2. Start Working

cd ~/projects/my-app

# Just run new — that's it!
discode new

new handles everything automatically: detects installed agents, starts the daemon, creates a Discord channel, launches the agent in tmux, and attaches you to the session.

discode new claude        # Specify an agent explicitly

Your AI agent is now running in tmux, with output delivered to Discord/Slack in real time through hooks.

CLI Reference

Global Commands

onboard

One-time onboarding: prompts for bot token, connects to Discord to auto-detect your server, lets you choose your default AI CLI, configures OpenCode permission mode, and asks telemetry opt-in.

discode onboard
# Optional for non-interactive shells
discode onboard --token YOUR_BOT_TOKEN

The onboarding flow will:

  1. Save your bot token to ~/.discode/config.json
  2. Connect to Discord and detect which server(s) your bot is in
  3. If the bot is in multiple servers, prompt you to select one
  4. Let you choose a default AI CLI for discode new
  5. Ask whether to set OpenCode permission mode to allow
  6. Warn that non-allow mode may cause inconvenient approval prompts in Discord
  7. Ask whether to enable anonymous CLI telemetry (opt-in)

daemon <action>

Control the global daemon process.

discode daemon start    # Start daemon
discode daemon stop     # Stop daemon
discode daemon status   # Check daemon status

list

List all registered projects.

discode list

agents

List available AI agents detected on your system.

discode agents

tui

Open interactive terminal UI. Use /new inside the TUI to create a new agent session.

discode tui

config [options]

View or update global configuration.

discode config --show              # Show current configuration
discode config --token NEW_TOKEN   # Update bot token
discode config --server SERVER_ID  # Set Discord server ID manually
discode config --port 18470        # Set hook server port
discode config --telemetry on      # Enable anonymous CLI telemetry (opt-in)
discode config --telemetry-endpoint https://telemetry.discode.chat/v1/events

Project Commands

Run these commands from your project directory.

start [options]

Start the bridge server for registered projects.

discode start                        # Start all projects
discode start -p my-app             # Start a specific project
discode start -p my-app --attach    # Start and attach to tmux

stop [project]

Stop a project: kills tmux session, deletes Discord channel, and removes project state. Defaults to current directory name if project is not specified.

discode stop                # Stop current directory's project
discode stop my-app         # Stop a specific project
discode stop --keep-channel # Keep Discord channel (only kill tmux)

status

Show project status.

discode status

attach [project]

Attach to a project's tmux session. Defaults to current directory name if project is not specified.

discode attach              # Attach to current directory's project
discode attach my-app       # Attach to a specific project

Press Ctrl-b d to detach from tmux without stopping the agent.

new [agent] [options]

Quick start: start daemon, set up project if needed, and attach to tmux. Auto-detects installed agents and creates the Discord channel automatically.

discode new              # Auto-detect agent, setup & attach
discode new claude       # Use a specific agent
discode new --no-attach  # Start without attaching to tmux

Supported Agents

Agent Binary Auto-Detect Notes
Claude Code claude Yes Official Anthropic CLI
Gemini CLI gemini Yes Google Gemini CLI
OpenCode opencode Yes Open-source alternative

Note: Codex support is temporarily removed and will be restored once Codex provides hook support. Tracking discussion: openai/codex#2150

Agent Detection

The CLI automatically detects installed agents using command -v <binary>. Run discode agents to see available agents on your system.

Configuration

Global Config

Stored in ~/.discode/config.json:

{
  "token": "YOUR_BOT_TOKEN",
  "serverId": "YOUR_SERVER_ID",
  "hookServerPort": 18470,
  "telemetryEnabled": false
}
Key Required Description Default
token Yes Discord bot token. Set via discode onboard or config --token -
serverId Yes Discord server (guild) ID. Auto-detected by onboard, or set via config --server -
hookServerPort No Port for the hook server 18470
defaultAgentCli No Default AI CLI used by discode new when agent is omitted First installed CLI
telemetryEnabled No Opt-in flag for anonymous CLI telemetry false
telemetryEndpoint No HTTP endpoint for telemetry proxy (recommended: Cloudflare Worker) https://telemetry.discode.chat/v1/events
telemetryInstallId No Anonymous per-install random ID used as GA client ID Auto-generated on opt-in
discode config --show               # View current config
discode config --token NEW_TOKEN     # Update bot token
discode config --server SERVER_ID    # Set server ID manually
discode config --port 18470          # Set hook server port
discode config --telemetry on        # Enable anonymous telemetry
discode config --telemetry-endpoint https://telemetry.discode.chat/v1/events

Project State

Project state is stored in ~/.discode/state.json and managed automatically.

Environment Variables

Config values can be overridden with environment variables:

Variable Required Description Default
DISCORD_BOT_TOKEN Yes (if not in config.json) Discord bot token -
DISCORD_GUILD_ID Yes (if not in config.json) Discord server ID -
DISCORD_CHANNEL_ID No Override default channel Auto-created per project
TMUX_SESSION_PREFIX No Prefix for tmux session names ``
TMUX_SHARED_SESSION_NAME No Shared tmux session name (without prefix) bridge
DISCODE_DEFAULT_AGENT_CLI No Default AI CLI used by discode new when agent is omitted First installed CLI
HOOK_SERVER_PORT No Port for the hook server 18470
DISCODE_TELEMETRY_ENABLED No Enable telemetry without writing config (true/false) false
DISCODE_TELEMETRY_ENDPOINT No Telemetry proxy endpoint URL -
DISCODE_TELEMETRY_INSTALL_ID No Override anonymous install ID -
DISCORD_BOT_TOKEN=token discode daemon start
DISCORD_GUILD_ID=server_id discode new

Telemetry Proxy (GA4)

Deploy Cloudflare Worker proxy:

npm run telemetry:deploy
npm run telemetry:secret

CLI telemetry defaults to https://telemetry.discode.chat/v1/events. To override it with your own deployed Worker URL:

discode config --telemetry-endpoint https://discode-telemetry-proxy.<your-subdomain>.workers.dev
discode config --telemetry on

Worker source: workers/telemetry-proxy

Development

Architecture overview: ARCHITECTURE.md Module boundaries: docs/MODULE_BOUNDARIES.md Documentation maps: docs/DESIGN.md, docs/PRODUCT_SENSE.md, docs/PLANS.md

Building

bun install
bun run build          # Compile TypeScript
bun run dev            # Dev mode

Release Packaging (prebuilt binaries)

npm run build:release              # Build CLI/daemon/sidecar/runtime-client binaries + npm meta package
npm run build:release:binaries:single  # Build only current OS/arch binary
npm run pack:release               # Create npm tarballs in dist/release

Testing

bun test              # Run all tests
bun run test:watch    # Watch mode
bun run test:coverage # Coverage report

Test suite includes 129 tests covering:

  • Agent adapters
  • State management
  • Discord client
  • Hook-based event delivery
  • CLI commands
  • Storage and execution mocks

Project Structure

discode/
├── bin/                  # CLI entry point (discode)
├── src/
│   ├── agents/           # Agent adapters (Claude, Gemini, OpenCode)
│   ├── capture/          # shared message parsing utilities
│   ├── config/           # Configuration management
│   ├── discord/          # Discord client and message handlers
│   ├── infra/            # Infrastructure (storage, shell, environment)
│   ├── state/            # Project state management
│   ├── tmux/             # tmux session management
│   └── types/            # TypeScript interfaces
├── tests/                # Vitest test suite
├── package.json
└── tsconfig.json

Dependency Injection

The codebase uses constructor injection with interfaces for testability:

// Interfaces
interface IStorage { readFile, writeFile, exists, unlink, mkdirp, chmod }
interface ICommandExecutor { exec, execVoid }
interface IEnvironment { get, homedir, platform }

// Usage
class DaemonManager {
  constructor(
    private storage: IStorage = new FileStorage(),
    private executor: ICommandExecutor = new ShellCommandExecutor()
  ) {}
}

// Testing
const mockStorage = new MockStorage();
const daemon = new DaemonManager(mockStorage);

Code Quality

  • TypeScript strict mode enabled
  • ESM modules with .js extensions in imports
  • Vitest with 129 passing tests
  • No unused locals/parameters (enforced by tsconfig.json)

Troubleshooting

Bot not connecting

  1. Verify token: discode config --show
  2. Check bot permissions in Discord Developer Portal
  3. Ensure MessageContent intent is enabled
  4. Restart daemon: discode daemon stop && discode daemon start

Agent not detected

  1. Run discode agents to see available agents
  2. Verify agent binary is in PATH: which claude
  3. Install missing agent and retry

tmux session issues

  1. Check session exists: tmux ls
  2. Kill stale session: tmux kill-session -t <session-name>
  3. Restart project: discode stop && discode start

No messages in Discord

  1. Check daemon status: discode daemon status
  2. Check daemon logs
  3. Check Discord channel permissions (bot needs Send Messages)

Tip: Keep running with lid closed (macOS)

If you want Discode to keep working when the laptop lid is closed on battery power, run:

sudo pmset -b disablesleep 1

To revert to normal sleep behavior:

sudo pmset -b disablesleep 0

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Guidelines

  • Add tests for new features
  • Maintain TypeScript strict mode compliance
  • Follow existing code style
  • Update documentation as needed

License

MIT License - see LICENSE file for details.

Acknowledgments

Support

About

messenger bridge for coding agents

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors