Configuration Reference
Archon supports a layered configuration system with sensible defaults, optional YAML config files, and environment variable overrides. For a quick introduction, see Getting Started: Configuration.
Directory Structure
Section titled “Directory Structure”User-Level (~/.archon/)
Section titled “User-Level (~/.archon/)”~/.archon/├── workspaces/owner/repo/ # Project-centric layout│ ├── source/ # Clone or symlink -> local path│ ├── worktrees/ # Git worktrees for this project│ ├── artifacts/ # Workflow artifacts│ └── logs/ # Workflow execution logs├── workflows/ # Home-scoped workflows (source: 'global')├── commands/ # Home-scoped commands (source: 'global')├── scripts/ # Home-scoped scripts (runtime: bun | uv)├── archon.db # SQLite database (when DATABASE_URL not set)└── config.yaml # Global configuration (optional)Home-scoped workflows/, commands/, and scripts/ apply to every project on the machine. Repo-local files at <repoRoot>/.archon/{workflows,commands,scripts}/ override them by filename (or script name). Each directory supports one level of subfolders for grouping; deeper nesting is ignored. See Global Workflows for details and dotfiles-sync examples.
Repository-Level (.archon/)
Section titled “Repository-Level (.archon/)”.archon/├── commands/ # Custom commands│ └── plan.md├── workflows/ # Workflow definitions (YAML files)└── config.yaml # Repo-specific configuration (optional)Configuration Priority
Section titled “Configuration Priority”Settings are loaded in this order (later overrides earlier):
- Defaults - Sensible built-in defaults
- Global Config -
~/.archon/config.yaml - Repo Config -
.archon/config.yamlin repository - Environment Variables - Always highest priority
Global Configuration
Section titled “Global Configuration”Create ~/.archon/config.yaml for user-wide preferences:
# Default AI assistantdefaultAssistant: claude # must match a registered provider (e.g. claude, codex)
# Assistant defaultsassistants: claude: model: sonnet settingSources: # Which sources the Claude SDK loads (default: ['project', 'user']) - project # Project-level <cwd>/.claude/ (CLAUDE.md, skills, commands, agents) - user # User-level ~/.claude/ (CLAUDE.md, skills, commands, agents) # Optional: absolute path to the Claude Code executable. # Required in compiled Archon binaries when CLAUDE_BIN_PATH is not set. # Accepts the native binary (~/.local/bin/claude from the curl installer) # or the npm-installed cli.js. Source/dev mode auto-resolves. # claudeBinaryPath: /absolute/path/to/claude codex: model: gpt-5.3-codex modelReasoningEffort: medium webSearchMode: disabled additionalDirectories: - /absolute/path/to/other/repo # codexBinaryPath: /absolute/path/to/codex # Optional: Codex CLI path
# Streaming preferences per platformstreaming: telegram: stream # 'stream' or 'batch' discord: batch slack: batch github: batch
# Custom paths (usually not needed)paths: workspaces: ~/.archon/workspaces worktrees: ~/.archon/worktrees
# Concurrency limitsconcurrency: maxConversations: 10Repository Configuration
Section titled “Repository Configuration”Create .archon/config.yaml in any repository for project-specific settings:
# AI assistant for this project (used as default provider for workflows)assistant: claude
# Assistant defaults (override global)assistants: claude: model: sonnet settingSources: # Override global settingSources for this repo - project codex: model: gpt-5.3-codex webSearchMode: live
# Commands configurationcommands: folder: .archon/commands autoLoad: true
# Worktree settingsworktree: baseBranch: main # Optional: auto-detected from git when not set copyFiles: # Optional: Gitignored files/dirs to copy into new worktrees. # `.archon/` is always copied automatically — don't list it. - .env - .vscode # Copy entire directory - plans/ # Local plans not committed to the team repo initSubmodules: true # Optional: default true — auto-detects .gitmodules and runs # `git submodule update --init --recursive`. Set false to opt out. path: .worktrees # Optional: co-locate worktrees with the repo at # <repoRoot>/.worktrees/<branch> instead of under # ~/.archon/workspaces/<owner>/<repo>/worktrees/. # Must be relative; no absolute, no `..` segments.
# Documentation directorydocs: path: docs # Optional: default is docs/
# Defaults configurationdefaults: loadDefaultCommands: true # Load app's bundled default commands at runtime loadDefaultWorkflows: true # Load app's bundled default workflows at runtime
# Per-project environment variables for workflow execution (Claude SDK only)# Injected into the Claude subprocess env. Use the Web UI Settings panel for secrets.# env:# MY_API_KEY: value# CUSTOM_ENDPOINT: https://...Claude settingSources
Section titled “Claude settingSources”Controls which sources the Claude Agent SDK loads during sessions — CLAUDE.md, skills, commands, agents, and hooks:
| Value | Description |
|---|---|
project | Load project-level <cwd>/.claude/ (CLAUDE.md, skills, commands, agents) |
user | Load user-level ~/.claude/ (CLAUDE.md, skills, commands, agents) |
Default: ['project', 'user'] — both project-level and user-level sources are loaded.
To restrict a project to project-level resources only (e.g. CI, shared environments, or when ~/.claude/ contains personal commands you don’t want surfacing in workflows):
assistants: claude: settingSources: - projectSet in ~/.archon/config.yaml (global) or .archon/config.yaml (repo-specific).
Worktree file copying (worktree.copyFiles)
Section titled “Worktree file copying (worktree.copyFiles)”git worktree add only copies tracked files into a new worktree. Anything gitignored — secrets, local planning docs, agent reports, IDE settings, data fixtures — is absent by default. Archon’s worktree.copyFiles closes that gap: after the worktree is created, each listed path is copied from the canonical repo into the worktree via raw filesystem copy (not git), so gitignored content comes along for the ride.
Defaults — no config needed for the common case. .archon/ is always copied automatically. If you gitignore .archon/ (or it’s just not committed), your custom commands, workflows, and scripts still reach every worktree. You do not need to list .archon/ in copyFiles — it’s merged in for you.
Common entries:
worktree: copyFiles: - .env # local secrets - .vscode/ # editor settings - .claude/ # per-repo Claude Code config (agents, skills, hooks) - plans/ # working docs that aren't committed - reports/ # agent-generated markdown reports - data/fixtures/ # local-only test dataSemantics:
- Each entry is a path (file or directory) relative to the repo root — source and destination are always identical. No rename syntax.
- Missing files are silently skipped (
ENOENTat debug level), so you can list “optional” entries without bookkeeping. - Directories are copied recursively.
- Per-entry failures are isolated — one bad entry won’t abort the rest. Non-ENOENT failures (permissions, disk full) are surfaced as warnings on the environment.
- Path-traversal attempts (entries resolving outside the repo root, or absolute paths on a different drive) are rejected — the entry is logged and skipped.
Interaction with worktree.path: The copy step runs identically whether worktrees live under ~/.archon/workspaces/<owner>/<repo>/worktrees/ (default) or inside the repo at <repoRoot>/<worktree.path>/ (repo-local). Both layouts get the same gitignored-file treatment.
Defaults behavior: The app’s bundled default commands and workflows are loaded at runtime and merged with repo-specific ones. Repo commands/workflows override app defaults by name. Set defaults.loadDefaultCommands: false or defaults.loadDefaultWorkflows: false to disable runtime loading.
Submodule behavior: When a repo contains .gitmodules, submodules are initialized in new worktrees by default (git’s worktree add does not do this). The check is a cheap filesystem probe — repos without submodules pay zero cost. Submodule init failure throws a classified error (credentials, network, timeout) rather than silently producing a worktree with empty submodule directories. Set worktree.initSubmodules: false to opt out.
Base branch behavior: Before creating a worktree, the canonical workspace is synced to the latest code. Resolution order:
- If
worktree.baseBranchis set: Uses the configured branch. Fails with an error if the branch doesn’t exist on remote (no silent fallback). - If omitted: Auto-detects the default branch via
git remote show origin. Works without any config for standard repos. - If auto-detection fails and a workflow references
$BASE_BRANCH: Fails with an error explaining the resolution chain.
Docs path behavior: The docs.path setting controls where the $DOCS_DIR variable points. When not configured, $DOCS_DIR defaults to docs/. Unlike $BASE_BRANCH, this variable always has a safe default and never throws an error. Configure it when your documentation lives outside the standard docs/ directory (e.g., packages/docs-web/src/content/docs).
Worktree path behavior: By default, every repo’s worktrees live under ~/.archon/workspaces/<owner>/<repo>/worktrees/<branch> — outside the repo, invisible to the IDE. Set worktree.path to opt in to a repo-local layout instead: worktrees are created at <repoRoot>/<worktree.path>/<branch> so they show up in the file tree and editor workspace. A common choice is .worktrees. Because worktrees now live inside the repository tree, you should add the directory to your .gitignore (Archon does not modify user-owned files). The configured path must be relative to the repo root; absolute paths and paths containing .. segments fail loudly at worktree creation rather than silently falling back.
Environment Variables
Section titled “Environment Variables”Environment variables override all other configuration. They are organized by category below.
| Variable | Description | Default |
|---|---|---|
ARCHON_HOME | Base directory for all Archon-managed files. Ignored in Docker — the container always uses /.archon. | ~/.archon |
PORT | HTTP server listen port | 3090 (auto-allocated in worktrees) |
LOG_LEVEL | Logging verbosity (fatal, error, warn, info, debug, trace) | info |
BOT_DISPLAY_NAME | Bot name shown in batch-mode “starting” messages | Archon |
DEFAULT_AI_ASSISTANT | Default AI assistant (must match a registered provider) | claude |
MAX_CONCURRENT_CONVERSATIONS | Maximum concurrent AI conversations | 10 |
SESSION_RETENTION_DAYS | Delete inactive sessions older than N days | 30 |
ARCHON_SUPPRESS_NESTED_CLAUDE_WARNING | When set to 1, suppresses the stderr warning emitted when archon is run inside a Claude Code session | — |
ARCHON_VERBOSE_BOOT | When set to 1, prints [archon] loaded N keys from … lines to stderr at boot. Also enabled by LOG_LEVEL=debug or LOG_LEVEL=trace. Silent by default to avoid interleaving with interactive command output. | — |
AI Providers — Claude
Section titled “AI Providers — Claude”| Variable | Description | Default |
|---|---|---|
CLAUDE_USE_GLOBAL_AUTH | Use global auth from claude /login (true/false) | Auto-detect |
CLAUDE_CODE_OAUTH_TOKEN | Explicit OAuth token (alternative to global auth) | — |
CLAUDE_API_KEY | Explicit API key (alternative to global auth) | — |
TITLE_GENERATION_MODEL | Lightweight model for generating conversation titles | SDK default |
ARCHON_CLAUDE_FIRST_EVENT_TIMEOUT_MS | Timeout (ms) before Claude subprocess is considered hung (throws with diagnostic log) | 60000 |
When CLAUDE_USE_GLOBAL_AUTH is unset, Archon auto-detects: it uses explicit tokens if present, otherwise falls back to global auth.
AI Providers — Codex
Section titled “AI Providers — Codex”| Variable | Description | Default |
|---|---|---|
CODEX_ID_TOKEN | Codex ID token (from ~/.codex/auth.json) | — |
CODEX_ACCESS_TOKEN | Codex access token | — |
CODEX_REFRESH_TOKEN | Codex refresh token | — |
CODEX_ACCOUNT_ID | Codex account ID | — |
Platform Adapters — Slack
Section titled “Platform Adapters — Slack”| Variable | Description | Default |
|---|---|---|
SLACK_BOT_TOKEN | Slack bot token (xoxb-...) | — |
SLACK_APP_TOKEN | Slack app-level token for Socket Mode (xapp-...) | — |
SLACK_ALLOWED_USER_IDS | Comma-separated Slack user IDs for whitelist | Open access |
SLACK_STREAMING_MODE | Streaming mode (stream or batch) | batch |
Platform Adapters — Telegram
Section titled “Platform Adapters — Telegram”| Variable | Description | Default |
|---|---|---|
TELEGRAM_BOT_TOKEN | Telegram bot token from @BotFather | — |
TELEGRAM_ALLOWED_USER_IDS | Comma-separated Telegram user IDs for whitelist | Open access |
TELEGRAM_STREAMING_MODE | Streaming mode (stream or batch) | stream |
Platform Adapters — Discord
Section titled “Platform Adapters — Discord”| Variable | Description | Default |
|---|---|---|
DISCORD_BOT_TOKEN | Discord bot token from Developer Portal | — |
DISCORD_ALLOWED_USER_IDS | Comma-separated Discord user IDs for whitelist | Open access |
DISCORD_STREAMING_MODE | Streaming mode (stream or batch) | batch |
Platform Adapters — GitHub
Section titled “Platform Adapters — GitHub”| Variable | Description | Default |
|---|---|---|
GITHUB_TOKEN | GitHub personal access token (also used by gh CLI) | — |
GH_TOKEN | Alias for GITHUB_TOKEN (used by GitHub CLI) | — |
WEBHOOK_SECRET | HMAC SHA-256 secret for GitHub webhook signature verification | — |
GITHUB_ALLOWED_USERS | Comma-separated GitHub usernames for whitelist (case-insensitive) | Open access |
GITHUB_BOT_MENTION | @mention name the bot responds to in issues/PRs | Falls back to BOT_DISPLAY_NAME |
Platform Adapters — Gitea
Section titled “Platform Adapters — Gitea”| Variable | Description | Default |
|---|---|---|
GITEA_URL | Self-hosted Gitea instance URL (e.g. https://gitea.example.com) | — |
GITEA_TOKEN | Gitea personal access token or bot account token | — |
GITEA_WEBHOOK_SECRET | HMAC SHA-256 secret for Gitea webhook signature verification | — |
GITEA_ALLOWED_USERS | Comma-separated Gitea usernames for whitelist (case-insensitive) | Open access |
GITEA_BOT_MENTION | @mention name the bot responds to in issues/PRs | Falls back to BOT_DISPLAY_NAME |
Database
Section titled “Database”| Variable | Description | Default |
|---|---|---|
DATABASE_URL | PostgreSQL connection string (omit to use SQLite) | SQLite at ~/.archon/archon.db |
Web UI
Section titled “Web UI”| Variable | Description | Default |
|---|---|---|
WEB_UI_ORIGIN | CORS origin for API routes (restrict when exposing publicly) | * (allow all) |
WEB_UI_DEV | When set, skip serving static frontend (Vite dev server used instead) | — |
Worktree Management
Section titled “Worktree Management”| Variable | Description | Default |
|---|---|---|
STALE_THRESHOLD_DAYS | Days before an inactive worktree is considered stale | 14 |
MAX_WORKTREES_PER_CODEBASE | Max worktrees per codebase before auto-cleanup | 25 |
CLEANUP_INTERVAL_HOURS | How often the background cleanup service runs | 6 |
Docker / Deployment
Section titled “Docker / Deployment”| Variable | Description | Default |
|---|---|---|
ARCHON_DATA | Host path for Archon data (workspaces, worktrees, artifacts). Compose-only — read by docker-compose.yml to choose the bind-mount source for /.archon; not read by Archon source code. | Docker-managed volume |
ARCHON_USER_HOME | Host path for /home/appuser (Claude/Codex/Pi config, ~/.gitconfig, shell history). Compose-only — read by docker-compose.yml to choose the bind-mount source for /home/appuser; not read by Archon source code. Persisted by default to a Docker-managed volume so user state survives rebuilds. | Docker-managed volume |
DOMAIN | Public domain for Caddy reverse proxy (TLS auto-provisioned) | — |
CADDY_BASIC_AUTH | Caddy basicauth directive to protect Web UI and API | Disabled |
AUTH_USERNAME | Username for form-based auth (Caddy forward_auth) | — |
AUTH_PASSWORD_HASH | Bcrypt hash for form-based auth password (escape $ as $$ in Compose) | — |
COOKIE_SECRET | 64-hex-char secret for auth session cookies | — |
AUTH_SERVICE_PORT | Port for the auth service container | 9000 |
COOKIE_MAX_AGE | Auth cookie lifetime in seconds | 86400 |
.env File Locations
Section titled “.env File Locations”Archon keys env loading on directory ownership, not filename. .archon/ (at ~/ or <cwd>/) is archon-owned. Anything else is yours.
| Path | Stripped at boot? | Archon loads? | archon setup writes? |
|---|---|---|---|
<cwd>/.env | yes (safety guard) | never | never |
<cwd>/.archon/.env | no | yes (repo scope, overrides user scope) | yes iff --scope project |
~/.archon/.env | no | yes (user scope) | yes iff --scope home (default) |
Load order at boot (every entry point — CLI and server):
- Strip keys Bun auto-loaded from
<cwd>/.env,.env.local,.env.development,.env.production(prevents target-repo env from leaking into Archon). - Load
~/.archon/.envwithoverride: true(archon config wins over shell-inherited vars). - Load
<cwd>/.archon/.envwithoverride: true(repo scope wins over user scope).
Operator log lines (stderr, emitted only when there is something to report):
[archon] stripped 2 keys from /path/to/target-repo (.env, .env.local) to prevent target repo env from leaking into Archon processesThe [archon] loaded N keys from … lines are suppressed by default (they would otherwise interleave with archon setup/archon doctor checklist output). To enable them, set ARCHON_VERBOSE_BOOT=1 or LOG_LEVEL=debug before running:
[archon] loaded 3 keys from ~/.archon/.env[archon] loaded 2 keys from /path/to/target-repo/.archon/.env (repo scope, overrides user scope)Which file should I use?
~/.archon/.env— user-wide defaults (your personalSLACK_WEBHOOK,DATABASE_URL, etc.). Applies to every project.<cwd>/.archon/.env— per-project overrides. Different webhook per repo, different DB per environment, etc.<cwd>/.env— your app’s env file. Archon does not read this file; it strips the keys at boot so they do not leak into Archon’s process.
# User-widemkdir -p ~/.archoncp .env.example ~/.archon/.env
# Per-project override (e.g. a different Slack webhook for this repo)mkdir -p /path/to/repo/.archonprintf 'SLACK_WEBHOOK=https://hooks.slack.com/...\n' > /path/to/repo/.archon/.envDocker Configuration
Section titled “Docker Configuration”In Docker containers, paths are automatically set:
/.archon/├── workspaces/owner/repo/│ ├── source/│ ├── worktrees/│ ├── artifacts/│ └── logs/└── archon.dbEnvironment variables still work and override defaults.
Command Folder Detection
Section titled “Command Folder Detection”When cloning or switching repositories, Archon looks for commands in this priority order:
.archon/commands/- Always searched first- Configured folder from
commands.folderin.archon/config.yaml(if specified)
Example .archon/config.yaml:
commands: folder: .claude/commands/archon # Additional folder to search autoLoad: trueExamples
Section titled “Examples”Minimal Setup (Using Defaults)
Section titled “Minimal Setup (Using Defaults)”No configuration needed. Archon works out of the box with:
~/.archon/for all managed files- Claude as default AI assistant
- Platform-appropriate streaming modes
Custom AI Preference
Section titled “Custom AI Preference”defaultAssistant: codexProject-Specific Settings
Section titled “Project-Specific Settings”# .archon/config.yaml in your repoassistant: claude # Workflows inherit this provider unless they specify their owncommands: autoLoad: trueDocker with Custom Volume
Section titled “Docker with Custom Volume”docker run -v /my/data:/.archon ghcr.io/coleam00/archonStreaming Modes
Section titled “Streaming Modes”Each platform adapter supports two streaming modes, configured via environment variable or ~/.archon/config.yaml.
Stream Mode
Section titled “Stream Mode”Messages are sent in real-time as the AI generates responses.
TELEGRAM_STREAMING_MODE=streamSLACK_STREAMING_MODE=streamDISCORD_STREAMING_MODE=streamPros:
- Real-time feedback and progress indication
- More interactive and engaging
- See AI reasoning as it works
Cons:
- More API calls to platform
- May hit rate limits with very long responses
- Creates many messages/comments
Best for: Interactive chat platforms (Telegram)
Batch Mode
Section titled “Batch Mode”Only the final summary message is sent after AI completes processing.
TELEGRAM_STREAMING_MODE=batchSLACK_STREAMING_MODE=batchDISCORD_STREAMING_MODE=batchPros:
- Single coherent message/comment
- Fewer API calls
- No spam or clutter
Cons:
- No progress indication during processing
- Longer wait for first response
- Can’t see intermediate steps
Best for: Issue trackers and async platforms (GitHub)
Platform Defaults
Section titled “Platform Defaults”| Platform | Default Mode |
|---|---|
| Telegram | stream |
| Discord | batch |
| Slack | batch |
| GitHub | batch |
| Web UI | SSE streaming (always real-time, not configurable) |
Concurrency Settings
Section titled “Concurrency Settings”Control how many conversations the system processes simultaneously:
MAX_CONCURRENT_CONVERSATIONS=10 # Default: 10How it works:
- Conversations are processed with a lock manager
- If the max concurrent limit is reached, new messages are queued
- Prevents resource exhaustion and API rate limits
- Each conversation maintains its own independent context
Tuning guidance:
| Resources | Recommended Setting |
|---|---|
| Low resources | 3-5 |
| Standard | 10 (default) |
| High resources | 20-30 (monitor API limits) |
Health Check Endpoints
Section titled “Health Check Endpoints”The application exposes health check endpoints for monitoring:
Basic Health Check:
curl http://localhost:3090/healthReturns: {"status":"ok"}
Database Connectivity:
curl http://localhost:3090/health/dbReturns: {"status":"ok","database":"connected"}
Concurrency Status:
curl http://localhost:3090/health/concurrencyReturns: {"status":"ok","active":0,"queued":0,"maxConcurrent":10}
Use cases:
- Docker healthcheck configuration
- Load balancer health checks
- Monitoring and alerting systems (Prometheus, Datadog, etc.)
- CI/CD deployment verification
Troubleshooting
Section titled “Troubleshooting”Config Parse Errors
Section titled “Config Parse Errors”If your config file has invalid YAML syntax, you’ll see error messages like:
[Config] Failed to parse global config at ~/.archon/config.yaml: <error details>[Config] Using default configuration. Please fix the YAML syntax in your config file.Common YAML syntax issues:
- Incorrect indentation (use spaces, not tabs)
- Missing colons after keys
- Unquoted values with special characters
The application will continue running with default settings until the config file is fixed.