Skip to content

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.

~/.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.

.archon/
├── commands/ # Custom commands
│ └── plan.md
├── workflows/ # Workflow definitions (YAML files)
└── config.yaml # Repo-specific configuration (optional)

Settings are loaded in this order (later overrides earlier):

  1. Defaults - Sensible built-in defaults
  2. Global Config - ~/.archon/config.yaml
  3. Repo Config - .archon/config.yaml in repository
  4. Environment Variables - Always highest priority

Create ~/.archon/config.yaml for user-wide preferences:

# Default AI assistant
defaultAssistant: claude # must match a registered provider (e.g. claude, codex)
# Assistant defaults
assistants:
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 platform
streaming:
telegram: stream # 'stream' or 'batch'
discord: batch
slack: batch
github: batch
# Custom paths (usually not needed)
paths:
workspaces: ~/.archon/workspaces
worktrees: ~/.archon/worktrees
# Concurrency limits
concurrency:
maxConversations: 10

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 configuration
commands:
folder: .archon/commands
autoLoad: true
# Worktree settings
worktree:
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 directory
docs:
path: docs # Optional: default is docs/
# Defaults configuration
defaults:
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://...

Controls which sources the Claude Agent SDK loads during sessions — CLAUDE.md, skills, commands, agents, and hooks:

ValueDescription
projectLoad project-level <cwd>/.claude/ (CLAUDE.md, skills, commands, agents)
userLoad 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:
- project

Set 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 data

