
Archon
- 259 installs
- 23.1k repo stars
- Updated August 2, 2026
- coleam00/archon
Runs, creates, and configures Archon AI workflows that execute in isolated git worktrees for parallel development via the archon CLI.
About
Routes user intent to run Archon workflows, author workflow/command YAML, or manage Archon setup and config, delegating work to the archon CLI in isolated git worktrees. A developer uses it to run or build agentic coding workflows.
- Runs AI workflows in isolated git worktrees for parallelism
- Intent-routing table to setup, config, and authoring guides
Archon by the numbers
- 259 all-time installs (skills.sh)
- Ranked #2,471 of 16,556 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/coleam00/archon --skill archonAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 259 |
|---|---|
| repo stars | ★ 23.1k |
| Last updated | August 2, 2026 |
| Repository | coleam00/archon ↗ |
What it does
Runs, creates, and configures Archon AI workflows that execute in isolated git worktrees for parallel development via the archon CLI.
Files
Archon CLI Skill
Archon is a remote agentic coding platform that runs AI workflows in isolated git worktrees. This skill teaches you how to run workflows, create new workflows and commands, and manage Archon configuration.
Available Workflows (live)
!archon workflow list 2>&1 || echo "Archon CLI not installed. Read guides/setup.md to set it up."
Routing
Determine the user's intent and dispatch to the appropriate guide:
| Intent | Action |
|---|---|
| Setup / install / "how to use" | Read guides/setup.md — interactive setup wizard |
| Config / settings | Read guides/config.md — interactive config editor |
| Initialize .archon/ in a repo | Read references/repo-init.md |
| Create a workflow | Read references/workflow-dag.md — the complete workflow authoring guide |
| Quick parameter lookup — which field works on which node type | Read references/parameter-matrix.md — master matrix, intent-based lookup, silent-failure catalog |
| Advanced features (hooks/MCP/skills) | Read references/dag-advanced.md |
| Create a command file | Read references/authoring-commands.md |
| Variable substitution reference | Read references/variables.md |
| CLI command reference | Read references/cli-commands.md |
| Run an interactive workflow | Read references/interactive-workflows.md — transparent relay protocol |
| Workflow good practices / anti-patterns | Read references/good-practices.md — read before designing a non-trivial workflow |
| Troubleshoot a failing / stuck workflow | Read references/troubleshooting.md — log locations, common failure modes |
| Run a workflow (default) | Continue with "Running Workflows" below |
If the intent is ambiguous, ask the user to clarify.
---
Richer Context: archon.diy
The references in this skill are a distilled subset. The full, canonical docs live at [archon.diy](https://archon.diy) (Starlight site from packages/docs-web/). If the skill's reference pages don't cover what you need — an edge case, a worked example, a diagram, a deeper section on a feature — fetch the matching page from archon.diy.
When to reach for the live docs
- You need an end-to-end example that's longer than what the skill shows (e.g. full patterns for hooks, MCP config, sandbox schema, approval flows)
- You're explaining a concept to the user and want the most readable framing (the
book/series is written as a tutorial, not a reference) - You hit a feature the skill only mentions in passing (e.g.
agents:inline sub-agents, advanced Codex options, the full SyncHookJSONOutput schema) - The user asks "where is this documented?" — point them at the archon.diy URL, not a skill file path
URL map
| Topic | URL |
|---|---|
| Landing + install | archon.diy |
| Getting started (installation, quick start, concepts) | archon.diy/getting-started/ |
| The book (tutorial-style walkthrough) | archon.diy/book/ |
| Workflow authoring guide | archon.diy/guides/authoring-workflows/ |
| Command authoring guide | archon.diy/guides/authoring-commands/ |
| Node type guides | archon.diy/guides/loop-nodes/, /approval-nodes/, /script-nodes/ |
| Per-node features (Claude only) | /hooks/, /mcp-servers/, /skills/ |
| Global workflows/commands/scripts | archon.diy/guides/global-workflows/ |
| Variables reference | archon.diy/reference/variables/ |
| CLI reference | archon.diy/reference/cli/ |
Security model (env, sandbox, target-repo .env stripping) | archon.diy/reference/security/ |
| Architecture | archon.diy/reference/architecture/ |
Configuration (.archon/config.yaml full schema) | archon.diy/reference/configuration/ |
| Troubleshooting | archon.diy/reference/troubleshooting/ |
| Adapter setup (Slack/Telegram/GitHub/Web/Discord/Gitea/GitLab) | archon.diy/adapters/ |
| Deployment (Docker, cloud, Windows) | archon.diy/deployment/ |
URL shape is archon.diy/<section>/<page>/ — the paths mirror the filenames under packages/docs-web/src/content/docs/.
Precedence
This skill's reference pages are the primary source for routine workflow authoring, CLI use, and setup. Reach for archon.diy when the skill is incomplete for your case — don't go to the live docs first by default (skill refs load into context faster and are tuned for agents).
---
Running Workflows
Core Command
archon workflow run <workflow-name> --branch <branch-name> "<message>"CRITICAL RULES:
1. Always run in background — Archon workflows are long-running. Always invoke the Bash tool with run_in_background: true. Use /tasks or the TaskOutput tool to check on progress.
2. Always use worktree isolation — Use the --branch flag unless the user explicitly requests otherwise. This creates an isolated environment so Archon works without affecting the main branch.
3. One workflow per shell — Each workflow blocks its shell. Run multiple workflows as separate background tasks.
Isolation Modes
| Mode | Flag | When to Use |
|---|---|---|
| Worktree (Default) | --branch <name> | Always use this unless told otherwise |
| Custom start-point | --branch <name> --from <base> | Start from a specific branch |
| Direct checkout | --no-worktree | Only if user explicitly requests no isolation |
| Resume failed run | --resume | Resume from the last failure point |
Workflow Selection
Match the user's intent to a workflow from the live list above. Common patterns:
| User Intent | Typical Workflow | Branch Pattern |
|---|---|---|
| "Fix issue #X" / "Resolve bug" | archon-fix-github-issue | fix/issue-{N} |
| "Review PR #X" / "Full review" | archon-comprehensive-pr-review | review/pr-{N} |
| "Quick review PR #X" | archon-smart-pr-review | review/pr-{N} |
| "Validate PR #X" / "Check PR" | archon-validate-pr | review/pr-{N} |
| "Implement from plan" | archon-feature-development | feat/{name} |
| "Plan and implement feature" | archon-idea-to-pr | feat/{name} |
| "Execute plan file" | archon-plan-to-pr | feat/{name} |
| "Run ralph" / "Implement PRD" | archon-ralph-dag | feat/{name} |
| "Resolve conflicts" | archon-resolve-conflicts | resolve/pr-{N} |
| "Create issue" / "File a bug" | archon-create-issue | issue/{name} |
| "Review issue #X fully" | archon-issue-review-full | review/issue-{N} |
| "Refactor safely" | archon-refactor-safely | refactor/{name} |
| "Architecture review" | archon-architect | review/{name} |
| "PIV loop" / "guided dev" | archon-piv-loop ⚡ | piv/{name} |
| "Create a PRD" / "interactive PRD" | archon-interactive-prd ⚡ | prd/{name} |
| General / debugging | archon-assist | assist/{description} |
⚡ = Interactive workflow — requires the transparent relay protocol. Read references/interactive-workflows.md before running.
If no specific workflow matches, use archon-assist as the fallback. The live workflow list above is always authoritative — it may include workflows not in this table.
Multi-Issue Invocation
When the user mentions multiple issues, PRs, or tasks — run each as a separate background task:
# Each gets its own worktree — they won't conflict
archon workflow run archon-fix-github-issue --branch fix/issue-10 "Fix issue #10"
archon workflow run archon-fix-github-issue --branch fix/issue-11 "Fix issue #11"
archon workflow run archon-fix-github-issue --branch fix/issue-12 "Fix issue #12"Never combine multiple issues into a single command.
---
Other CLI Commands
archon workflow list # List all available workflows
archon workflow list --json # Machine-readable JSON
archon isolation list # Show active worktree environments
archon isolation cleanup # Remove stale worktrees (default: 7 days)
archon isolation cleanup --merged # Remove branches merged into main
archon complete <branch> # Complete branch lifecycle (remove worktree + branches)
archon version # Show version infoFor the full CLI reference with all flags: Read references/cli-commands.md
---
Authoring Quick Start
Archon uses a single workflow format: nodes (DAG). Workflows are YAML files in .archon/workflows/.
IMPORTANT: The examples below are starting points. Always design the workflow around what the user actually needs — the number of nodes, their types, dependencies, and configuration should match the user's requirements, not these templates.
Workflow Structure
name: my-workflow
description: What this workflow does
provider: claude # Optional: 'claude' or 'codex'
model: sonnet # Optional: model override
nodes:
- id: first-node
command: my-command # Loads .archon/commands/my-command.md
- id: second-node
prompt: "Use the output: $first-node.output"
depends_on: [first-node]Node Types
Each node has exactly ONE of: command, prompt, bash, script, loop, approval, or cancel.
Command node — runs a .archon/commands/*.md file:
- id: investigate
command: investigate-issuePrompt node — inline AI prompt:
- id: classify
prompt: "Classify this issue: $ARGUMENTS"
model: haiku
allowed_tools: []Bash node — shell script, no AI, stdout captured as output:
- id: fetch-data
bash: "gh issue view 42 --json title,body"
timeout: 15000Script node — TypeScript/JavaScript (via bun) or Python (via uv), no AI, stdout captured as output:
- id: transform
script: |
const raw = process.argv.slice(2).join(' ') || '{}';
console.log(JSON.stringify({ parsed: JSON.parse(raw) }));
runtime: bun # 'bun' (.ts/.js) or 'uv' (.py) — REQUIRED
timeout: 30000 # Optional, ms, default 120000
# Or reference a named script from .archon/scripts/ or ~/.archon/scripts/
- id: analyze
script: analyze-metrics # loads .archon/scripts/analyze-metrics.py
runtime: uv
deps: ["pandas>=2.0"] # Optional, uv only — 'uv run --with <dep>'Loop node — iterates AI prompt until completion:
- id: implement
loop:
prompt: "Implement next story. When done: <promise>COMPLETE</promise>"
until: COMPLETE
max_iterations: 10
fresh_context: true
until_bash: "bun run test" # Optional: exit 0 = doneApproval node — pauses the workflow for human review. Requires interactive: true at the workflow level for Web UI delivery:
interactive: true # workflow level — required for web UI
nodes:
- id: review-gate
approval:
message: "Review the plan above before proceeding."
capture_response: true # Optional: user's comment → $review-gate.output
on_reject: # Optional: AI rework on rejection instead of cancel
prompt: "Revise based on feedback: $REJECTION_REASON"
max_attempts: 3 # Range 1-10, default 3
depends_on: [plan]Cancel node — terminates the workflow with a reason. Typically gated with when::
- id: stop-if-unsafe
cancel: "Refusing to proceed: input flagged UNSAFE."
depends_on: [classify]
when: "$classify.output != 'SAFE'"For the full authoring guide with all fields, conditions, trigger rules, and patterns: Read references/workflow-dag.md
Creating a Command File
Commands are .md files in .archon/commands/ containing AI prompt templates:
---
description: What this command does
argument-hint: <expected arguments>
---
# My Command
User request: $ARGUMENTS
Workflow artifacts: $ARTIFACTS_DIR
[Instructions for the AI agent]For the full command authoring guide: Read references/authoring-commands.md
Key Variables
| Variable | Description |
|---|---|
$ARGUMENTS | User's input message |
$ARTIFACTS_DIR | Pre-created directory for workflow artifacts |
$BASE_BRANCH | Base branch (auto-detected from git) |
$WORKFLOW_ID | Unique workflow run ID |
$nodeId.output | Output from upstream node |
Full variable reference: Read references/variables.md
Advanced Features (Command/Prompt Nodes, Claude Only)
hooks (tool interception), mcp (external tool servers), skills (domain knowledge injection), output_format (structured JSON output), allowed_tools/denied_tools (tool restrictions).
For details: Read references/dag-advanced.md
Example Files
examples/dag-workflow.yaml— workflow with conditions, bash + script + loop nodes, structured outputexamples/command-template.md— Command file skeleton with all variables
---
Example Interactions
User: "Use Archon to fix issue #42"
archon workflow run archon-fix-github-issue --branch fix/issue-42 "Fix issue #42"User: "Have Archon review PR #15"
archon workflow run archon-comprehensive-pr-review --branch review/pr-15 "Review PR #15"User: "Create a workflow that reviews code and runs tests" → Read references/workflow-dag.md and create a workflow with parallel review nodes.
User: "Make a workflow with conditional routing" → Read references/workflow-dag.md and create nodes with when: conditions and output_format.
User: "Write a command file for investigating bugs" → Read references/authoring-commands.md and create an .md file in .archon/commands/.
User: "Set up Archon in this repo" → Read references/repo-init.md to create the .archon/ directory structure.
User: "Initialize .archon and create a custom workflow" → First read references/repo-init.md, then the appropriate workflow reference.
Command Name
Workflow ID: $WORKFLOW_ID
---
Phase 1: LOAD
Gather context and inputs for this command.
- User request: $ARGUMENTS
- Read any artifacts from previous steps:
$ARTIFACTS_DIR/ - Base branch: $BASE_BRANCH
PHASE_1_CHECKPOINT
- [ ] User request understood
- [ ] Prior artifacts loaded (if any)
- [ ] Codebase context gathered
Phase 2: EXECUTE
Do the main work of this command.
[Replace this section with specific instructions for what the AI should do. Be precise about which tools to use, what files to examine, and what actions to take.]
PHASE_2_CHECKPOINT
- [ ] Main work completed
- [ ] Changes validated (type-check, lint, tests as appropriate)
Phase 3: GENERATE
Write artifacts for downstream steps.
Write your output to $ARTIFACTS_DIR/output.md with:
- Summary of what was done
- Key decisions made
- Any issues encountered
PHASE_3_CHECKPOINT
- [ ] Artifact written to
$ARTIFACTS_DIR/output.md - [ ] Artifact contains actionable information for the next step
Phase 4: REPORT
Provide a concise summary to the user:
1. What was accomplished 2. Key findings or decisions 3. Any blockers or warnings 4. Next steps (if part of a multi-step workflow)
# Example: Workflow demonstrating multiple node types
#
# Demonstrates: bash nodes, script nodes (TypeScript via bun), structured output,
# when: conditions, trigger_rule, per-node model, context: fresh, loop nodes,
# and output substitution.
#
# IMPORTANT: This is a reference example. Design your actual workflow
# around the user's specific needs — the number of nodes, their types,
# dependencies, and configuration should match what the user requests.
#
# Run with:
# archon workflow run smart-issue-fix --branch fix/issue-42 "Fix issue #42"
name: smart-issue-fix
description: |
Classify a GitHub issue, then route to the appropriate handler.
Bugs get investigated; features get planned. Both paths merge at implementation.
provider: claude
nodes:
# ── BASH NODE: Shell script, no AI, stdout captured as output ──
- id: fetch-issue
bash: |
issue_num=$(echo "$ARGUMENTS" | grep -oE '/issues/[0-9]+' | grep -oE '[0-9]+' | head -1)
# Fallback: extract first number if no URL path found (e.g., "Fix issue #42")
if [ -z "$issue_num" ]; then
issue_num=$(echo "$ARGUMENTS" | grep -oE '[0-9]+' | head -1)
fi
if [ -n "$issue_num" ]; then
gh issue view "$issue_num" --json title,body,labels,comments
else
echo "No issue number found in: $ARGUMENTS"
exit 1
fi
timeout: 15000
- id: fetch-pr-template
bash: |
if [ -f .github/PULL_REQUEST_TEMPLATE.md ]; then
cat .github/PULL_REQUEST_TEMPLATE.md
else
echo "No PR template found"
fi
timeout: 5000
# ── SCRIPT NODE: TypeScript (bun runtime), no AI, stdout captured as output ──
# Deterministic parsing the shell would mangle — extracts labels cleanly as JSON.
#
# NOTE: `$fetch-issue.output` is substituted *raw* into the script body (no shell
# quoting — see reference/variables.md). JSON is valid JS expression syntax —
# assign directly without String.raw or JSON.parse. String.raw breaks if the
# output contains backticks (e.g. markdown code spans in AI-generated content).
- id: extract-labels
script: |
try {
const issue = $fetch-issue.output;
const labels = (issue.labels ?? []).map((l) => l.name);
console.log(JSON.stringify({ labels, count: labels.length }));
} catch {
console.log(JSON.stringify({ labels: [], count: 0 }));
}
runtime: bun
depends_on: [fetch-issue]
timeout: 10000
# ── PROMPT NODE: Inline AI prompt with structured output ──
- id: classify
prompt: |
Classify this GitHub issue:
$fetch-issue.output
Determine if this is a bug fix or a new feature.
depends_on: [fetch-issue]
model: haiku
allowed_tools: []
output_format:
type: object
properties:
issue_type:
type: string
enum: [bug, feature]
title:
type: string
severity:
type: string
enum: [low, medium, high, critical]
required: [issue_type, title]
# ── COMMAND NODE: Loads .archon/commands/<name>.md ──
- id: investigate
command: investigate-bug
depends_on: [classify]
when: "$classify.output.issue_type == 'bug'"
context: fresh
- id: plan
command: plan-feature
depends_on: [classify]
when: "$classify.output.issue_type == 'feature'"
context: fresh
# ── LOOP NODE: Iterates until completion or max iterations ──
- id: implement
depends_on: [investigate, plan]
trigger_rule: one_success
idle_timeout: 600000
loop:
prompt: |
You are implementing changes for: $classify.output.title
Read the investigation or plan artifacts from $ARTIFACTS_DIR.
Implement the next piece, validate with type-check and tests.
When all changes are complete and validated: <promise>DONE</promise>
until: DONE
max_iterations: 5
fresh_context: false
# ── Final node: create PR using template ──
- id: create-pr
prompt: |
Create a pull request for the changes.
Issue title: $classify.output.title
PR template: $fetch-pr-template.output
Implementation summary: $implement.output
Use `gh pr create` to create the PR. Link to the original issue.
depends_on: [implement, fetch-pr-template]
trigger_rule: none_failed_min_one_success
context: fresh
CLI Setup Guide
Steps to install and configure the Archon CLI. Always run these first.
1. Install Dependencies
cd <archon-repo> && bun installIf bun is not installed, direct the user to https://bun.sh and stop.
2. Link the CLI Globally
cd <archon-repo>/packages/cli && bun linkThis makes archon available as a global command from any directory.
3. Verify Installation
archon versionShould print the version number. If it fails, re-run step 2 and check that Bun's global bin directory is in $PATH.
4. Authenticate Claude
Check if Claude Code is installed:
which claudeIf not installed, direct the user to install Claude Code and stop.
If installed but not authenticated, run:
claude /loginThis stores credentials globally — no .env or API key needed for CLI usage.
Notes
- No `.env` required: CLI-only usage doesn't need any environment variables. If no API keys are in the environment, the CLI auto-defaults to global Claude auth from
claude /login. - Database: SQLite auto-creates at
~/.archon/archon.db— no setup needed for CLI-only use. - Config:
~/.archon/config.yamlis auto-created on first run with sensible defaults. Per-repo config can be added at<repo>/.archon/config.yamlto override the AI assistant or configure command folders. Neither file needs manual creation for basic usage.
Archon Configuration Guide
Interactive guide for viewing and modifying Archon configuration. Use this when the user wants to change, view, or understand their config — at any point, not just during initial setup.
Step 1: Determine Scope
Use AskUserQuestion to determine what the user wants to configure:
Header: "Config scope"
Question: "Which configuration do you want to modify?"
Options:
1. "Repo config" (Recommended) — Settings for a specific repository (.archon/config.yaml in the repo)
2. "Global config" — User-wide settings (~/.archon/config.yaml)
3. "Both" — Review and modify both configsStep 2: Load Current Config
For Global Config (~/.archon/config.yaml)
Read the file:
cat ~/.archon/config.yamlIf it doesn't exist, tell the user it will be auto-created on first Archon run with defaults. Offer to create it now.
For Repo Config (<repo>/.archon/config.yaml)
First determine the target repo. If the current working directory is a git repo (and not the Archon source repo), use it. Otherwise ask:
Header: "Target repo"
Question: "Which repository's config do you want to modify?"
Options:
1. "Current directory" — Use the repo at the current working directory
2. "I'll provide a path" — Type or paste a repo pathThen read the file:
cat <target-repo>/.archon/config.yamlIf it doesn't exist, tell the user: "No repo config found. I can create one — or Archon will use defaults." Offer to create it.
Step 3: Show Current State
Display the current configuration in a clear format. Show both the current values and what the defaults are, so the user knows what's customized vs default.
Format example:
Current repo config (.archon/config.yaml):
assistant: codex (default: claude)
worktree.baseBranch: develop (default: auto-detected)
worktree.copyFiles: [".env"] (default: none)
defaults.loadDefaultCommands: true (default)
defaults.loadDefaultWorkflows: true (default)Step 4: Interactive Modification
Ask the user what they want to change. Use AskUserQuestion based on the scope.
Global Config Options
Header: "Global option"
Question: "What would you like to change in the global config?"
Options:
1. "Bot name" — Display name shown in messages (current: {value}, default: Archon)
2. "Default assistant" — AI assistant for new repos (current: {value}, default: claude)
3. "Streaming modes" — How responses are delivered per platform
4. "Concurrency" — Max concurrent AI conversations (current: {value}, default: 10)If "Streaming modes" is selected, follow up with:
Header: "Platform"
Question: "Which platform's streaming mode do you want to change?"
Options:
1. "Telegram" — Current: {value} (default: stream)
2. "GitHub" — Current: {value} (default: batch)
3. "Slack" — Current: {value} (default: batch)
4. "Discord" — Current: {value} (default: batch)Then for the selected platform:
Header: "Mode"
Question: "Which streaming mode for {platform}?"
Options:
1. "stream" — Send tokens as they arrive (real-time updates)
2. "batch" — Send complete response at once (cleaner for GitHub/Slack)Repo Config Options
Header: "Repo option"
Question: "What would you like to change in the repo config?"
Options:
1. "AI assistant" — Which AI to use for this repo (current: {value}, default: claude)
2. "Worktree settings" — Base branch and file copying
3. "Default loading" — Whether to load bundled commands/workflows
4. "Commands folder" — Custom command folder pathIf "Worktree settings" is selected:
Header: "Worktree"
Question: "Which worktree setting?"
Options:
1. "Base branch" — Branch used as base for worktree creation (current: {value})
2. "Copy files" — Files to copy into new worktrees (current: {value})For "Copy files", let the user add/remove entries. Show current list and ask:
Header: "Copy files"
Question: "Current copyFiles: {list}. What do you want to do?"
Options:
1. "Add a file" — Add a new file to copy into worktrees
2. "Remove a file" — Remove one from the list
3. "Replace all" — Start fresh with a new listRemind the user about the "source -> destination" syntax for renaming (e.g., ".env.example -> .env").
If "Default loading" is selected:
Header: "Defaults"
Question: "Which default loading option?"
Options:
1. "Default commands" — Load bundled command templates at runtime (current: {value})
2. "Default workflows" — Load bundled workflow definitions at runtime (current: {value})Step 5: Apply Changes
After gathering changes, update the YAML file. Use the Edit tool to modify existing values or Write to create the file if it doesn't exist.
Rules:
- Only include non-default values in the file (keep it clean)
- Preserve existing comments
- Preserve any values the user didn't change
- Validate values before writing (e.g., assistant must be "claude" or "codex")
After writing, confirm: "Updated {path}. Changes take effect on the next Archon invocation (no restart needed for CLI)."
If the server is running for non-CLI platforms, note: "Server platforms (Telegram, Slack, GitHub, Discord) require a server restart to pick up config changes."
Step 6: Offer Further Changes
After applying changes, ask if the user wants to modify anything else:
Header: "More changes?"
Question: "Want to change anything else?"
Options:
1. "Done" — All set
2. "Change another option" — Go back to Step 4
3. "View final config" — Show the full config as it stands nowLoop back to Step 4 if they want more changes.
---
Reference: All Configuration Options
Global Config (~/.archon/config.yaml)
| Option | Type | Default | Description |
|---|---|---|---|
botName | string | Archon | Bot display name shown in messages |
defaultAssistant | claude \ | codex | claude |
streaming.telegram | stream \ | batch | stream |
streaming.discord | stream \ | batch | batch |
streaming.slack | stream \ | batch | batch |
paths.workspaces | string | ~/.archon/workspaces | Directory for cloned repositories |
paths.worktrees | string | ~/.archon/worktrees | Directory for git worktrees |
concurrency.maxConversations | number | 10 | Maximum concurrent AI conversations |
Repo Config (<repo>/.archon/config.yaml)
| Option | Type | Default | Description |
|---|---|---|---|
assistant | claude \ | codex | claude |
commands.folder | string | .archon/commands | Custom command folder path (relative to repo root) |
commands.autoLoad | boolean | true | Auto-load commands on clone |
worktree.baseBranch | string | auto-detected | Base branch for worktree creation |
worktree.copyFiles | string[] | [] | Files to copy into new worktrees (supports "source -> dest" renaming) |
defaults.loadDefaultCommands | boolean | true | Load bundled default commands at runtime |
defaults.loadDefaultWorkflows | boolean | true | Load bundled default workflows at runtime |
Precedence Order (highest wins)
1. Environment variables (.env or shell) — always win 2. Repo config (.archon/config.yaml in repo) — project-specific 3. Global config (~/.archon/config.yaml) — user-wide preferences 4. Defaults — hardcoded sensible values
Environment Variable Overrides
These env vars override any config file setting:
| Env Var | Overrides |
|---|---|
BOT_DISPLAY_NAME | botName |
DEFAULT_AI_ASSISTANT | defaultAssistant / assistant |
TELEGRAM_STREAMING_MODE | streaming.telegram |
DISCORD_STREAMING_MODE | streaming.discord |
SLACK_STREAMING_MODE | streaming.slack |
MAX_CONCURRENT_CONVERSATIONS | concurrency.maxConversations |
ARCHON_HOME | Base directory for all Archon paths |
Discord Bot Setup Guide
1. Create a Discord Application
1. Go to the Discord Developer Portal 2. Click New Application 3. Enter a name (e.g., "Archon Bot") and click Create
2. Create a Bot
1. In the left sidebar, click Bot 2. Click Reset Token to generate a new bot token 3. Copy the token — this is your DISCORD_BOT_TOKEN 4. Under Privileged Gateway Intents, enable:
- MESSAGE CONTENT INTENT (required to read message text)
3. Generate Invite URL
1. In the left sidebar, click OAuth2 2. Under OAuth2 URL Generator, select scopes:
bot
3. Under Bot Permissions, select:
- Send Messages
- Read Message History
- Use Slash Commands
4. Copy the generated URL and open it in your browser 5. Select your server and click Authorize
4. Get Your User ID
1. In Discord, go to Settings > Advanced > Developer Mode (enable it) 2. Right-click your username anywhere and click Copy User ID 3. This is your DISCORD_ALLOWED_USER_IDS
5. Add to .env (in the archon repo root)
DISCORD_BOT_TOKEN=<token from step 2>
DISCORD_ALLOWED_USER_IDS=<your user ID>
DISCORD_STREAMING_MODE=batchDISCORD_STREAMING_MODE=batchwaits for the full response (recommended for Discord).DISCORD_STREAMING_MODE=streamshows responses as they're generated.- Multiple user IDs can be comma-separated.
6. Start the Server
Follow the Server Setup Guide to start the server. The Discord adapter auto-starts when DISCORD_BOT_TOKEN is set.
7. Test
In the Discord channel where you invited the bot:
@Archon Bot /helpThe bot should respond with available commands.
GitHub Webhook Setup Guide
GitHub integration lets Archon respond to issue comments, PR comments, and @mentions via webhooks.
IMPORTANT — Freeform input rule: This guide collects URLs, tokens, and usernames. Never use AskUserQuestion for freeform text input (URLs, tokens, usernames, paths). Ask the user directly in plain text — e.g., "Paste the ngrok URL here." Use AskUserQuestion only for multiple-choice decisions.
0. Check Existing .env Values
Before starting, read the existing .env file and check which GitHub-related values are already populated:
cat <archon-repo>/.envCheck these keys: WEBHOOK_SECRET, GITHUB_TOKEN, GH_TOKEN, GITHUB_ALLOWED_USERS.
If all are already filled in: Tell the user "GitHub tokens are already configured in .env. Skipping to webhook setup." Jump to Step 5 (configure the repo webhook).
If some are filled in: Tell the user which values are already set and which are missing. Only collect the missing ones in the steps below.
If none are filled in: Proceed with all steps.
1. Set Up a Public URL (ngrok)
GitHub webhooks need to reach your local server. Check if ngrok is installed:
which ngrokIf not installed, use AskUserQuestion:
Header: "Install ngrok"
Question: "ngrok is not installed. Want me to install it via Homebrew?"
Options:
1. "Yes, install it" (Recommended) — runs `brew install ngrok`
2. "I'll install it myself" — user handles it, wait for confirmationIf yes, run:
brew install ngrokIf ngrok is not authenticated, check and guide:
ngrok config check 2>&1If it needs auth: 1. Tell the user: "Sign up at https://ngrok.com (free tier works), then copy your auth token from the dashboard." 2. Ask the user in plain text to paste the token, then run:
ngrok config add-authtoken <token>2. Start ngrok
Tell the user to run this in a separate terminal (ngrok must stay running):
Run this in another terminal: ngrok http 3090Then ask in plain text (NOT AskUserQuestion):
"Paste the ngrok HTTPS URL here (e.g., https://abc123.ngrok-free.app)."If the user pastes the full ngrok terminal output, parse the URL from the Forwarding line (the https://... URL before the -> arrow).
Store the URL as <ngrok-url>.
3. Generate a Webhook Secret
Only if `WEBHOOK_SECRET` is empty/missing in `.env`.
openssl rand -hex 32Store this as <webhook-secret>.
4. Collect GitHub Token and Username
Only collect values that are missing from `.env`.
Present all missing items together in a single message, then let the user respond. Do not ask one at a time.
For example, if both token and username are missing:
"I need two things from you:
1. GitHub token — Go to github.com/settings/tokens and create a fine-grained token with repository access for <target-repo> and permissions: Issues (R/W), Pull Requests (R/W), Contents (Read).2. GitHub username — Your GitHub username (used for authorization).
>
Paste them here when ready (token first, then username), or tell me you've added them to .env directly."If the user says they've already added values to .env, read the file to confirm and skip to the next step. Do not ask again for values the user says are already there.
5. Write to .env
Write only the missing values to .env. Do not overwrite existing values.
Values to set (if missing):
WEBHOOK_SECRET=<webhook-secret>
GITHUB_TOKEN=<token>
GH_TOKEN=<same token>
GITHUB_ALLOWED_USERS=<username>6. Configure the Repository Webhook
Tell the user to go to their target repo on GitHub > Settings > Webhooks > Add webhook and configure:
- Payload URL:
<ngrok-url>/webhooks/github - Content type:
application/json - Secret:
<webhook-secret>(the value from step 3, or the existing value from.env) - Select events: Issue comments + Pull request review comments (or "Send me everything")
- Click Add webhook
Use AskUserQuestion to confirm when done:
Header: "Webhook"
Question: "Have you added the webhook to your GitHub repo?"
Options:
1. "Done" — webhook is configured
2. "I need help" — walk me through it step by step7. Verify the Webhook
Start the server and test the webhook endpoint:
cd <archon-repo> && bun run dev &
sleep 3
curl -s http://localhost:3090/healthIf health check returns {"status":"ok"}, also verify the ngrok tunnel is forwarding:
curl -s <ngrok-url>/healthBoth should return {"status":"ok"}. If the ngrok check fails, make sure the ngrok terminal is still running.
Stop the background server when done verifying:
kill %1 2>/dev/nullNotes
- Free tier URLs change on restart — you'll need to update the webhook URL in GitHub each time you restart ngrok.
- Persistent URLs: Use a paid ngrok plan, Cloudflare Tunnel, or cloud deployment (see
docs/cloud-deployment.md). - Both the server (
bun run dev) and ngrok must be running for GitHub webhooks to work.
Server Setup Guide
Shared setup for all non-CLI platforms (Telegram, Slack, Discord, GitHub). Run the CLI setup first.
Important: The server runs from the archon repo root — not the target repo. The .env file should already exist there (created in Step 4 of the setup wizard).
1. Verify .env
Make sure .env exists in the archon repo root with the platform tokens from the platform-specific guides:
ls -la <archon-repo>/.envIf it doesn't exist yet:
cd <archon-repo> && cp .env.example .envThen add the platform tokens from the relevant platform guides.
2. Start the Development Server
cd <archon-repo> && bun run devThis starts the Hono server with hot reload. Platform adapters auto-start based on which tokens are present in .env.
3. Verify Server Health
curl http://localhost:3090/healthExpected response: {"status":"ok"}
4. Database
- SQLite (default): Auto-creates at
~/.archon/archon.db. No setup needed. - PostgreSQL (optional): Set
DATABASE_URLin.envand run migrations:
docker-compose --profile with-db up -d postgres
psql $DATABASE_URL < migrations/001_initial_schema.sql5. Running in Background
For persistent operation, choose one:
tmux/screen:
tmux new -s archon
cd <archon-repo> && bun run dev
# Ctrl+B, D to detachDocker (production):
cd <archon-repo> && docker-compose --profile with-db up -d --buildsystemd (Linux): Create a service file at /etc/systemd/system/archon.service pointing to bun run start.
Important Notes
- Only use one instance at a time per set of platform tokens — running multiple instances causes token conflicts.
- The server must be running for Telegram, Slack, Discord, and GitHub platforms to work.
- CLI workflows work independently and do not require the server.
- Configuration:
~/.archon/config.yamlis auto-created on first run with sensible defaults. Environment variables in.envoverride matching config values (e.g.,TELEGRAM_STREAMING_MODEoverridesstreaming.telegram).
Archon Setup Wizard
Interactive setup guide. Follow these steps in order, using AskUserQuestion to gather input.
IMPORTANT — When to use AskUserQuestion vs plain text:
- AskUserQuestion: Use ONLY for multiple-choice decisions (pick A or B).
- Plain text: Use for freeform input (paths, URLs, tokens, usernames). Just ask the user directly in your message — e.g., "Paste the path to your repo here." Never wrap freeform input in AskUserQuestion with an "I'll provide it" option — that creates a pointless double question.
Prerequisites
Run these checks first:
bun --version
git --versionIf `git` is not installed: Try to install it automatically based on the platform:
macOS:
# Try Homebrew first, fall back to Xcode CLI tools
brew install git || xcode-select --installNote: xcode-select --install opens a GUI dialog - tell the user to click "Install" and wait.
Linux (detect package manager):
# Try in order: apt, dnf, pacman, apk
sudo apt-get install -y git 2>/dev/null || \
sudo dnf install -y git 2>/dev/null || \
sudo pacman -S --noconfirm git 2>/dev/null || \
sudo apk add git 2>/dev/nullWindows (PowerShell):
winget install Git.GitIf installation fails (e.g., no sudo access, no package manager), tell the user to install Git manually from https://git-scm.com and run setup again.
If `bun` is not installed: Install it automatically based on the platform:
macOS/Linux:
curl -fsSL https://bun.sh/install | bashThe installer adds Bun to the shell config, but it won't take effect until a new shell starts. For the rest of this setup session, use the full path ~/.bun/bin/bun instead of just bun.
Verify installation:
~/.bun/bin/bun --versionWindows (PowerShell):
irm bun.sh/install.ps1 | iexOn Windows, the installer updates the PATH for the current session, so bun --version should work immediately.
Important: For all bun commands in Steps 3-4, use ~/.bun/bin/bun on macOS/Linux if bun was just installed. After setup is complete and the user opens a new terminal, bun will work without the full path.
Context
The user is inside the remote-coding-agent repository — that's how they have access to this skill. The Archon repo path is the current working directory. Store it as <archon-repo>.
Step 1: Ask for Target Repo
IMPORTANT: The target repo is the user's own project — never the remote-coding-agent (Archon) repo itself. Do not suggest or offer the current directory as an option.
Use AskUserQuestion with a single question:
Header: "Target repo"
Question: "What is the path to the repository you want to work on using Archon? (This should be your own project, not the Archon repo.)"
Options:
1. "Clone from GitHub" — user provides a GitHub URL; clone it to ~/.archon/workspaces/The user will either select "Clone from GitHub" or type a local path via "Other". Do NOT add a second question to collect the path — the "Other" freeform input captures it directly in one step.
Store the result as <target-repo>.
If "Clone from GitHub": ask for the URL in plain text (not AskUserQuestion), then:
archon-repo-path=$(pwd)
mkdir -p ~/.archon/workspaces
cd ~/.archon/workspaces && git clone <url>Set <target-repo> to the cloned directory.
Step 2: Ask for Platforms
Use AskUserQuestion with multiSelect: true:
Header: "Platforms"
Question: "Which platforms do you want to set up? CLI is always included."
Options:
1. "CLI + GitHub" (Recommended) — CLI for local use, GitHub webhooks for issue/PR automation
2. "CLI only" — terminal-only, simplest setup
3. "Telegram" — chat bot via BotFather
4. "Slack" — Socket Mode appDiscord is also available — mention it as the "Other" option text.
Step 3: Run CLI Setup
Always run this. Read and follow guides/cli.md.
If Bun was just installed in Prerequisites (macOS/Linux), use ~/.bun/bin/bun instead of bun:
1. cd <archon-repo> && ~/.bun/bin/bun install (or bun install if bun was already in PATH) 2. cd <archon-repo>/packages/cli && ~/.bun/bin/bun link (or bun link) 3. Verify: archon version 4. Check Claude is installed: which claude, then claude /login if needed
Note — Claude Code binary path. Archon does not bundle Claude Code. In compiled Archon binaries (quick install, Homebrew), the Claude Code SDK needsCLAUDE_BIN_PATHset to the absolute path of itscli.js. Thearchon setupwizard in Step 4 auto-detects this vianpm root -gand writes it to~/.archon/.env— no manual action needed in the typical case. Source installs (bun run) don't need this; the SDK findscli.jsvianode_modulesautomatically.
Step 4: Configure Credentials
Archon loads infrastructure config (database, tokens) from two archon-owned files — ~/.archon/.env (user scope) and <cwd>/.archon/.env (repo scope, overrides user). The project's own <cwd>/.env is stripped at boot so it cannot leak into Archon; archon setup never writes to it.
Credential configuration runs in a separate terminal so your API keys stay private — the AI assistant won't see them.
4a: Launch the Setup Wizard
Run this command to attempt opening the wizard in a new terminal:
archon setup --spawnCRITICAL: Do NOT run archon setup directly via Bash — it requires interactive input that I cannot provide. The --spawn flag attempts to open a new terminal window where the user can interact directly.
Tell the user:
"Time to configure your credentials. This runs in a separate terminal so your keys stay private — I won't see them.
>
The wizard will walk you through:
1. Database selection (SQLite default or PostgreSQL)
2. AI assistant configuration (Claude and/or Codex)
3. Platform tokens for any integrations you selected
>
By default it saves to~/.archon/.env(user scope). Re-run witharchon setup --scope projectto write<repo>/.archon/.envinstead (project overrides user for this repo). Existing values are preserved — a timestamped backup is written before every rewrite."
If the terminal opened automatically, add:
"Complete the wizard in the new terminal window that just opened."
If the output says to run it manually (common on VPS, WSL, SSH, Docker), add:
"Open a separate terminal or SSH session and run the command shown in the output. Come back here and let me know when you finish so I can continue with validation."
Both paths are normal — the manual path is not an error.
4b: Wait for User Confirmation
Wait for the user to confirm they've completed the setup wizard before proceeding.
4c: Verify Configuration
After the user confirms setup is complete:
archon versionShould show:
Database: sqlite(default, zero setup) orDatabase: postgresql(if DATABASE_URL was configured)- No errors about missing configuration
4d: Run Database Migrations (PostgreSQL only)
SQLite users: skip this step. SQLite is auto-initialized on first run with zero setup.
If the user selected PostgreSQL, run migrations:
test -n "$DATABASE_URL" && psql $DATABASE_URL < migrations/000_combined.sqlTroubleshooting:
| Issue | Cause | Fix |
|---|---|---|
Shows sqlite but expected postgresql | ~/.archon/.env missing or no DATABASE_URL | Run archon setup again in your terminal |
| "relation does not exist" | Tables not created | Run psql $DATABASE_URL < migrations/000_combined.sql |
| Connection refused | Database not running or wrong URL | Check DATABASE_URL and database server status |
Step 5: Platform-Specific Verification
The setup wizard already collected credentials for platforms selected in Step 3. Verify each one:
| Platform | Verification |
|---|---|
| CLI only | Done — skip to Step 6 |
| GitHub | Check GITHUB_TOKEN and WEBHOOK_SECRET are in .env |
| Telegram | Check TELEGRAM_BOT_TOKEN is in .env |
| Slack | Check SLACK_BOT_TOKEN and SLACK_APP_TOKEN are in .env |
| Discord | Check DISCORD_BOT_TOKEN is in .env |
For advanced platform configuration (webhook URLs, bot permissions, etc.), refer to the platform-specific guides:
guides/github.md— GitHub webhook setup detailsguides/telegram.md— BotFather commandsguides/slack.md— Slack app configurationguides/discord.md— Discord bot permissions
Step 6: Defaults (No Copy Needed)
Bundled default commands and workflows are loaded automatically at runtime from the Archon installation — nothing needs to be copied into the target repo.
Tell the user:
- "Default commands and workflows are loaded automatically at runtime — no files are added to your repo."
- "To browse defaults, look in
<archon-repo>/.archon/commands/defaults/and<archon-repo>/.archon/workflows/defaults/." - "To customize a default, copy the specific file into your repo's
.archon/commands/or.archon/workflows/directory with the same filename. Your repo version takes priority over the bundled default."
Step 7: Start the Server (non-CLI platforms only)
Skip if "CLI only" was selected.
After all platform tokens are in .env, read and follow guides/server.md to start the server from the archon repo.
Step 8: Verify from Target Repo
Run a test workflow from the target repo:
cd <target-repo> && archon workflow listIf the CLI is working, also run:
cd <target-repo> && archon workflow run archon-assist "Say hello"Troubleshooting
If verification fails:
| Error | Cause | Fix |
|---|---|---|
archon: command not found | CLI not linked | Re-run cd <archon-repo>/packages/cli && bun link |
Not a git repository | Not in a git repo | cd to the target repo root |
No workflows found | Missing .archon/workflows/ | Default workflows load automatically — check archon version works first |
| Auth errors | Claude not authenticated | Run claude /login |
relation "remote_agent_*" does not exist | DATABASE_URL missing or tables not created | Ensure ~/.archon/.env has DATABASE_URL and run migrations |
Database: sqlite but expected PostgreSQL | ~/.archon/.env missing DATABASE_URL | Add DATABASE_URL to ~/.archon/.env |
Step 9: Copy Skill to Target Repo (Optional)
Use AskUserQuestion to ask:
Header: "Archon skill"
Question: "Would you like to copy the Archon skill into your target repo so Claude Code can invoke Archon workflows from there?"
Options:
1. "Yes, copy the skill" — Copies .claude/skills/archon/ into the target repo. This will appear in git unless you gitignore it.
2. "No, skip" — You can always run Archon workflows from the Archon repo instead.If "Yes, copy the skill":
mkdir -p <target-repo>/.claude/skills
cp -r <archon-repo>/.claude/skills/archon <target-repo>/.claude/skills/archonNote: Do NOT modify the user's .gitignore — let them decide how to handle it.
Step 10: Final Summary
Tell the user what was set up, then give these instructions:
1. Open a new terminal 2. cd <target-repo> 3. Run claude to launch Claude Code 4. The archon skill is now loaded — ask Claude to run workflows, fix issues, review PRs, etc.
Example first command in the target repo:
"Use archon to fix issue #1"Tell the user:
- Default commands and workflows load automatically at runtime — nothing was added to your repo
.claude/skills/archon/— skill for Claude Code integration- To customize a default, copy the specific file from
<archon-repo>/.archon/commands/defaults/or<archon-repo>/.archon/workflows/defaults/into your repo's.archon/commands/or.archon/workflows/with the same filename
Important: End the summary with this message:
"If you want to configure advanced options later — like changing the default AI assistant, customizing worktree behavior, or adjusting which files get copied into isolated environments — just ask me to help you with 'archon config' and I'll walk you through it."
The end state: user is in their target repo with the Archon skill available, defaults loaded at runtime without polluting the repo, using Claude Code as the interface.
Configuration Reference
For advanced users — these are not needed for basic setup:
Environment Files (.env)
Archon's env model is scoped by directory ownership: .archon/ is archon-owned, anything else belongs to you.
| Path | Stripped at boot? | Archon loads? | archon setup writes? |
|---|---|---|---|
<cwd>/.env | yes (safety guard) | never | never |
<cwd>/.archon/.env | no | yes (project scope, overrides user scope) | yes iff --scope project |
~/.archon/.env | no | yes (user scope) | yes iff --scope home (default) |
Which should I use?
~/.archon/.env— defaults that apply everywhere (your personalSLACK_WEBHOOK,DATABASE_URL, bot tokens).<cwd>/.archon/.env— per-project overrides (different webhook per repo, different DB per environment).<cwd>/.env— your app's env file; archon strips these keys at boot so nothing leaks between your app and archon.
archon setup writes to exactly one archon-owned file chosen by --scope (default home), merges into existing content so user-added keys survive, and writes a timestamped backup before every rewrite. Use --force to opt into wholesale overwrite (backup still written).
Config Files (YAML)
Project-specific settings use layered YAML configs:
| Location | Scope | Purpose |
|---|---|---|
~/.archon/config.yaml | Global | Default AI assistant, streaming modes, concurrency |
<repo>/.archon/config.yaml | Per-repo | AI assistant, worktree settings, commands config |
Environment variables in .env override matching config.yaml values.
Repo Config Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
assistant | claude \ | codex | claude |
commands.folder | string | .archon/commands | Custom command folder path (relative to repo root) |
commands.autoLoad | boolean | true | Auto-load commands on clone |
worktree.baseBranch | string | auto-detected | Base branch for worktree creation |
worktree.copyFiles | string[] | [] | Files to copy into new worktrees (supports "source -> dest" syntax) |
defaults.loadDefaultCommands | boolean | true | Load bundled default commands at runtime |
defaults.loadDefaultWorkflows | boolean | true | Load bundled default workflows at runtime |
Slack Bot Setup Guide
Slack setup is more involved than other platforms. A detailed walkthrough is available in the main docs.
Full Guide
Follow the step-by-step instructions in [docs/slack-setup.md](../../../../../docs/slack-setup.md) in this repository.
Summary
1. Create a Slack app at api.slack.com/apps (from scratch) 2. Enable Socket Mode — generates an App-Level Token (xapp-...) for SLACK_APP_TOKEN 3. Add Bot Token Scopes: app_mentions:read, chat:write, channels:history, channels:join, im:history, im:write, im:read 4. Subscribe to Bot Events: app_mention, message.im 5. Install to Workspace — generates a Bot User OAuth Token (xoxb-...) for SLACK_BOT_TOKEN 6. Invite the bot to your channel: /invite @YourBotName
.env Configuration (in the archon repo root)
SLACK_BOT_TOKEN=xoxb-your-bot-token
SLACK_APP_TOKEN=xapp-your-app-token
SLACK_ALLOWED_USER_IDS=<your Slack user ID>
SLACK_STREAMING_MODE=batchTo find your Slack user ID: click your profile > ... > Copy member ID.
Start the Server
Follow the Server Setup Guide to start the server. The Slack adapter auto-starts when both SLACK_BOT_TOKEN and SLACK_APP_TOKEN are set.
Telegram Bot Setup Guide
1. Create a Bot via BotFather
1. Open Telegram and search for @BotFather 2. Send /newbot 3. Choose a display name (e.g., "Archon Bot") 4. Choose a username (must end in bot, e.g., my_archon_bot) 5. Copy the bot token — this is your TELEGRAM_BOT_TOKEN
2. Get Your User ID
1. Search for @userinfobot on Telegram 2. Send any message 3. It replies with your user ID (a number like 123456789) 4. This is your TELEGRAM_ALLOWED_USER_IDS
3. Add to .env (in the archon repo root)
TELEGRAM_BOT_TOKEN=<token from BotFather>
TELEGRAM_ALLOWED_USER_IDS=<your user ID>
TELEGRAM_STREAMING_MODE=streamTELEGRAM_STREAMING_MODE=streamshows responses as they're generated (recommended).TELEGRAM_STREAMING_MODE=batchwaits for the full response before sending.- Multiple user IDs can be comma-separated.
4. Start the Server
Follow the Server Setup Guide to start the server. The Telegram adapter auto-starts when TELEGRAM_BOT_TOKEN is set.
5. Test
Send a message to your bot on Telegram:
/helpThe bot should respond with available commands.
Authoring Command Files
Commands are plain Markdown files containing AI prompt templates. They are the atomic unit of AI instruction — each command file defines what a single AI agent does in one step of a workflow.
File Location
Commands are discovered from three scopes, highest-precedence first:
<repoRoot>/.archon/commands/ # 1. Repo-scoped (wins)
├── my-command.md # Custom command for this repo
├── archon-assist.md # Overrides the bundled archon-assist
└── triage/ # Subfolders allowed, 1 level deep
└── review.md # Resolves as 'review', not 'triage/review'
~/.archon/commands/ # 2. Home-scoped (user-level, shared across all repos)
├── review-checklist.md # Personal helper available in every repo
└── pr-style-guide.md
<bundled defaults> # 3. Shipped with Archon (archon-assist, etc.)Resolution rules:
- Filename-without-extension is the command name (e.g.
my-command.md→my-command). - 1-level subfolders are supported for grouping; resolution is still by filename (
triage/review.md→review). - Repo scope overrides home scope overrides bundled, by name.
- Duplicate basenames within a scope (e.g. two different
review.mdfiles intriage/andsecurity/) are a user error — keep names unique within each scope.
Commands are referenced by name (without .md) in workflow YAML files.
File Format
---
description: One-line description of what this command does
argument-hint: <issue-number> or (no arguments)
---
# Command Title
**Workflow ID**: $WORKFLOW_ID
---
## Phase 1: LOAD
[Instructions for gathering context]
## Phase 2: EXECUTE
[Instructions for doing the work]
## Phase 3: GENERATE
[Instructions for writing artifacts]
### PHASE_3_CHECKPOINT
- [ ] Artifact written to `$ARTIFACTS_DIR/output.md`
- [ ] Summary prepared
## Phase 4: REPORT
[Instructions for the final output message]Frontmatter Fields
| Field | Required | Description |
|---|---|---|
description | Recommended | Human-readable description (shown in listings) |
argument-hint | Optional | Expected arguments hint (e.g., <issue-number>, (no arguments)) |
The frontmatter is metadata for discovery. The entire file content (including frontmatter) becomes the prompt sent to the AI.
Variable Substitution
Variables are replaced at execution time. See references/variables.md for the complete list.
Most commonly used:
$ARGUMENTS— the user's input message$ARTIFACTS_DIR— write artifacts here (pre-created directory)$WORKFLOW_ID— for tracking$BASE_BRANCH— for git operations
Name Validation Rules
Command names must:
- Not contain
/,\, or.. - Not start with
. - Not be empty
Discovery and Priority
When a workflow references command: my-command, Archon searches in this order:
1. <repoRoot>/.archon/commands/my-command.md (repo scope) 2. ~/.archon/commands/my-command.md (home scope — shared across every repo on the machine) 3. Bundled defaults (shipped with Archon)
First match wins. To override a bundled command, drop a file with the same name at either scope. To override a home-scoped command for a specific repo, drop a file with the same name in that repo's .archon/commands/.
Web UI note: Home-scoped commands appear in the workflow builder's node palette under a dedicated "Global (~/.archon/commands/)" section, distinct from project and bundled entries.
Referencing Commands from Workflows
In workflow YAML, use the command: field on a node:
nodes:
- id: review
command: my-command # Loads .archon/commands/my-command.md
depends_on: [implement]Phase-Based Organization Pattern
The recommended structure for complex commands:
1. LOAD — Read inputs, gather context, load artifacts from previous steps 2. EXPLORE/ANALYZE — Research the codebase, understand the problem 3. EXECUTE/GENERATE — Do the work, write code, create artifacts 4. VALIDATE — Run tests, type-check, verify 5. REPORT — Summarize results for the user
Each phase should have a PHASE_N_CHECKPOINT with a checklist to keep the AI on track.
Artifact Conventions
Artifacts are how steps communicate in multi-step workflows. Write outputs to $ARTIFACTS_DIR/:
| Convention | Purpose |
|---|---|
$ARTIFACTS_DIR/plan.md | Implementation plan |
$ARTIFACTS_DIR/investigation.md | Bug investigation results |
$ARTIFACTS_DIR/implementation.md | Implementation summary |
$ARTIFACTS_DIR/validation.md | Test/lint results |
$ARTIFACTS_DIR/pr-body.md | PR description content |
$ARTIFACTS_DIR/.pr-number | PR number (metadata) |
$ARTIFACTS_DIR/.pr-url | PR URL (metadata) |
$ARTIFACTS_DIR/review/ | Review agent outputs (subdirectory) |
Anti-Patterns
- Vague instructions — "Fix the code" is too vague. Be specific about what to investigate, which tools to use, what output to produce.
- No artifact output — If a command produces no artifacts, downstream steps have nothing to work from.
- Assuming prior context — When
context: freshis set on the calling node, the AI starts fresh. It must read artifacts explicitly. - Giant monolithic commands — Split complex work into focused phases. Each command should have one clear responsibility.
- Hardcoded paths — Use
$ARTIFACTS_DIRinstead of hardcoded paths for portability.
Simple Command Example
---
description: General-purpose AI assistant
argument-hint: <any request>
---
You are a helpful coding assistant working on this project.
**Request**: $ARGUMENTS
Analyze the codebase and help the user with their request. Use Read, Grep, Glob, and Bash tools to explore the code. Provide clear, actionable answers.Complex Command Example
---
description: Validate implementation against the plan
argument-hint: (no arguments - reads from workflow artifacts)
---
# Validate Implementation
**Workflow ID**: $WORKFLOW_ID
---
## Phase 1: LOAD
Read the plan context:
- Read `$ARTIFACTS_DIR/plan-context.md` for the implementation plan
- Read `$ARTIFACTS_DIR/implementation.md` for what was implemented
## Phase 2: VALIDATE
Run the full validation suite:
bun run type-check bun run lint bun run test
Record all failures with file paths and error messages.
### PHASE_2_CHECKPOINT
- [ ] Type-check results recorded
- [ ] Lint results recorded
- [ ] Test results recorded
## Phase 3: REPORT
Write validation results to `$ARTIFACTS_DIR/validation.md` with:
- Pass/fail status for each check
- Specific error details for failures
- Summary recommendation (proceed / needs fixes)Archon CLI Command Reference
All commands must be run from within a git repository (subdirectories work — resolves to repo root). Exceptions: version, setup, chat.
Workflow Commands
archon workflow list
List all discovered workflows (bundled + repo-defined).
archon workflow list # Human-readable table
archon workflow list --json # Machine-readable JSON outputJSON output includes: { workflows: [{ name, description, provider?, model? }], errors: [{ filename, error }] }
archon workflow run <name> [message] [flags]
Execute a workflow.
archon workflow run archon-assist "What does the auth module do?"
archon workflow run archon-fix-github-issue --branch fix/issue-42 "Fix issue #42"
archon workflow run my-workflow --branch feat/dark-mode --from develop "Add dark mode"
archon workflow run quick-fix --no-worktree "Fix the typo in README"
archon workflow run archon-fix-github-issue --resume| Flag | Description |
|---|---|
--branch <name> / -b | Branch name for worktree. Reuses existing worktree if healthy |
--from <name> / --from-branch <name> | Start-point branch for new worktree (default: repo default branch) |
--no-worktree | Skip isolation — run in the live checkout |
--resume | Resume the last failed run of this workflow at this cwd (skips completed nodes) |
--cwd <path> | Working directory override |
Flag conflicts (errors):
--branch+--no-worktree--from+--no-worktree--resume+--branch
Default behavior (no flags): Auto-creates a worktree with branch name {workflow-name}-{timestamp}.
Auto-resume without `--resume`: If a prior invocation of the same workflow at the same cwd failed, the next invocation automatically skips completed nodes. --resume is only needed when you want to force resume a specific failed run or to reuse the worktree from that run.
archon workflow status
Show the currently running workflow (if any) with its run ID, state, and last activity.
archon workflow status
archon workflow status --json # Machine-readable outputarchon workflow approve <run-id> [comment]
Approve a paused approval-node workflow. Auto-resumes the workflow.
archon workflow approve abc123
archon workflow approve abc123 --comment "Plan looks good"
archon workflow approve abc123 "Plan looks good" # positional formFor interactive loop nodes, the comment becomes $LOOP_USER_INPUT on the next iteration. For approval nodes with capture_response: true, the comment becomes $<gate-id>.output for downstream nodes.
archon workflow reject <run-id> [reason]
Reject a paused approval gate. Without on_reject on the node, cancels the workflow. With on_reject, runs the rework prompt with $REJECTION_REASON substituted and re-pauses.
archon workflow reject abc123
archon workflow reject abc123 --reason "Plan misses test coverage"
archon workflow reject abc123 "Plan misses test coverage"archon workflow abandon <run-id>
Mark a non-terminal workflow run as cancelled. Use when a running row is stuck after a server crash or when you want to discard a paused run without rejecting. This does NOT kill an in-flight subprocess — it only transitions the DB row.
archon workflow abandon abc123There is no `archon workflow cancel` CLI subcommand. To actively cancel a running workflow (terminate its subprocess), use the chat slash command/workflow cancel <run-id>on the platform that started it (Web UI, Slack, Telegram, etc.), or the Cancel button on the Web UI dashboard. The CLI only offersabandon, which is the right tool for orphan cleanup but does not interrupt a live subprocess.
archon workflow resume <run-id> [message]
Explicitly re-run a failed run. Most workflows auto-resume without this — use it when you want to force a specific run ID.
archon workflow resume abc123
archon workflow resume abc123 "continue with the plan"archon workflow cleanup [days]
Deletes old terminal workflow runs (completed/failed/cancelled) from the database for disk hygiene. Does NOT transition running rows — use abandon/cancel for those.
archon workflow cleanup # Default: 7 days
archon workflow cleanup 30 # Custom: 30 daysarchon workflow event emit --run-id <uuid> --type <event-type> [--data <json>]
Emit a workflow event to a running workflow. Used inside loop prompts to signal state (e.g. "checkpoint written") for observability. Rarely invoked from the shell directly.
archon workflow event emit --run-id abc123 --type checkpoint --data '{"step":"plan"}'archon continue <branch> [flags] [message]
Continue work on a branch with prior context. Defaults to archon-assist; use --workflow to pick a different workflow. Useful for iterative sessions on the same worktree without typing the full workflow run incantation.
archon continue feat/auth "Add password reset"
archon continue feat/auth --workflow archon-feature-development "Continue from step 3"
archon continue feat/auth --no-context "Start fresh without loading prior artifacts"Flags: --workflow <name>, --no-context.
Isolation Commands
archon isolation list
Show active worktree environments for all codebases.
archon isolation listOutputs: branch name, path, workflow type, platform, last activity age. Ghost entries (deleted worktrees) are auto-reconciled.
archon isolation cleanup [days]
Remove stale worktree environments.
archon isolation cleanup # Default: 7 days
archon isolation cleanup 14 # Custom: 14 days
archon isolation cleanup --merged # Also remove worktrees whose branches merged into main (deletes remote branches too)
archon isolation cleanup --merged --include-closed # Also remove worktrees whose PRs were closed without mergingFlags:
| Flag | Description |
|---|---|
[days] | Positional — age threshold in days. Environments untouched for longer than this are removed. Default: 7 |
--merged | Union of three signals — ancestry (git branch --merged), patch equivalence (git cherry), and PR state (gh) — safely catches squash-merges |
--include-closed | With --merged, also remove worktrees whose PRs were closed (abandoned, not merged) |
Validate Commands
archon validate workflows [name]
Validate workflow YAML definitions and their referenced resources.
archon validate workflows # Validate all workflows in the repo
archon validate workflows my-workflow # Validate a single workflow
archon validate workflows my-workflow --json # Machine-readable JSON outputChecks: YAML syntax, DAG structure (cycles, dependency refs), command file existence, MCP config files, skill directories, provider compatibility. Returns actionable error messages with "did you mean?" suggestions for typos.
Exit code: 0 = all valid, 1 = errors found.
archon validate commands [name]
Validate command files (.md) in .archon/commands/.
archon validate commands # Validate all commands
archon validate commands my-command # Validate a single commandChecks: file exists, non-empty, valid name.
Other Commands
archon complete <branch> [flags]
Complete a branch lifecycle — removes worktree + local/remote branches.
archon complete feature-auth
archon complete feature-auth --force # Skip uncommitted-changes check
archon complete branch1 branch2 branch3 # Multiple branchesOther Commands
archon version
archon version
# Archon CLI v0.x.x
# Platform: darwin-arm64
# Build: source (bun)
# Database: sqlitearchon setup [--spawn]
Interactive setup wizard for database, AI providers, and platform connections.
archon setup # Run in current terminal
archon setup --spawn # Open wizard in a new terminal windowarchon chat <message>
Single-shot message to the orchestrator (does not require a git repo).
archon chat "What platforms are configured?"
archon chat "/status"Global Flags
| Flag | Short | Description |
|---|---|---|
--cwd <path> | — | Working directory override |
--quiet | -q | Set log level to warn (errors only) |
--verbose | -v | Set log level to debug |
--json | — | Machine-readable JSON output (workflow list) |
--help | -h | Print usage and exit |
Key Environment Variables
| Variable | Purpose |
|---|---|
CLAUDE_API_KEY | Claude API key (explicit auth) |
CLAUDE_USE_GLOBAL_AUTH | true to use claude /login credentials |
ARCHON_HOME | Override base directory (default: ~/.archon) |
LOG_LEVEL | Pino log level: `fatal\ |
DATABASE_URL | PostgreSQL URL (omit for SQLite default) |
Advanced Features: Hooks, MCP, Skills, Retry
These features are available on command and prompt nodes (hooks, MCP, skills, tool restrictions, output_format, agents, Claude SDK options) and command, prompt, bash, and script nodes (retry). Loop nodes do not support these features (retry on loop nodes is a hard error; others are silently ignored). Bash and script nodes silently ignore AI-specific fields (a loader warning lists the ignored fields).
Provider Compatibility
| Feature | Claude (per-node) | Codex (per-node) | Codex (global) |
|---|---|---|---|
hooks | Supported | Ignored | Not available |
mcp | Supported | Ignored | ~/.codex/config.toml [mcp_servers.*] |
skills | Supported | Ignored | ~/.agents/skills/ or .agents/skills/ |
allowed_tools / denied_tools | Supported | Ignored | enabled_tools / disabled_tools per MCP server in config.toml |
output_format | Supported | Supported | — |
retry | Supported | Supported | — |
model / provider per-node | Supported | Supported | — |
Claude vs Codex: How Each Gets MCP and Skills
Claude: MCP servers and skills are configured per-node in the workflow YAML via mcp: and skills: fields. Each node can have different MCP servers and skills.
Codex: MCP servers and skills are configured globally — they apply to all Codex nodes in the workflow:
- MCP servers: Add to
~/.codex/config.toml(or.codex/config.tomlin the repo):
[mcp_servers.github]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
env = { GITHUB_TOKEN = "your-token" }Manage with: codex mcp add <name>, codex mcp list
- Skills: Place in
~/.agents/skills/<name>/SKILL.md(user-level) or.agents/skills/<name>/SKILL.md(repo-level). Codex discovers them automatically. - Custom instructions: Place in
~/.codex/AGENTS.md(global) orAGENTS.mdin the repo root.
The Codex CLI picks up all of these automatically because Archon inherits the full process environment when spawning the CLI. No Archon configuration needed — just set up the Codex CLI config once.
Hooks have no Codex equivalent — they are a Claude-only SDK feature for intercepting tool calls.
---
Hooks
Claude only. Codex nodes log a warning and ignore hooks.
Hooks intercept tool calls during a node's AI execution. Use them to approve/deny tools, inject context after tool use, or emergency-stop the agent.
Syntax
- id: analyze
prompt: "Analyze the codebase"
hooks:
PreToolUse:
- matcher: "Bash" # Regex on tool name (optional)
response: # Required: SDK SyncHookJSONOutput
hookSpecificOutput:
hookEventName: PreToolUse # Must match the event key
permissionDecision: deny
permissionDecisionReason: "No shell access in analysis phase"
timeout: 30 # Seconds (optional, default: 60)
PostToolUse:
- matcher: "Read"
response:
systemMessage: "You just read a file. Stay focused on analysis — do not modify anything."
- response: # No matcher = fires on every tool
systemMessage: "Verify this output is relevant."Supported Hook Events
Most commonly used: PreToolUse, PostToolUse, Stop
Full list: PreToolUse, PostToolUse, PostToolUseFailure, Notification, UserPromptSubmit, SessionStart, SessionEnd, Stop, SubagentStart, SubagentStop, PreCompact, PermissionRequest, Setup, TeammateIdle, TaskCompleted, Elicitation, ElicitationResult, ConfigChange, WorktreeCreate, WorktreeRemove, InstructionsLoaded
Matcher Fields
| Field | Type | Required | Description |
|---|---|---|---|
matcher | string | No | Regex pattern to filter by tool name. Omit to match all |
response | object | Yes | The SyncHookJSONOutput returned when hook fires |
timeout | number | No | Timeout in seconds (default: 60) |
Response Fields
| Field | Type | Effect |
|---|---|---|
hookSpecificOutput | object | Event-specific payload. Must include hookEventName matching the outer event key |
systemMessage | string | Inject a message visible to the AI model |
continue | boolean | Set to false to stop the agent |
stopReason | string | Reason when stopping |
decision | approve / block | Top-level approve/block decision |
PreToolUse hookSpecificOutput
| Field | Effect |
|---|---|
permissionDecision | deny / allow / ask |
permissionDecisionReason | Human-readable reason |
updatedInput | Object to replace tool arguments |
additionalContext | Extra context injected into the conversation |
PostToolUse hookSpecificOutput
| Field | Effect |
|---|---|
additionalContext | Context injected after the tool runs |
updatedMCPToolOutput | Replace MCP tool output |
Common Patterns
Deny specific tools:
hooks:
PreToolUse:
- matcher: "Write|Edit|Bash"
response:
hookSpecificOutput:
hookEventName: PreToolUse
permissionDecision: deny
permissionDecisionReason: "Read-only analysis node"Inject guidance after file reads:
hooks:
PostToolUse:
- matcher: "Read"
response:
systemMessage: "Focus on identifying security vulnerabilities in what you just read."Emergency stop on shell access:
hooks:
PreToolUse:
- matcher: "Bash"
response:
continue: false
stopReason: "Shell access not permitted"Hooks vs Tool Restrictions
| Mechanism | Granularity | Effect |
|---|---|---|
allowed_tools | Coarse | Tools not in list are invisible to AI |
denied_tools | Coarse | Listed tools are invisible to AI |
hooks.PreToolUse | Fine | Tool is visible but call can be denied/modified/annotated |
Use allowed_tools/denied_tools for hard restrictions. Use hooks when you want the AI to know the tool exists but have guardrails on how it's used.
---
MCP (Model Context Protocol) Servers
Claude only. Codex nodes log a warning and ignore MCP configuration.
Connect external tool servers to individual nodes.
Syntax
- id: github-analysis
prompt: "Analyze recent PRs using GitHub MCP tools"
mcp: .archon/mcp/github.json # Path relative to repo root
allowed_tools: [] # MCP-only mode (no built-in tools)Config File Format
The JSON file defines one or more MCP servers:
{
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "$GITHUB_TOKEN"
}
}
}Transport types:
stdio (default):
{
"my-server": {
"command": "npx",
"args": ["-y", "@server/package"],
"env": { "API_KEY": "$MY_API_KEY" }
}
}HTTP:
{
"my-server": {
"type": "http",
"url": "https://api.example.com/mcp",
"headers": { "Authorization": "Bearer $API_KEY" }
}
}SSE:
{
"my-server": {
"type": "sse",
"url": "https://api.example.com/sse"
}
}Environment Variable Expansion
$VAR_NAME patterns in env and headers values are expanded from process.env at execution time (not load time). This keeps secrets out of YAML files.
Missing env vars produce a user-visible warning but don't abort the node.
Automatic Tool Wildcards
When MCP servers are loaded, mcp__<serverName>__* wildcards are automatically added to the node's allowed tools. This means MCP tools work without explicit permission.
MCP-Only Nodes
Combine mcp: with allowed_tools: [] for nodes that should ONLY use MCP tools:
- id: notify
prompt: "Send a notification that the workflow completed"
mcp: .archon/mcp/ntfy.json
allowed_tools: [] # No built-in tools, MCP only---
Skills
Claude only. Codex nodes log a warning and ignore skills.
Preload domain knowledge into a node via Claude Code skills.
Syntax
- id: generate
prompt: "Create a Remotion animation for: $ARGUMENTS"
skills:
- remotion-best-practices # Must be installed in .claude/skills/
allowed_tools: [Read, Write, Edit, Glob]How It Works
When skills: is set, the node is wrapped in a Claude SDK AgentDefinition:
- The skill content is injected into the agent's context at startup
- The
Skilltool is automatically added to the node's allowed tools - The agent gets a system prompt listing the preloaded skills
Installing Skills
# From the skills.sh marketplace
npx skills add remotion-dev/skills
# Or create manually
mkdir -p .claude/skills/my-skill
# Write .claude/skills/my-skill/SKILL.md with frontmatterSkills are discovered from:
.claude/skills/(project-level)~/.claude/skills/(user-level, global)
Combining Skills with MCP
Skills provide knowledge (how to do something). MCP provides capability (external tool access). Combine them:
- id: smart-github-agent
prompt: "Triage these issues using GitHub best practices"
skills:
- github-triage-guide
mcp: .archon/mcp/github.json
allowed_tools: [] # MCP tools + skill knowledge---
Retry Configuration
Available on command, prompt, and bash nodes. Not supported on loop nodes (hard error at load time).
- id: deploy
bash: "deploy.sh"
retry:
max_attempts: 3 # 1-5 (required when retry is set)
delay_ms: 5000 # 1000-60000, default 3000. Doubles each attempt
on_error: all # 'transient' (default) or 'all'Error Classification
| Category | Examples | Retried? |
|---|---|---|
| FATAL | unauthorized, forbidden, permission denied, invalid token, authentication failed, auth error, 401, 403, credit balance | Never |
| TRANSIENT | timeout, etimedout, rate limit, too many requests, 429, 502, 503, econnrefused, econnreset, network error, socket hang up, exited with code, claude code crash | By default |
| UNKNOWN | Everything else | Only with on_error: all |
FATAL patterns take priority over TRANSIENT patterns in the same error message.
Two-Layer Retry Stack
1. SDK-level (automatic): Built-in retry for API errors (behavior managed by the Claude/Codex SDK) 2. Node-level (configurable via retry:): Wraps the entire SDK call. Default when retry: is omitted: 2 retries, 3000ms base delay, transient errors only
Idle Timeout
Separate from retry — controls how long a node can be idle (no output) before being aborted:
- id: long-running
command: full-analysis
idle_timeout: 600000 # 10 minutes (default: 5 minutes / 300000ms)For bash nodes, use timeout: instead (controls total script execution time, default: 120000ms).
Workflow Good Practices and Anti-Patterns
Guidance for authoring workflows that survive first contact with a real codebase. Written for an agent or human writing their first non-trivial workflow.
Good Practices
1. Use deterministic nodes for deterministic work
AI nodes are expensive, non-reproducible, and can hallucinate. Use bash: or script: for anything that has a right answer a computer can produce.
- Run tests with
bash: "bun run test", notprompt: "run the tests and tell me if they passed". - Parse JSON with
script:(bun/uv), not aprompt:that re-derives structure from free text. - Read files with known paths via
bash: "cat path/to/file"orReadin an AI node where the agent actually needs to reason about the content. - Git state checks (current branch, uncommitted changes, merge-base) →
bash:.
2. Use output_format for every node whose output downstream when: reads
when: conditions do best-effort JSON parsing on $nodeId.output for .field access. If the upstream node doesn't enforce a shape, you're pattern-matching free-form AI text — fragile.
# GOOD
- id: classify
prompt: "Classify as BUG or FEATURE"
output_format: # enforces the JSON shape
type: object
properties:
type: { type: string, enum: [BUG, FEATURE] }
required: [type]
- id: investigate
command: investigate-bug
depends_on: [classify]
when: "$classify.output.type == 'BUG'" # safe field access
# BAD
- id: classify
prompt: "Is this a bug or a feature?"
# no output_format; AI might reply "it looks like a bug", "BUG", or "This is a bug.\n\n..."
- id: investigate
command: investigate-bug
depends_on: [classify]
when: "$classify.output == 'BUG'" # fragile string match3. trigger_rule: none_failed_min_one_success after conditional branches
After when:-gated branches, the downstream merge node will see one or more skipped dependencies. Skipped ≠ success. Default all_success fails.
- id: investigate
command: investigate-bug
depends_on: [classify]
when: "$classify.output.type == 'BUG'"
- id: plan
command: plan-feature
depends_on: [classify]
when: "$classify.output.type == 'FEATURE'"
- id: implement
command: implement
depends_on: [investigate, plan]
trigger_rule: none_failed_min_one_success # CORRECT — exactly one ran
# trigger_rule: all_success ← would fail here (one dep skipped)Use one_success when any dep succeeding is enough; none_failed_min_one_success when no dep should have failed AND at least one must have succeeded; all_done for "run cleanup regardless" patterns with cancel: or notification nodes.
4. context: fresh requires artifacts for state passing
A node with context: fresh starts with no memory of prior nodes in the same workflow. The only way state moves is via files. Default is fresh for parallel layers and shared for sequential — explicit context: fresh is common when you want cost isolation.
- id: investigate
command: investigate-bug
# Investigator WRITES to $ARTIFACTS_DIR/investigation.md
- id: implement
command: implement-fix
depends_on: [investigate]
context: fresh
# Implementer MUST read $ARTIFACTS_DIR/investigation.md — it has no memory
# of what the investigator found.Command files should lead with "read artifacts from $ARTIFACTS_DIR/..." when they're downstream of a fresh node. This is the single biggest quality lever on multi-node workflows.
5. Cheap models for glue, strong models for substance
Classification, routing, formatting, and short summaries don't need Opus. Use model: haiku for these and reserve sonnet/opus for the nodes that actually produce code or long-form analysis. Combined with allowed_tools: [] on pure-text nodes, this cuts cost dramatically.
- id: classify
prompt: "Classify this issue"
model: haiku # fast + cheap
allowed_tools: [] # no tool overhead
output_format: { ... }
- id: implement
command: implement-fix
model: sonnet # where the thinking happens6. Write the workflow description for routing
Archon's orchestrator routes user intent to workflows by description. Write descriptions that make routing obvious.
- Start with the imperative action: "Fix a GitHub issue end-to-end", "Generate a Remotion video composition".
- Mention triggers: "Use when the user asks to review a PR", "Use when there's a failing test run".
- Mention what it does NOT do: "Does not create a PR — use
archon-plan-to-prfor that".
7. Validate before shipping
Never declare a workflow "done" without:
archon validate workflows <name> # YAML + DAG structure + resource refsThis checks: YAML syntax, node ID uniqueness, no cycles, all depends_on exist, all $nodeId.output refs point to known nodes, all command: files exist, all mcp: configs parse, all skills: directories exist, provider/model compatibility, named script existence, runtime availability. Fix everything it reports before first run.
For brand-new workflows, also: 1. Run once against a trivial input (archon workflow run my-workflow --branch test/sanity "hello") 2. Check the run log at ~/.archon/workspaces/<owner>/<repo>/logs/<run-id>.jsonl 3. Check artifacts at ~/.archon/workspaces/<owner>/<repo>/artifacts/runs/<run-id>/
See references/troubleshooting.md for how to read those.
8. Design the artifact chain before writing command files
In a multi-node workflow, each node's artifact IS the specification for the next node. Before writing any command body, map out:
| Node | Reads | Writes |
|---|---|---|
investigate-issue | GitHub issue via gh | $ARTIFACTS_DIR/issues/issue-{n}.md |
implement-issue | Artifact from investigate-issue | Code files, tests |
create-pr | Git diff | GitHub PR, $ARTIFACTS_DIR/pr-body.md |
If a downstream agent can't execute from just its artifact, the artifact is incomplete. This is the single most common failure mode in multi-node workflows.
9. Keep workflows reversible
Use worktree.enabled: true at the workflow level for anything that modifies the codebase. The CLI --no-worktree flag will hard-error, forcing users into isolation. The cost is a one-time cp of the worktree; the benefit is never having a failed workflow corrupt a live checkout.
For read-only workflows (triage, reporting, code analysis), pin worktree.enabled: false instead — saves the worktree setup cost.
---
Anti-Patterns
❌ Asking AI to run deterministic checks
# BAD
- id: test
prompt: "Run bun run test and tell me if it passed"
# GOOD
- id: test
bash: "bun run test 2>&1"
- id: react-to-tests
prompt: "Fix any failures: $test.output"
depends_on: [test]
trigger_rule: all_done # run even if tests failed❌ Pattern-matching free-form AI output in when:
# BAD — brittle
- id: decide
prompt: "Should we proceed? Answer yes or no."
- id: do-thing
depends_on: [decide]
when: "$decide.output == 'yes'" # AI says "Yes!" or "Yes, because..." — no match
# GOOD
- id: decide
prompt: "Should we proceed?"
output_format:
type: object
properties: { proceed: { type: boolean } }
required: [proceed]
- id: do-thing
depends_on: [decide]
when: "$decide.output.proceed == 'true'"❌ Commands that assume prior-node memory in a context: fresh chain
<!-- BAD — implement.md -->
Fix the bug we discussed in the investigation phase.
<!-- GOOD — implement.md -->
Read the investigation at `$ARTIFACTS_DIR/issues/issue-{n}.md`.
Extract the root cause, affected files, and implementation plan.
Implement the changes exactly as specified in the plan.❌ Long flat layers of AI nodes
Ten sibling prompt: nodes in one layer all depending on one upstream is a $N/run cost bomb and a latency trap. If the work is parallel and similar, use the agents: inline sub-agent map-reduce pattern with a cheap model per item and a single stronger reducer. See references/dag-advanced.md and the Inline sub-agents section on archon.diy for a worked example.
❌ Hardcoding secrets in YAML or MCP configs
Use $ENV_VAR expansion in MCP configs and the env: block in .archon/config.yaml (or Web UI Settings → Projects → Env Vars). See references/repo-init.md §Per-Project Env Injection.
❌ retry on a loop node
Loop nodes manage their own iteration via max_iterations. Setting retry: on a loop is a hard parse error — the workflow fails to load. If a loop iteration is flaky, handle it inside the loop prompt (the AI can retry tool calls) or use until_bash to gate completion on a deterministic check.
❌ Tiny max_iterations on open-ended loops
A loop with max_iterations: 3 that's supposed to implement N stories from a PRD will silently stop after 3 iterations and leave the work half-done. Think about the worst case — multi-story PRDs need 10–20, fix-iterate cycles need 5–8, refinement loops need 3–5.
❌ Missing interactive: true at workflow level for approval/loop gates on web
Web UI dispatches non-interactive workflows to a background worker that cannot deliver chat messages. Approval-gate messages and loop gate_message prompts will never reach the user. If the workflow has approval: nodes OR loop.interactive: true, set workflow-level interactive: true.
❌ Tool-restricted nodes without the MCP wildcard
# BAD — no tools available, including MCP
- id: analyze
prompt: "Use the Postgres MCP to query users"
mcp: .archon/mcp/postgres.json
allowed_tools: [] # OOPS — disables EVERYTHING, including MCP tools
# FIXED — Archon auto-adds mcp__<server>__* wildcards when mcp: is set,
# so this actually works out of the box. The anti-pattern is forgetting
# and manually adding Read/Write/Bash/etc. when you only want MCP.
- id: analyze
prompt: "Use Postgres MCP to query users"
mcp: .archon/mcp/postgres.json
allowed_tools: [] # correct — MCP tools auto-attachedCaveat: this only helps Claude. Codex gets MCP config from ~/.codex/config.toml globally, not per-node.
Interactive Workflow Guide
Interactive workflows use human-in-the-loop approval gates and interactive loops. When you invoke one, you become a transparent relay between the user and the running workflow — not a commentator.
Identifying Interactive Workflows
A workflow is interactive if it has interactive: true in its YAML definition. Key interactive workflows:
archon-piv-loop— Plan-Implement-Validate with iterative feedbackarchon-interactive-prd— Guided PRD creation with approval gates
When the user asks to run one of these, follow the protocol below.
Protocol: Running Interactive Workflows
1. Invoke the workflow
Run it in the background as usual:
archon workflow run <name> "<message>"2. Monitor for pause
Check archon workflow status periodically. When status changes to paused, the workflow is waiting for user input.
3. Fetch and relay the output — BE TRANSPARENT
When the workflow pauses, immediately read the log file to get the AI's output:
# Find the log file
find ~/.archon/workspaces -name "<run-id>.jsonl" 2>/dev/null
# Extract the last assistant messageParse the JSONL log for the last "type":"assistant" entry and display its content field directly to the user. Do not summarize, do not add commentary, do not say "the workflow asked..." — just show the output as if the user is talking to the workflow agent directly.
DO:
## What I Understand
You want to add a --json flag to workflow status...
## Questions
1. Should the output include...
2. Do you want...DON'T:
The workflow has paused and is asking you several questions. Here's what it found:
- It discovered that the --json flag is partially implemented
- It's asking about the output format
You can respond with...4. Collect user response and resume
When the user responds naturally (answers questions, says "ready", gives feedback), pass their response directly:
archon workflow approve <run-id> "<user's exact response>"Do not modify, summarize, or enhance the user's response. Pass it through verbatim.
5. Repeat until workflow completes
The workflow will alternate between running and pausing. Each time it pauses:
- Read the latest output from the log
- Display it directly
- Wait for the user's response
- Resume with their response
When the workflow finishes (status becomes completed or failed), report the final result.
Key Behavior Rules
1. You are a transparent pipe. The user should feel like they're talking directly to the workflow agent. Never insert yourself as a middleman with commentary.
2. Show output verbatim. The workflow agent's questions, findings, and summaries should appear exactly as written — including markdown formatting, code blocks, and structure.
3. Pass input verbatim. The user's responses go directly to the workflow via workflow approve. Don't rewrite or "improve" their input.
4. Don't explain the workflow mechanics. Don't say "the workflow is now in the explore phase" or "it will pause again after this." The user knows they're in a conversation — let it flow naturally.
5. Monitor proactively. Don't wait for the user to ask "what happened?" — check status and relay output as soon as the workflow pauses.
Approval Commands
# Approve with feedback (interactive loops)
archon workflow approve <run-id> "your feedback or answers here"
# Reject (cancels the workflow)
archon workflow reject <run-id> "reason for rejection"Troubleshooting
- Workflow shows `running` for a long time: The AI is doing research/implementation. Be patient — check again in a few minutes.
- Log file not found: The log is at
~/.archon/workspaces/<owner>/<repo>/logs/<run-id>.jsonl - User wants to cancel: Run
archon workflow reject <run-id>to stop at an approval gate, orarchon workflow abandon <run-id>to mark the run cancelled without killing any subprocess. To actively terminate a still-live subprocess, use the chat slash command/workflow cancel <run-id>on the platform that started it — there is noarchon workflow cancelCLI subcommand
Parameter Matrix (Quick Reference)
One-page lookup for Archon workflow parameters: which field works on which node type, how to pick the right parameter for a given intent, and the gotchas that don't fail loudly.
This is a lookup reference. For the full explanation of any field, follow the cross-references at the bottom to the detailed guides.
Master Matrix: Parameters × Node Types
There are seven node types. Exactly one of command, prompt, bash, script, loop, approval, or cancel must appear per node.
| Parameter | command | prompt | bash | script | loop | approval | cancel |
|---|---|---|---|---|---|---|---|
id | yes | yes | yes | yes | yes | yes | yes |
depends_on | yes | yes | yes | yes | yes | yes | yes |
when | yes | yes | yes | yes | yes | yes | yes |
trigger_rule | yes | yes | yes | yes | yes | yes | yes |
idle_timeout | yes | yes | ignored (use timeout) | ignored (use timeout) | yes (per-iter) | yes | yes |
timeout (total, not idle) | — | — | yes | yes | — | — | — |
model / provider | yes | yes | ignored | ignored | ignored at runtime | ignored | ignored |
context: fresh \ | shared | yes | yes | ignored | ignored | ignored (use loop.fresh_context) | ignored |
output_format | yes | yes | ignored | ignored | ignored | ignored | ignored |
allowed_tools / denied_tools | yes | yes | ignored | ignored | ignored | ignored | ignored |
hooks | yes | yes | ignored | ignored | ignored | ignored | ignored |
mcp | yes | yes | ignored | ignored | ignored | ignored | ignored |
skills | yes | yes | ignored | ignored | ignored | ignored | ignored |
agents | yes | yes | ignored | ignored | ignored | ignored | ignored |
retry | yes | yes | yes | yes | hard error | yes (on_reject) | yes |
effort / thinking / fallbackModel / betas / sandbox / maxBudgetUsd / systemPrompt | yes | yes | ignored | ignored | ignored | ignored | ignored |
bash / script / runtime / deps | — | — | bash required | script + runtime required | — | — | — |
loop (nested config) | — | — | — | — | required | — | — |
approval (nested config) | — | — | — | — | — | required | — |
cancel (reason string) | — | — | — | — | — | — | required |
Reading the matrix:
- yes — field works as expected on this node type.
- ignored — field is accepted by the parser but has no effect at runtime. Loader emits a warning (
<node-type>_node_ai_fields_ignored). - hard error — workflow fails to load. Only
retryon a loop node does this.
Most AI features work on command and prompt nodes. Loop nodes are thin controllers — the AI fields inside loop.prompt are what actually run. bash and script nodes silently ignore AI fields. approval and cancel nodes don't invoke AI at all.
Parameter Selection by Intent
Organized by what you're trying to do, not by field name. Useful when you know the outcome you want but aren't sure which parameter gets you there.
| You want to... | Use |
|---|---|
| Control cost per node | model: haiku, maxBudgetUsd: 0.50, effort: low |
| Force pure reasoning (no tools) | allowed_tools: [] |
| Read-only analysis phase | denied_tools: [Write, Edit, Bash] |
| Route based on upstream output | Upstream output_format: {...} + downstream when: |
| Join after mutually-exclusive routes | trigger_rule: none_failed_min_one_success or one_success |
| Run two independent branches in parallel | Two nodes with no shared depends_on |
| Iterate until tests pass | loop: {until_bash: "bun run test", max_iterations: N} |
| Iterate through a backlog without memory bleed | loop: {fresh_context: true}, state written to $ARTIFACTS_DIR |
| Iterate with human feedback between iterations | loop: {interactive: true, gate_message: "..."} + workflow interactive: true |
| Single human approval gate | approval: node with on_reject: {prompt, max_attempts} |
| Fail fast if upstream output is wrong | cancel: node with when: |
| Enforce a rule on every file edit | hooks.PostToolUse with `matcher: "Write\ |
| Deny dangerous commands | hooks.PreToolUse with permissionDecision: deny |
| Give a node domain knowledge | skills: [skill-name] |
| Give a node external tools | mcp: .archon/mcp/server.json |
| Retry flaky API calls | retry: {max_attempts: 3, delay_ms: 2000} |
| Run Python in a node | script: node with runtime: uv, deps: [...] |
| Run TypeScript in a node | script: node with runtime: bun |
| Mix providers in one workflow | Workflow-level provider: claude, per-node provider: codex |
| Use a non-default model for one node | Node-level model: override |
| Run on a 1M context window | model: opus[1m] + betas: ['context-1m-2025-08-07'] |
| Increase per-iteration timeout on a long loop | idle_timeout: 600000 on the loop node |
| Pass large artifacts between nodes | Write to $ARTIFACTS_DIR/..., read in downstream node |
| Pass small structured data | output_format + $nodeId.output.field access |
| Block workflow on an external condition | bash: polling loop or approval: node |
| Spawn parallel sub-tasks inside one node | Inline agents: map (see below) |
| Force isolation regardless of CLI flags | Workflow-level worktree: {enabled: true} |
| Force live checkout for read-only workflows | Workflow-level worktree: {enabled: false} |
Silent Failures (what gets ignored without erroring)
Things that don't fail parsing but don't do what you'd expect:
1. `model` / `provider` on a loop node → silently ignored. Logged as loop_node_ai_fields_ignored. The loop is a controller; set model at workflow level or inside the loop prompt body. 2. `hooks` / `mcp` / `skills` / `output_format` / `allowed_tools` / `denied_tools` on a loop, bash, script, approval, or cancel node → silently ignored. 3. `context: fresh` on a loop → ignored. Use loop.fresh_context: true instead. 4. `output_format` on a bash or script node → schema is accepted but bash/script output is whatever stdout says; no JSON coercion. 5. Unknown `$nodeId.output` reference → resolves to empty string + warning; does not fail the workflow. 6. Invalid `when:` expression → node silently skipped (fail-closed). 7. `allowed_tools` / `denied_tools` on Codex nodes → ignored. Use Codex CLI config (~/.codex/config.toml). 8. `hooks` on Codex nodes → ignored + warning logged. 9. `mcp` or `skills` per-node on Codex → ignored. Configure globally in ~/.codex/config.toml or ~/.agents/skills/. 10. `trigger_rule: all_success` after `when:`-gated fan-out → branches that didn't run count as "not succeeded"; the join node will never fire. Use none_failed_min_one_success or one_success. 11. Node-level `interactive: true` on an approval node or loop, without workflow-level `interactive: true` → on the Web UI, gate messages never reach the user. The workflow dispatches to a background worker that can't deliver chat messages. 12. Missing env var in MCP config → warning logged, node continues with empty string substitution. 13. `retry` on a loop node → this one is a hard parse error (not silent). Use the loop's own max_iterations and until_bash for finish-line detection. 14. `String.raw\`$nodeId.output\`` in a `script:` body → silently corrupts when the substituted value contains a backtick (e.g. markdown code spans in AI output or output_format payloads). The template literal terminates early, producing a cryptic Expected ";" parse error. Use direct assignment instead: const data = $nodeId.output; — JSON is valid JS expression syntax and needs no wrapper.
The pattern across these: if you set an AI feature on a non-AI node, it's silently ignored. Watch loader logs for _ignored warnings when debugging.
Inline agents: (Task-tool sub-agents)
A node can define named sub-agents that Claude invokes via the Task tool. Useful for map-reduce patterns: one node spawns N parallel sub-tasks with a cheap model, then a reducer summarizes.
- id: analysis
prompt: |
For each area of the codebase, delegate to the appropriate sub-agent
via the Task tool. Summarize all findings into a single report.
agents:
security-scanner: # kebab-case id
description: "Scan for common web vulnerabilities"
prompt: "Run OWASP top-10 style checks on the given files"
model: haiku
tools: [Read, Grep, Glob] # tool whitelist for this sub-agent
disallowedTools: [Write, Edit, Bash]
maxTurns: 5
test-coverage-auditor:
description: "Report untested or weakly-tested surfaces"
prompt: "Identify code paths without corresponding tests"
model: haiku
tools: [Read, Grep, Glob]
skills: [test-coverage-patterns] # skill injection per sub-agent
maxTurns: 5Fields per agent:
| Field | Required | Description |
|---|---|---|
description | yes | Shown when Claude decides which agent to delegate to |
prompt | yes | System prompt the sub-agent runs under |
model | no | Per-agent model override |
tools | no | Tool whitelist for the sub-agent |
disallowedTools | no | Tool blacklist |
skills | no | Skills to inject into the sub-agent |
maxTurns | no | Max conversation turns for the sub-agent |
Naming rule: lowercase kebab-case. No leading or trailing hyphens, no double hyphens, no digits-only ids.
When to use `agents:` vs fan-out at the workflow level:
- Use
agents:when the number of sub-tasks is dynamic or decided by the orchestrator node at runtime. - Use workflow-level fan-out (parallel nodes with
depends_on: [setup]) when the sub-tasks are known ahead of time and each needs its own artifact.
See archon.diy/guides/authoring-workflows/#inline-sub-agents for a worked end-to-end example.
Cross-References to Detailed Guides
Use this matrix to find the right parameter. Use these references for the full explanation of how it works.
| Topic | Detailed reference |
|---|---|
| Workflow authoring overview, node base fields | workflow-dag.md |
| Loop nodes in depth (completion, session patterns) | workflow-dag.md § Loop Nodes |
| Approval / cancel nodes | workflow-dag.md § Approval Nodes, § Cancel Nodes |
| Hooks (events, matchers, response shapes) | dag-advanced.md § Hooks |
| MCP (transports, env expansion, wildcards) | dag-advanced.md § MCP |
| Skills (injection, discovery, combining with MCP) | dag-advanced.md § Skills |
| Retry classification (FATAL / TRANSIENT / UNKNOWN) | dag-advanced.md § Retry Configuration |
Variable reference ($ARGUMENTS, $ARTIFACTS_DIR, etc) | variables.md |
| CLI flags and commands | cli-commands.md |
| Command file authoring | authoring-commands.md |
Repo initialization, .archon/config.yaml schema | repo-init.md |
| Good practices and anti-patterns | good-practices.md |
| Interactive workflow relay protocol | interactive-workflows.md |
| Debugging and log locations | troubleshooting.md |
| Full schema reference | archon.diy/reference/configuration/ |
Providers at a Glance
| Feature | Claude | Codex | Pi (community) |
|---|---|---|---|
command / prompt / loop | yes | yes | yes |
bash / script | yes | yes | yes |
output_format | reliable | reliable | best-effort |
allowed_tools / denied_tools | yes | ignored (use Codex CLI config) | ignored |
hooks | yes | ignored + warn | not available |
mcp (per-node) | yes | global ~/.codex/config.toml only | not available |
skills (per-node) | yes | global ~/.agents/skills/ only | not available |
| Model naming | haiku, sonnet, opus, opus[1m] | Codex model ID (e.g. gpt-5.2) | <vendor>/<model> (e.g. anthropic/claude-opus-4-5, openai/gpt-4o, groq/llama-3-70b) |
effort / thinking | yes | use modelReasoningEffort for reasoning models | via effort: (maps to thinking level) |
Session resume / --resume | yes | yes | yes |
Mixing providers in one workflow: set workflow-level provider: claude, then override per-node with provider: codex or provider: pi. Cross-provider $nodeId.output substitution works as expected.
Ten Principles for Safe Workflow Design
1. Always use --branch <name> (or worktree: {enabled: true}) for workflows that modify the codebase. 2. Validate before running: archon validate workflows <name>. 3. Tier your models. Haiku for routing and glue; Sonnet for reasoning and review; Opus only where the context is deep. 4. Use output_format for every node whose output downstream when: reads. Never pattern-match free-form AI text. 5. On Ralph-style loops, use loop.fresh_context: true and treat $ARTIFACTS_DIR as the source of truth. Command bodies should re-read state at the top of every iteration. 6. Use interactive loops for iterative refinement with the human. Use approval: nodes for single-point checkpoints. 7. Read-only analysis phases use denied_tools: [Write, Edit, Bash]. Separation of concerns. 8. Use hooks.PostToolUse to enforce post-change validation (type-check, lint). Tighter feedback loop than end-of-workflow review. 9. Large artifacts go through $ARTIFACTS_DIR. Small structured data goes through $nodeId.output.field. 10. AI can scaffold a workflow. Only a human can verify it. Read the YAML before running.
Initializing Archon in a Repository
Set up the .archon/ directory structure in any git repository to enable custom workflows and commands.
Directory Structure
Create the following in your repository root:
.archon/
├── commands/ # Custom command files (.md)
├── workflows/ # Workflow definitions (.yaml)
├── scripts/ # Named scripts for script: nodes (.ts/.js for bun, .py for uv) — optional
├── mcp/ # MCP server config files (.json) — optional
├── state/ # Cross-run workflow state — gitignored, never committed
├── config.yaml # Repo-specific configuration — optional
└── .env # Repo-scoped Archon env (optional; do NOT commit)mkdir -p .archon/commands .archon/workflows .archon/scriptsWhat each directory is for:
commands/— Reusable prompt templates used bycommand:workflow nodes. Committed to git.workflows/— YAML workflow definitions. Committed to git.scripts/— Named TypeScript/JavaScript (bun) or Python (uv) scripts referenced byscript:nodes. Extension determines runtime:.ts/.js→ bun,.py→ uv. Committed to git.mcp/— MCP server JSON configs. Usually checked in with$ENV_VARreferences; avoid hardcoding secrets. Some teams gitignore this and rely entirely on env expansion.state/— Workflow-written cross-run state (e.g. therepo-triagededup log). Always gitignore — these are runtime artifacts, not source.config.yaml— Repo-specific defaults (assistant, worktree settings, etc.). Committed to git..env— Repo-scoped Archon env (loaded withoverride: trueat boot). Do NOT commit. This is different from the target repo's top-level.env— that file belongs to the target project, and Archon strips its auto-loaded keys from subprocess env before spawning AI to prevent leakage. See Three-Path Env Model below.
Minimal config.yaml
Create .archon/config.yaml only if you need to override defaults:
# AI provider for this repo (default: inherited from global config)
assistant: claude # Repo-level key. In ~/.archon/config.yaml, use 'defaultAssistant' instead
# Worktree settings
worktree:
baseBranch: main # Branch to create worktrees from (default: auto-detected)
copyFiles: # Git-ignored files to copy into new worktrees
- .env
- .env.local
# Control whether bundled defaults are loaded
defaults:
loadDefaultCommands: true # Include bundled default commands (default: true)
loadDefaultWorkflows: true # Include bundled default workflows (default: true)How Bundled Defaults Work
Archon ships with built-in commands and workflows (like archon-assist, archon-fix-github-issue). These are loaded at runtime automatically — no files need to be copied into your repo.
- To see bundled workflows:
archon workflow list - To override a default: Create a file with the same name in your repo's
.archon/workflows/or.archon/commands/. Repo files take priority. - To disable defaults: Set
defaults.loadDefaultWorkflows: falseordefaults.loadDefaultCommands: falsein config.
.gitignore Considerations
Add to your .gitignore:
# Archon runtime artifacts — NEVER commit
.archon/state/ # Cross-run workflow state, runtime-only
.archon/.env # Repo-scoped Archon env (secrets)
# Optional — gitignore if your MCP configs hardcode secrets
.archon/mcp/.archon/commands/, .archon/workflows/, and .archon/scripts/ should be committed — they are part of your project's workflow definitions. .archon/config.yaml should be committed unless it contains secrets (use .archon/.env for those instead).
Three-Path Env Model
Archon loads env from three distinct paths at boot, with different trust levels and precedence:
| Path | Scope | Trust | Loaded? |
|---|---|---|---|
~/.archon/.env | User (home) | Trusted — user owns it | Yes, with override: true |
<cwd>/.archon/.env | Repo (per-project, Archon-owned) | Trusted — user owns it | Yes, with override: true (overrides home) |
<cwd>/.env | Target repo | Untrusted — belongs to the project being worked on | Stripped from `process.env` before subprocess spawn to prevent secret leakage (see archon.diy/reference/security/ for the full trust model) |
Boot behavior emits observable log lines:
[archon] loaded N keys from ~/.archon/.env
[archon] loaded M keys from /path/to/repo/.archon/.env
[archon] stripped K keys from /path/to/repo (ANTHROPIC_API_KEY, OPENAI_API_KEY, ...)Where should you put what?
- API keys for Archon itself (
ANTHROPIC_API_KEY,CLAUDE_CODE_OAUTH_TOKEN,DATABASE_URL,SLACK_BOT_TOKEN, etc.) →~/.archon/.env(shared across all repos) or<cwd>/.archon/.env(per-repo override). - Target-project env that a workflow needs (
GH_TOKEN,DOTENV_PRIVATE_KEY, etc.) → see Per-Project Env Injection below. - Target-project env that Archon should NOT touch → leave it in
<cwd>/.envwhere the project already expects it. Archon strips it from subprocess env but doesn't delete the file.
The archon setup --scope home|project [--force] wizard writes to the right file for you and produces a timestamped backup on every rewrite.
Per-Project Env Injection
For env vars a workflow's bash: and script: subprocesses need (GH_TOKEN for gh calls, DATABASE_URL for a migration script, etc.), use one of the two managed injection surfaces — both inject into subprocess env at workflow execution time, after the target-repo .env strip:
Option 1: `.archon/config.yaml` `env:` block (checked into git; values can be $REF_NAME expansions from Archon env):
env:
GH_TOKEN: $GH_TOKEN # expanded from ~/.archon/.env at runtime
BUILD_TARGET: production # literal valueOption 2: Web UI Settings → Projects → Env Vars — per-codebase, stored in the Archon DB, values never returned over the API (only keys are listed). Use this for values that should NOT appear in git.
Both surfaces inject into: Claude/Codex/Pi subprocess env, bash: node subprocess env, script: node subprocess env, and direct chat messages that run against the codebase. The worktree isolation layer propagates them as well.
About keys in the target repo's `<cwd>/.env`: Archon unconditionally strips the keys auto-loaded from<cwd>/.envout ofprocess.envat boot (see the Three-Path Env Model above) and the Bun subprocess is invoked with--no-env-file, so those values do NOT reach AI / bash / script subprocesses. If a workflow needs a value that currently lives in the target repo's.env, surface it through one of the two managed injection options above — don't expect the target.envto leak through.
Global Configuration
The global config at ~/.archon/config.yaml applies to all repositories. Use guides/config.md for interactive config editing, or create it manually:
botName: Archon
defaultAssistant: claude
assistants:
claude:
model: sonnet
codex:
model: gpt-5.3-codex
modelReasoningEffort: medium
concurrency:
maxConversations: 10Verification
After setting up, verify with:
# Confirm Archon sees your repo
archon workflow list
# Should show bundled workflows + any custom ones you've addedVariable Substitution Reference
Variables are placeholders in command files and workflow prompts that get replaced at execution time.
Variable Table
| Variable | Scope | Description |
|---|---|---|
$ARGUMENTS | All modes | The user's original message passed to the workflow |
$USER_MESSAGE | All modes | Same as $ARGUMENTS — both resolve to the user's message |
$WORKFLOW_ID | All modes | Unique workflow run ID (for tracking and logging) |
$ARTIFACTS_DIR | All modes | Pre-created directory for this workflow run's artifacts. Write outputs here |
$BASE_BRANCH | All modes | Base branch name. Auto-detected from git, or set via worktree.baseBranch in config. Throws if referenced but unresolvable |
$CONTEXT | All modes | GitHub issue/PR context (if available from platform). Empty string if unavailable |
$EXTERNAL_CONTEXT | All modes | Alias for $CONTEXT |
$ISSUE_CONTEXT | All modes | Alias for $CONTEXT |
$nodeId.output | DAG only | Full text output of a completed upstream node |
$nodeId.output.field | DAG only | JSON field access on structured output from upstream node (string/number/boolean) |
Variable Availability
All variables are available in all workflows. The only exception is $nodeId.output / $nodeId.output.field, which is DAG-only (requires an upstream node to reference).
Where Variables Are Substituted
- Command files (
.archon/commands/*.md) — all variables except$nodeId.output - Inline `prompt:` fields — in DAG prompt nodes and loop node prompts
- `bash:` scripts in DAG nodes —
$nodeId.outputreferences are automatically shell-quoted (single-quoted with'escaped) - `script:` bodies in DAG nodes — same substitution as bash, but
$nodeId.outputvalues are NOT shell-quoted. For TypeScript/bun scripts, assign directly (const data = $nodeId.output;) — JSON is valid JS expression syntax. Avoid `String.raw\`$nodeId.output\`` — it silently breaks when the output contains a backtick (common in AI-generated markdown andoutput_formatpayloads).
Substitution Order
1. Standard workflow variables ($WORKFLOW_ID, $ARGUMENTS, $ARTIFACTS_DIR, $BASE_BRANCH, $CONTEXT) 2. Node output references ($nodeId.output, $nodeId.output.field) — DAG mode only
Context Auto-Append
If $CONTEXT / $EXTERNAL_CONTEXT / $ISSUE_CONTEXT is NOT present anywhere in the prompt template but context exists (e.g., from a GitHub issue), it is automatically appended at the end after a --- separator.
Escaped Dollar Signs
Use \$ to produce a literal $ in command files (prevents variable substitution).
Node Output Details (DAG Only)
$nodeId.output resolves to the full text output of the upstream node. If the node used output_format: (structured output), the output is the JSON-stringified result.
$nodeId.output.field parses the output as JSON and extracts the named field. Only works when the upstream node produced structured output via output_format:. Returns the string representation of the field value.
In bash: nodes, $nodeId.output values are automatically shell-escaped before injection to prevent command injection.
Unknown node references resolve to an empty string (with a warning logged).