This guide walks you through installing and configuring copilot-bridge from scratch. If you prefer an interactive experience, run copilot-bridge init (or npm run init from source) after installing — it automates most of these steps.
| Requirement | Version | Notes |
|---|---|---|
| Node.js | 20+ | nodejs.org |
| GitHub Copilot CLI | latest | Installed automatically via npm install (bundled in @github/copilot-sdk) |
| Chat platform | — | At least one: Mattermost 7+ or Slack workspace with admin access to create apps/bots |
Tip
Need a Mattermost server? See mattermost.com/install for all options, including:
- Docker deployment — official guide
- DigitalOcean 1-Click — ready-made droplet
- Hostinger VPS — managed Docker hosting
- Docker Compose example — sample stack with PostgreSQL and Cloudflare Tunnel
Using Slack? You just need a Slack workspace where you can create apps. The init wizard generates a manifest URL that pre-fills all the required permissions.
The Copilot CLI needs a valid GitHub token. Any of these methods work (checked in priority order):
| Method | How | Best for |
|---|---|---|
| Environment variable | export COPILOT_GITHUB_TOKEN=ghp_... |
Automation, CI, server deployments |
| GitHub CLI | gh auth login |
Development machines with gh installed |
| Copilot CLI | copilot login |
Standalone CLI installs |
Environment variables: COPILOT_GITHUB_TOKEN > GH_TOKEN > GITHUB_TOKEN (first one found wins).
Note
Keyring prompts: copilot login stores credentials in the system keyring when available (macOS Keychain, GNOME Keyring, etc.), or falls back to ~/.copilot/config.json if no keyring is found. If the bridge triggers OS-level keyring unlock prompts at startup, set COPILOT_GITHUB_TOKEN directly to bypass keyring access.
Tip
BYOK (Bring Your Own Key): The SDK also supports using your own API keys from OpenAI, Anthropic, Azure AI Foundry, etc. — no Copilot subscription needed. See issue #48 for status.
npm install -g @chrisromp/copilot-bridgeAfter installing, use copilot-bridge <command> anywhere:
copilot-bridge init # Interactive setup wizard
copilot-bridge check # Validate configuration
copilot-bridge start # Start the bridge
copilot-bridge install-service # Install as system servicegit clone https://github.com/ChrisRomp/copilot-bridge.git
cd copilot-bridge
npm installWhen running from source, use npm run <command> (e.g., npm run init, npm run check).
copilot-bridge init
# Or from source: npm run initThe wizard walks you through:
- Prerequisite validation
- Platform selection (Mattermost, Slack, or both)
- Platform-specific connection setup (URLs, tokens, app manifests)
- User access control (allowlist setup — who can use each bot)
- Channel configuration (with per-channel trigger mode and threading)
- Default settings (model, trigger mode, threading)
- Config file generation (with backup if updating)
- Optional service installation
mkdir -p ~/.copilot-bridgeCopy the sample and edit it:
cp config.sample.json ~/.copilot-bridge/config.jsonMinimal config (single bot, DMs only):
{
"platforms": {
"mattermost": {
"url": "https://chat.example.com",
"bots": {
"copilot": { "token": "YOUR_BOT_TOKEN" }
}
}
},
"channels": []
}With an empty channels array, the bridge still works — it auto-discovers DM conversations.
Slack (single bot, DMs only):
{
"platforms": {
"slack": {
"bots": {
"copilot": {
"token": "xoxb-YOUR-BOT-TOKEN",
"appToken": "xapp-YOUR-APP-TOKEN"
}
}
}
},
"channels": []
}Slack uses Socket Mode (WebSocket) — no public URL or webhook endpoint needed.
Multi-bot with group channels:
{
"platforms": {
"mattermost": {
"url": "https://chat.example.com",
"bots": {
"copilot": { "token": "TOKEN_1", "admin": true },
"alice": { "token": "TOKEN_2", "agent": "alice-agent" }
}
}
},
"channels": [
{
"id": "CHANNEL_ID",
"name": "my-project",
"platform": "mattermost",
"bot": "copilot",
"workingDirectory": "/path/to/project"
}
],
"defaults": {
"model": "claude-sonnet-4.6",
"triggerMode": "mention",
"threadedReplies": true,
"verbose": false
}
}See Configuration for the full reference.
Mattermost
In Mattermost as an admin:
- Go to System Console → Integrations → Bot Accounts
- Click Add Bot Account
- Set username (e.g.,
copilot), display name, and description - Save and copy the bot token
- Paste the token into your
config.json
For group channels, add the bot to each channel:
- Open the channel → Channel Settings → Members → Add Members → search for the bot
Slack
The easiest way is to use copilot-bridge init — it generates a manifest URL that pre-fills all permissions. For manual setup:
- Go to api.slack.com/apps → Create New App → From a manifest
- Select your workspace and paste the manifest (or use
initto generate one) - Go to OAuth & Permissions → Install to Workspace → copy the Bot User OAuth Token (
xoxb-...) - Go to Basic Information → App-Level Tokens → Generate Token with
connections:writescope → copy the token (xapp-...) - Add both tokens to your
config.jsonunderplatforms.slack.bots
Required bot scopes: chat:write, channels:history, channels:read, groups:history, groups:read, im:history, im:read, im:write, files:read, files:write, reactions:read, reactions:write, users:read
To enable DMs, go to App Home and check Allow users to send Slash commands and messages from the messages tab.
Note
DMs don't require any channel setup — just message the bot directly.
For group channels, you need the platform-specific channel ID:
- Mattermost: Open the channel → click the channel name → View Info → copy the ID field
- Slack: Right-click the channel name → View channel details → copy the Channel ID at the bottom
copilot-bridge check
# Or from source: npm run checkThis verifies everything end-to-end:
🔍 copilot-bridge check
Prerequisites
✅ Node.js v22.0.0
✅ GitHub Copilot CLI (v1.0.2)
✅ GitHub authenticated (via gh CLI)
Configuration
✅ Config: ~/.copilot-bridge/config.json
✅ Config structure valid
Platforms
✅ Mattermost: https://chat.example.com (reachable)
✅ Bot "copilot" (token valid, admin)
Channels (from config)
✅ Channel "my-project" (accessible)
...
All checks passed!
copilot-bridge startnpm run devThis starts in watch mode — restarts automatically when source files change. You'll see logs in the terminal.
npm run build
npm startThe bridge should run persistently so it's always available in chat.
copilot-bridge install-service
# Or from source: npm run install-serviceThis detects your OS, generates the correct service file with your local paths, and installs it:
- macOS: installs a launchd plist to
~/Library/LaunchAgents/(no sudo needed) - Linux: installs a systemd unit to
/etc/systemd/system/(prompts for sudo)
On Linux, build first since systemd runs the compiled output:
npm run build
npm run install-serviceAfter installing, management commands are printed to the terminal.
To remove the service:
copilot-bridge uninstall-service
# Or from source: npm run uninstall-serviceNote
The manual steps below reference template files in the scripts/ directory. If you installed via npm, these are at $(npm root -g)/@chrisromp/copilot-bridge/scripts/. The automated copilot-bridge install-service command is recommended instead.
macOS (launchd) — manual steps
cp scripts/com.copilot-bridge.plist ~/Library/LaunchAgents/Edit the plist to update paths:
WorkingDirectory→ your copilot-bridge clone pathHOME→ your home directoryPATH→ ensure it includes your Node.js install location
Then load it:
launchctl load ~/Library/LaunchAgents/com.copilot-bridge.plistManagement:
launchctl list com.copilot-bridge # status
launchctl kickstart -k gui/$(id -u)/com.copilot-bridge # restart
tail -f ~/.copilot-bridge/copilot-bridge.log # logs[!WARNING] Never use
launchctl unloadto restart — if the bridge is running your session,unloadkills it and the subsequentloadnever executes.
Linux (systemd) — manual steps
# Build first
npm run build
# Install the service
sudo cp scripts/copilot-bridge.service /etc/systemd/system/Edit /etc/systemd/system/copilot-bridge.service:
ExecStart→ path tonpx tsxand yourdist/index.jsWorkingDirectory→ your copilot-bridge clone path- Change
User=usernameto your service account user HOME→ that user's home directory
Then enable and start:
sudo systemctl daemon-reload
sudo systemctl enable --now copilot-bridgeManagement:
sudo systemctl status copilot-bridge # status
sudo journalctl -u copilot-bridge -f # logs
sudo systemctl restart copilot-bridge # restart[!TIP] Let Copilot help with service setup. The paths in service files are environment-specific. If you have the Copilot CLI installed, ask it:
Help me configure the copilot-bridge systemd service file at /etc/systemd/system/copilot-bridge.service. My copilot-bridge is cloned at /path/to/copilot-bridge, Node.js is at $(which node), and it should run as my user.
When the bridge starts for the first time:
- Config loaded from
~/.copilot-bridge/config.json - SQLite database created at
~/.copilot-bridge/state.db - Workspaces initialized at
~/.copilot-bridge/workspaces/<botname>/with files generated from templates:AGENTS.md— system prompt defining the bot's role, tools, and constraints. Admin bots get an admin-specific template with bridge management capabilities; regular bots get a sandboxed template. Customize this file to shape your bot's behavior.MEMORY.md— persistent memory file the bot can read/write across sessions- These files are only created if they don't already exist — your customizations are safe across restarts
- Connected to configured platforms (Mattermost via WebSocket, Slack via Socket Mode)
- Listening for messages
The bridge is ready when you see the "listening for messages" log.
After first run, your ~/.copilot-bridge/ directory looks like this:
~/.copilot-bridge/
├── config.json # Bridge configuration
├── state.db # SQLite database (sessions, prefs, permissions)
└── workspaces/
├── copilot/ # One directory per bot
│ ├── AGENTS.md # System prompt (from templates/admin/ or templates/agents/)
│ └── MEMORY.md # Persistent memory file
├── alice/
│ ├── AGENTS.md
│ └── MEMORY.md
└── ...
The AGENTS.md and MEMORY.md files are generated from the templates in the repo's templates/ directory — admin bots use templates/admin/, regular bots use templates/agents/. Once created, they're yours to customize; the bridge won't overwrite them.
- Customize your bot: Edit
~/.copilot-bridge/workspaces/<botname>/AGENTS.mdto define the bot's personality and capabilities - Add MCP servers: Configure external tools in
~/.copilot/mcp-config.json(user-level, shared with Copilot CLI) - Set up permissions: Use the
/autopilotcommand in chat, or configurepermissionsinconfig.json - Explore commands: Type
/helpin chat to see all available slash commands
See the full configuration reference and architecture overview for deeper details.
| Issue | Likely Cause | Fix |
|---|---|---|
| "Config file not found" | Missing config | Run copilot-bridge init or copy config.sample.json to ~/.copilot-bridge/config.json |
better-sqlite3 fails during npm install |
Missing native build tools | sudo apt-get install -y python3-full build-essential (Linux) |
| Bot doesn't respond | Token invalid or bot not in channel | Run copilot-bridge check to diagnose |
| "WebSocket closed" (Mattermost) | Bad URL or token | Verify URL and token in config |
| "Socket Mode" errors (Slack) | Invalid app token | Verify appToken starts with xapp- and has connections:write scope |
| Can't DM the Slack bot | Messages tab not enabled | In Slack app settings → App Home → enable "Allow users to send messages" |
| Copilot errors on first message | CLI not authenticated | Set COPILOT_GITHUB_TOKEN or run gh auth login |
| Service won't start | Wrong paths in service file | Check WorkingDirectory and ExecStart paths |
| Permission denied on files | Agent working outside workspace | Grant access via allowPaths in config or admin grant_path_access tool |
Run copilot-bridge check (or npm run check from source) at any time to validate your entire setup.