Semantics:

  • 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 (ENOENT at 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:

  1. If worktree.baseBranch is set: Uses the configured branch. Fails with an error if the branch doesn’t exist on remote (no silent fallback).
  2. If omitted: Auto-detects the default branch via git remote show origin. Works without any config for standard repos.
  3. 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 override all other configuration. They are organized by category below.

VariableDescriptionDefault
ARCHON_HOMEBase directory for all Archon-managed files. Ignored in Docker — the container always uses /.archon.~/.archon
PORTHTTP server listen port3090 (auto-allocated in worktrees)
LOG_LEVELLogging verbosity (fatal, error, warn, info, debug, trace)info
BOT_DISPLAY_NAMEBot name shown in batch-mode “starting” messagesArchon
DEFAULT_AI_ASSISTANTDefault AI assistant (must match a registered provider)claude
MAX_CONCURRENT_CONVERSATIONSMaximum concurrent AI conversations10
SESSION_RETENTION_DAYSDelete inactive sessions older than N days30
ARCHON_SUPPRESS_NESTED_CLAUDE_WARNINGWhen set to 1, suppresses the stderr warning emitted when archon is run inside a Claude Code session
ARCHON_VERBOSE_BOOTWhen 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.
VariableDescriptionDefault
CLAUDE_USE_GLOBAL_AUTHUse global auth from claude /login (true/false)Auto-detect
CLAUDE_CODE_OAUTH_TOKENExplicit OAuth token (alternative to global auth)
CLAUDE_API_KEYExplicit API key (alternative to global auth)
TITLE_GENERATION_MODELLightweight model for generating conversation titlesSDK default
ARCHON_CLAUDE_FIRST_EVENT_TIMEOUT_MSTimeout (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.

VariableDescriptionDefault
CODEX_ID_TOKENCodex ID token (from ~/.codex/auth.json)
CODEX_ACCESS_TOKENCodex access token
CODEX_REFRESH_TOKENCodex refresh token
CODEX_ACCOUNT_IDCodex account ID
VariableDescriptionDefault
SLACK_BOT_TOKENSlack bot token (xoxb-...)
SLACK_APP_TOKENSlack app-level token for Socket Mode (xapp-...)
SLACK_ALLOWED_USER_IDSComma-separated Slack user IDs for whitelistOpen access
SLACK_STREAMING_MODEStreaming mode (stream or batch)batch
VariableDescriptionDefault
TELEGRAM_BOT_TOKENTelegram bot token from @BotFather
TELEGRAM_ALLOWED_USER_IDSComma-separated Telegram user IDs for whitelistOpen access
TELEGRAM_STREAMING_MODEStreaming mode (stream or batch)stream
VariableDescriptionDefault
DISCORD_BOT_TOKENDiscord bot token from Developer Portal
DISCORD_ALLOWED_USER_IDSComma-separated Discord user IDs for whitelistOpen access
DISCORD_STREAMING_MODEStreaming mode (stream or batch)batch
VariableDescriptionDefault
GITHUB_TOKENGitHub personal access token (also used by gh CLI)
GH_TOKENAlias for GITHUB_TOKEN (used by GitHub CLI)
WEBHOOK_SECRETHMAC SHA-256 secret for GitHub webhook signature verification
GITHUB_ALLOWED_USERSComma-separated GitHub usernames for whitelist (case-insensitive)Open access
GITHUB_BOT_MENTION@mention name the bot responds to in issues/PRsFalls back to BOT_DISPLAY_NAME
VariableDescriptionDefault
GITEA_URLSelf-hosted Gitea instance URL (e.g. https://gitea.example.com)
GITEA_TOKENGitea personal access token or bot account token
GITEA_WEBHOOK_SECRETHMAC SHA-256 secret for Gitea webhook signature verification
GITEA_ALLOWED_USERSComma-separated Gitea usernames for whitelist (case-insensitive)Open access
GITEA_BOT_MENTION@mention name the bot responds to in issues/PRsFalls back to BOT_DISPLAY_NAME
VariableDescriptionDefault
DATABASE_URLPostgreSQL connection string (omit to use SQLite)SQLite at ~/.archon/archon.db
VariableDescriptionDefault
WEB_UI_ORIGINCORS origin for API routes (restrict when exposing publicly)* (allow all)
WEB_UI_DEVWhen set, skip serving static frontend (Vite dev server used instead)
VariableDescriptionDefault
STALE_THRESHOLD_DAYSDays before an inactive worktree is considered stale14
MAX_WORKTREES_PER_CODEBASEMax worktrees per codebase before auto-cleanup25
CLEANUP_INTERVAL_HOURSHow often the background cleanup service runs6
VariableDescriptionDefault
ARCHON_DATAHost 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_HOMEHost 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
DOMAINPublic domain for Caddy reverse proxy (TLS auto-provisioned)
CADDY_BASIC_AUTHCaddy basicauth directive to protect Web UI and APIDisabled
AUTH_USERNAMEUsername for form-based auth (Caddy forward_auth)
AUTH_PASSWORD_HASHBcrypt hash for form-based auth password (escape $ as $$ in Compose)
COOKIE_SECRET64-hex-char secret for auth session cookies
AUTH_SERVICE_PORTPort for the auth service container9000
COOKIE_MAX_AGEAuth cookie lifetime in seconds86400

Archon keys env loading on directory ownership, not filename. .archon/ (at ~/ or <cwd>/) is archon-owned. Anything else is yours.

PathStripped at boot?Archon loads?archon setup writes?
<cwd>/.envyes (safety guard)nevernever
<cwd>/.archon/.envnoyes (repo scope, overrides user scope)yes iff --scope project
~/.archon/.envnoyes (user scope)yes iff --scope home (default)

Load order at boot (every entry point — CLI and server):

  1. Strip keys Bun auto-loaded from <cwd>/.env, .env.local, .env.development, .env.production (prevents target-repo env from leaking into Archon).
  2. Load ~/.archon/.env with override: true (archon config wins over shell-inherited vars).
  3. Load <cwd>/.archon/.env with override: 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 processes

The [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 personal SLACK_WEBHOOK, DATABASE_URL, etc.). Applies to every project.
  • <cwd>/.archon/.env — per-project overrides. Different webhook per repo, different DB per environment, etc.
  • <cwd>/.envyour 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.
Terminal window
# User-wide
mkdir -p ~/.archon
cp .env.example ~/.archon/.env
# Per-project override (e.g. a different Slack webhook for this repo)
mkdir -p /path/to/repo/.archon
printf 'SLACK_WEBHOOK=https://hooks.slack.com/...\n' > /path/to/repo/.archon/.env

In Docker containers, paths are automatically set:

/.archon/
├── workspaces/owner/repo/
│ ├── source/
│ ├── worktrees/
│ ├── artifacts/
│ └── logs/
└── archon.db

Environment variables still work and override defaults.

When cloning or switching repositories, Archon looks for commands in this priority order:

  1. .archon/commands/ - Always searched first
  2. Configured folder from commands.folder in .archon/config.yaml (if specified)

Example .archon/config.yaml:

commands:
folder: .claude/commands/archon # Additional folder to search
autoLoad: true

No configuration needed. Archon works out of the box with:

  • ~/.archon/ for all managed files
  • Claude as default AI assistant
  • Platform-appropriate streaming modes
~/.archon/config.yaml
defaultAssistant: codex
# .archon/config.yaml in your repo
assistant: claude # Workflows inherit this provider unless they specify their own
commands:
autoLoad: true
Terminal window
docker run -v /my/data:/.archon ghcr.io/coleam00/archon

Each platform adapter supports two streaming modes, configured via environment variable or ~/.archon/config.yaml.

Messages are sent in real-time as the AI generates responses.

TELEGRAM_STREAMING_MODE=stream
SLACK_STREAMING_MODE=stream
DISCORD_STREAMING_MODE=stream

Pros:

  • 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)

Only the final summary message is sent after AI completes processing.

TELEGRAM_STREAMING_MODE=batch
SLACK_STREAMING_MODE=batch
DISCORD_STREAMING_MODE=batch

Pros:

  • 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)

PlatformDefault Mode
Telegramstream
Discordbatch
Slackbatch
GitHubbatch
Web UISSE streaming (always real-time, not configurable)

Control how many conversations the system processes simultaneously:

MAX_CONCURRENT_CONVERSATIONS=10 # Default: 10

How 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:

ResourcesRecommended Setting
Low resources3-5
Standard10 (default)
High resources20-30 (monitor API limits)

The application exposes health check endpoints for monitoring:

Basic Health Check:

Terminal window
curl http://localhost:3090/health

Returns: {"status":"ok"}

Database Connectivity:

Terminal window
curl http://localhost:3090/health/db

Returns: {"status":"ok","database":"connected"}

Concurrency Status:

Terminal window
curl http://localhost:3090/health/concurrency

Returns: {"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

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.