Configuration Reference
August 7, 2026 · View on GitHub
Configuration is stored at ~/.config/claude-threads/config.yaml.
Full Example
version: 1
workingDir: /home/user/repos/myproject
chrome: false
worktreeMode: prompt
respondOnlyWhenMentioned: false
userAttribution: true
platforms:
# Mattermost
- id: mattermost-main
type: mattermost
displayName: Main Team
url: https://chat.example.com
token: your-bot-token
channelId: abc123
botName: claude-code
allowedUsers: [alice, bob]
permissionMode: default
# Slack
- id: slack-eng
type: slack
displayName: Engineering
botToken: xoxb-your-bot-token
appToken: xapp-your-app-token
channelId: C0123456789
botName: claude
allowedUsers: [alice, bob]
permissionMode: default
Global Settings
| Setting | Description | Default |
|---|---|---|
version | Config schema version | 1 |
workingDir | Default working directory for Claude | Current directory |
chrome | Enable Chrome integration | false |
worktreeMode | Git worktree mode: off, prompt, or require | prompt |
respondOnlyWhenMentioned | Start new threads in quiet mode, where the bot only replies to messages that @mention it. Users can still toggle per-thread with !mentions. | false |
userAttribution | Prefix each user turn sent to Claude with the sender's [@username]: so Claude can tell who is speaking in multi-user threads. Only applied once a thread has more than one participant (after !invite); solo threads are left untouched. Set false to disable. Applies to new sessions. | true |
keepAlive | Prevent system sleep while sessions are active | true |
limits | Resource limits and timeouts (see below) | see below |
threadLogs | Thread logging (see below) | enabled |
stickyMessage | Sticky message text customization (see below) | none |
claudeAccounts | Multi-account pool (see below) | single-account mode |
Resource Limits (limits)
Every field is optional and falls back to the default. Older config.yaml files predate most of these, so leaving the block out is fine.
limits:
maxSessions: 5
sessionTimeoutMinutes: 30
sessionWarningMinutes: 5
cleanupIntervalMinutes: 60
maxWorktreeAgeHours: 24
cleanupWorktrees: true
permissionTimeoutSeconds: 120
flushDelayMs: 500
| Setting | Description | Default |
|---|---|---|
maxSessions | Maximum concurrent sessions | 5 |
sessionTimeoutMinutes | Idle timeout before a session auto-terminates | 30 |
sessionWarningMinutes | Warn the user this many minutes before timeout | 5 |
cleanupIntervalMinutes | How often the background cleanup runs | 60 |
maxWorktreeAgeHours | Clean up orphaned worktrees older than this | 24 |
cleanupWorktrees | Enable automatic cleanup of orphaned worktrees | true |
permissionTimeoutSeconds | How long a permission prompt waits for a reaction | 120 |
flushDelayMs | Delay before flushing batched output to the platform. Lower is snappier with more API calls; higher posts less often with coarser streaming. | 500 |
The legacy env vars MAX_SESSIONS and SESSION_TIMEOUT_MS still work as fallbacks when limits.maxSessions / limits.sessionTimeoutMinutes are unset. See Environment Variables.
Thread Logs (threadLogs)
threadLogs:
enabled: true
retentionDays: 30
| Setting | Description | Default |
|---|---|---|
enabled | Write per-thread session logs to disk | true |
retentionDays | Delete logs this many days after a session ends | 30 |
Sticky Message Text (stickyMessage)
Customize the text of the channel sticky message. This is distinct from the per-platform stickyMessage: <mode> visibility field documented under Platform Settings.
stickyMessage:
description: "Porygon — Mixpanel analytics bot"
footer: "• !stop — End session\n• !help — Show help"
| Setting | Description | Default |
|---|---|---|
description | Line shown below the sticky title | none |
footer | Content shown before the default "Mention me to start a session" line | none |
Platform Settings
Mattermost
| Setting | Required | Description |
|---|---|---|
id | Yes | Unique identifier for this platform |
type | Yes | Must be mattermost |
displayName | No | Human-readable name |
url | Yes | Mattermost server URL |
token | Yes | Bot access token |
channelId | Yes | Channel to listen in |
botName | No | Mention name (default: claude-code) |
allowedUsers | No | List of usernames who can use the bot |
permissionMode | No | How tool-use is gated: default / auto / bypass (default: default). See Permission Modes. |
skipPermissions | No | Deprecated. Use permissionMode. true maps to bypass, false to default. permissionMode wins when both are set. |
outboundFiles | No | send_file settings: { enabled, maxBytes } (defaults: enabled true, maxBytes 100 MB) |
sessionHeader | No | Per-thread header visibility: full (default) / minimal (status bar only) / hidden (no header post) |
stickyMessage | No | Channel sticky visibility: full (default) / minimal (status bar only) / hidden (no sticky, no bumping) |
Slack
| Setting | Required | Description |
|---|---|---|
id | Yes | Unique identifier for this platform |
type | Yes | Must be slack |
displayName | No | Human-readable name |
botToken | Yes | Bot User OAuth Token (xoxb-...) |
appToken | Yes | App-Level Token for Socket Mode (xapp-...) |
channelId | Yes | Channel ID (e.g., C0123456789) |
botName | No | Mention name (default: claude) |
allowedUsers | No | List of Slack usernames |
permissionMode | No | How tool-use is gated: default / auto / bypass (default: default). See Permission Modes. |
skipPermissions | No | Deprecated. Use permissionMode. true maps to bypass, false to default. permissionMode wins when both are set. |
outboundFiles | No | send_file settings: { enabled, maxBytes } (defaults: enabled true, maxBytes 100 MB) |
sessionHeader | No | Per-thread header visibility: full (default) / minimal (status bar only) / hidden (no header post) |
stickyMessage | No | Channel sticky visibility: full (default) / minimal (status bar only) / hidden (no sticky, no bumping) |
Permission Modes
The permissionMode field controls how the bot handles a session's tool-use requests.
| Mode | Behavior |
|---|---|
default | Every tool-use prompts for approval. The bot posts a permission request in the thread and the user reacts 👍 (allow once) / ✅ (allow all) / 👎 (deny). Safest option. |
auto | Claude's built-in classifier decides per tool: low-risk actions are auto-approved, high-risk ones still prompt. Requires Claude CLI 2.1.x. |
bypass | No prompts and no classifier. Every tool-use is allowed. Equivalent to --dangerously-skip-permissions. This is what the legacy skipPermissions: true maps to. |
A running session can switch mode at any time with !permissions <mode>; that override is not persisted across a bot restart.
Quieting the bot's overhead messages
Both the per-thread session header and the channel sticky message default to full for backward compatibility. To strip them down on a noisy channel, set the per-platform fields in config.yaml:
platforms:
- id: mattermost-main
type: mattermost
# ... credentials ...
sessionHeader: hidden # no header post, Claude's reply is the first message in the thread
stickyMessage: minimal # one-line status bar at the channel bottom, no sessions list
Note: the per-platform stickyMessage: <mode> field is distinct from the top-level Config.stickyMessage: { description, footer } block, which still customizes the full sticky for platforms not in hidden mode.
Claude Accounts (optional, multi-account mode)
By default every session spawns claude with the bot's own process.env, so they all share one subscription's token budget. Add a claudeAccounts block to spread load across multiple accounts. Omit the block entirely to stay in single-account mode (unchanged behavior).
Selection is usage-balanced (since v1.18.0). At each new-session start the bot probes every account's live limits with claude -p "/usage" --output-format json under that account's HOME (costs nothing, uses no turns) and routes the session to the account with the most subscription headroom, meaning the lowest max(session%, week%). Round-robin is only the fallback when probing yields no usable numbers (for example an API-key account, which reports no percentages). Accounts in rate-limit cooldown are skipped until their reset time. A resumed session always re-binds to the account its history lives under, cooling or not.
claudeAccounts:
# OAuth accounts (prepare each HOME first with `HOME=<path> claude login`)
- id: primary
home: /home/bot/.claude-accounts/primary
- id: backup
displayName: Backup (Pro)
home: /home/bot/.claude-accounts/backup
# API-key billed
- id: shared-api
apiKey: sk-ant-api03-xxxxxxxx...
| Setting | Required | Description |
|---|---|---|
id | Yes | Stable identifier used in logs, UI, and persisted session state |
home | One of | Alternate $HOME containing .claude/.credentials.json from a prior HOME=<path> claude login. For OAuth Pro/Max subscriptions. Session history also lives here, so resumed sessions pick the same account. |
apiKey | One of | Anthropic API key. Billed against that key; session history stays under the bot's default HOME. |
displayName | No | Human-readable label in UI (defaults to id) |
Exactly one of home or apiKey should be set per account. Persisted sessions record which account they ran under and resume on the same one.
Environment Variables
| Variable | Description | Default |
|---|---|---|
MAX_SESSIONS | Max concurrent sessions. Legacy fallback for limits.maxSessions. | 5 |
SESSION_TIMEOUT_MS | Idle timeout in milliseconds. Legacy fallback for limits.sessionTimeoutMinutes. | 1800000 (30 min) |
DEBUG | Enable verbose logging | - |
CLAUDE_PATH | Path to the claude binary. Overrides the PATH lookup and the common install locations. | claude (from PATH) |
DECISION_BRIDGE_TIMEOUT_MS | How long the MCP permission server waits for a plan approval or question answer routed through the decision bridge (the bot's reaction UI) before falling back to the legacy behavior (generic prompt for plans, auto-allow for questions). | 3600000 (1 h) |
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB | Strip ANTHROPIC_*, AWS_*_TOKEN, CLAUDE_CODE_OAUTH_TOKEN, GOOGLE_APPLICATION_CREDENTIALS, and similar from Bash, hook, and stdio-MCP subprocesses Claude spawns. Bot-specific vars like PLATFORM_TOKEN pass through. Also forces permission mode to default; --dangerously-skip-permissions will be rejected. Requires Claude CLI 2.1.83+. | - |
CLAUDE_THREADS_SESSIONS_PATH | Override the path to the persisted sessions file (default ~/.config/claude-threads/sessions.json). | - |
CLAUDE_THREADS_GITHUB_EMAILS_PATH | Override the path to the GitHub-emails store used for commit attribution. | - |
NO_UPDATE_NOTIFIER | Disable update checks | - |
Forwarded to Claude CLI automatically
The bot sets these tuning flags on the Claude child process when they aren't already present in the bot's environment:
| Variable | Effect | Requires |
|---|---|---|
MCP_CONNECTION_NONBLOCKING=true | Caps --mcp-config connects at 5s so a slow MCP server never delays startup | Claude CLI 2.1.89+ |
ENABLE_PROMPT_CACHING_1H=true | Opts into 1-hour prompt cache TTL, cutting re-caching cost on long-lived threads | Claude CLI 2.1.108+ |
MCP_TOOL_TIMEOUT=3600000 | Only set when the session has a decision bridge. Without it the CLI abandons a pending MCP permission call after ~2 minutes — far too short for plan approvals and question answers that wait on a human reaction. One hour matches the bridge's own DECISION_BRIDGE_TIMEOUT_MS default. Verified against CLI 2.1.223. | — |
Export any of them with a different value in the bot's own env to override.
CLI Options
CLI options override config file settings:
claude-threads [options]
Options:
--url <url> Mattermost server URL
--token <token> Bot token
--channel <id> Channel ID
--bot-name <name> Bot mention name (default: claude-code)
--allowed-users <list> Comma-separated allowed usernames
--permission-mode <mode> Permission mode: default | auto | bypass
--skip-permissions [deprecated] Alias for --permission-mode bypass
--no-skip-permissions [deprecated] Alias for --permission-mode default
--chrome Enable Chrome integration
--no-chrome Disable Chrome integration
--worktree-mode <mode> Git worktree mode: off, prompt, require
--session-header <mode> Per-thread header: full | minimal | hidden (overrides per-platform config)
--sticky-message <mode> Channel sticky: full | minimal | hidden (overrides per-platform config)
--setup Re-run setup wizard
--debug Enable debug logging
--version Show version
--help Show help
Session Persistence
Active sessions are saved to ~/.config/claude-threads/sessions.json and automatically resume after bot restarts.
Keep-Alive
The bot prevents system sleep while sessions are active (uses caffeinate on macOS, systemd-inhibit on Linux). Disable with --no-keep-alive or keepAlive: false in config.
claude-threads is maintained by Axolotl Systems. If it makes your team faster, consider sponsoring the project.