Beta

Configuration

Dark Factory is configured through godark.yaml in your project root, with CLI flags available as overrides.


godark.yaml

Here's a complete example showing all available fields:

# ── Required ──
repo: owner/my-project

# ── Build Commands (auto-detected by godark init) ──
format_command: "gofmt -w ."
build_command: "go build ./..."
test_command: "go test ./..."
lint_command: "go vet ./..."
generate_command: "go generate ./..."

# ── Agent Behavior ──
model: ""                         # Claude model: "sonnet" (default) or "opus"
max_retries: 3                    # Review/fix retry cycles per issue
max_resume_retries: 2             # At attempt N >= this, start fresh session
max_rebase_attempts: 1            # Auto-rebase cycles before needs-human-review
agent_timeout: "30m"              # Timeout per agent execution
quality_strictness_decay: true    # Relax quality gates on successive retries

# ── Safety ──
protected_paths:                  # Files agents cannot modify
  - godark.yaml
denied_commands:                  # Patterns forbidden in agent execution
  - "rm -rf"
  - "git push --force"
  - "git push -f"
  - "git reset --hard"
  - "git clean -f"
generated_paths:                  # Files agents must not hand-edit (generated)
  - "api/gen/"
  - "**/*.freezed.dart"
enforce_architecture: false       # Reviewer rejects layer violations when true

# ── Paths ──
roadmap_path: "docs/ROADMAP.md"
planning_dir: "docs/planning/"
scenario_dir: "tests/scenarios/"
review_dir: "tests/review/"
architecture_doc: "docs/architecture.md"
architecture_json: "docs/architecture.json"
conventions_doc: "docs/conventions.md"
base_branch: "main"
default_branch: "main"            # Auto-detected from GitHub if omitted
branch_prefix: "godark"           # Prefix for auto-generated branch names
label_prefix: "godark"            # Prefix for GitHub labels

# ── Auth ──
auth_preference: "oauth"          # "oauth" or "api_key"
required_env:                     # Must be set before run starts
  - CUSTOM_API_KEY

Runtime & Docker

Configure the project runtime and Docker sandbox settings:

runtime:
  name: "go"                       # go, flutter, node, rust, python, elixir
  version: "1.26.0"                # Optional — auto-detected if empty

docker:
  image: "ubuntu:22.04"            # Base Docker image
  dockerfile: "Dockerfile.devloop" # Custom Dockerfile (optional)
  mount: "/workspace"              # Container mount point
  user: "devloop"                  # Container user
  node_version: "20"               # Node.js version if needed
  extra_packages:                  # Additional APT packages
    - chromium
    - ffmpeg
  install_commands:                # Custom install commands
    - "pip install -r requirements.txt"

sandbox_env:                       # Environment vars passed to Docker
  GOOS: linux
  GOARCH: arm64

Auto Merge

Merging happens at two points, each with its own strategy:

# issue PR ──┐
# issue PR ──┼──► base branch ──► main
# issue PR ──┘
#             ^                   ^
#        feature merge       rollup merge

auto_merge:
  feature: "none"     # none | low_risk | all
  rollup: "manual"    # none | manual | auto

When base_branch equals your default branch (or isn't set), there is no rollup step — issue PRs merge directly to main and the rollup setting is ignored.

StrategyIssue PRs (feature)Base → Main (rollup)
nonePRs are created but not mergedNo rollup PR created
low_riskMerge if under risk thresholds
allMerge all approved PRs
manualCreate rollup PR, wait for human merge
autoMerge rollup PR automatically

Risk Thresholds

Used by the low_risk feature merge strategy to classify PRs:

risk_thresholds:
  max_lines: 200      # Max changed lines for low_risk classification
  max_files: 10        # Max changed files for low_risk classification

Prompts

Override the default prompt templates for each agent role:

prompts:
  implementer: "prompts/implementer.txt"
  implementer_retry: "prompts/implementer_retry.txt"
  reviewer: "prompts/reviewer.txt"
  quality_reviewer: "prompts/quality_reviewer.txt"
  spec_generator: "prompts/spec_generator.txt"
  punchlist: "prompts/punchlist.txt"
  verify_fix: "prompts/verify_fix.txt"
  recon: "prompts/recon.txt"

Prompt templates support template variables that are populated at runtime with issue data, file paths, and configuration values.


Modules

For monorepos or multi-module projects, override build commands per module:

modules:
  backend:
    build_command: "go build ./..."
    test_command: "go test ./..."
    lint_command: "go vet ./..."
    depends_on: ["core"]
  frontend:
    build_command: "npm run build"
    test_command: "npm test"
    lint_command: "eslint ."
  core:
    build_command: "go build ./..."
    test_command: "go test ./..."

Module names must match ^[a-zA-Z0-9._-]+$. Dependencies are validated for cycles.


Quality & Verification

quality:
  min_review_cost_usd: 0.0          # Quality gate: minimum review cost (0 = disabled)
  min_review_duration_seconds: 0    # Quality gate: minimum review duration (0 = disabled)

verify:
  max_fix_attempts: 2               # Fix cycles per verify failure
  blocking: true                    # Verify failures block merge

truncation:
  verify_output: 4096               # Max bytes from verify command output
  pr_diff: 30000                    # Max bytes from PR diff in prompts

CI Checks

Wait for CI checks to pass before merging:

wait_for_checks:
  timeout: "10m"                    # Max wait time (Go duration string)
  required:                         # CI check names to wait for
    - "test"
    - "lint"
    - "build"

Notifications

Get notified about run events. Environment variable references (${VAR}) are expanded from the host environment:

notify:
  - provider: "telegram"
    events:
      - "run_complete"
      - "implementation_complete"
      - "abort"
    settings:
      bot_token: "${TELEGRAM_BOT_TOKEN}"
      chat_id: "${TELEGRAM_CHAT_ID}"

Watch Mode

watch:
  poll_interval: "60s"              # How often to check for review feedback

Judge (Container Health Monitor)

The judge monitors agent containers for hangs, tool thrashing, and transport failures. Disable with --no-judge on the CLI.

judge:
  enabled: true                        # Enable/disable the judge
  default_idle_timeout: 300            # Seconds before killing an idle container
  idle_timeout_by_role: {}             # Per-role overrides (e.g. implementer: 600)
  default_no_progress_timeout: 0       # Seconds with no progress before kill (0 = disabled)
  no_progress_timeout_by_role: {}      # Per-role overrides
  tool_thrash_threshold: 3             # Repeated tool calls to trigger thrash detection
  tool_thrash_window_secs: 60          # Window for thrash detection
  transport_failure_threshold: 10      # Max consecutive transport failures
  container_retry_limit: 2             # Max container restarts before giving up

Docker Compose

Bring up dependent services (databases, caches, etc.) alongside agent containers:

docker_compose:
  file: "docker-compose.test.yml"      # Path to compose file (required)
  project_name: ""                     # Optional prefix (auto-generated if empty)
  services:                            # Optional service descriptions
    - name: postgres
      description: "PostgreSQL 16 test database on port 5432"
    - name: redis
      description: "Redis 7 cache on port 6379"

Host Services

Declare services running on the host that agents depend on. Health checks run before each agent execution:

host_services:
  - name: supabase
    description: "Supabase local stack"
    health_check:
      command: "curl -sf http://localhost:54321/rest/v1/"
      timeout: "5s"
      retries: 3

GitHub Authentication

Godark resolves a GitHub token using the following priority:

  1. GitHub App installation token - all three GODARK_APP_* variables set
  2. GH_TOKEN - a personal access token exported in the environment
  3. gh auth token - falls back to the GitHub CLI's stored credential

App auth is preferred for shared or team use: installation tokens are short-lived, rotate automatically before each agent launch, and commits are attributed to the App's bot account (godark-runner[bot]) instead of a human user.

GitHub App Setup

Once IT (or an org admin) provisions a GitHub App and installs it on the target repository, you'll have an App ID, an Installation ID, and a downloaded .pem private key. Configure godark in three steps:

1. Save the private key to disk.

mkdir -p ~/.godark
mv ~/Downloads/your-app.*.private-key.pem ~/.godark/github-app.pem
chmod 600 ~/.godark/github-app.pem

2. Export the three environment variables (add these to ~/.zshrc or ~/.bashrc):

export GODARK_APP_ID=<App ID>
export GODARK_APP_INSTALLATION_ID=<Installation ID>
export GODARK_APP_PRIVATE_KEY_PATH="$HOME/.godark/github-app.pem"

All three must be set together. If any one is missing, godark silently falls back to GH_TOKEN / gh auth - it does not partially use App config.

3. (Optional) Keep GH_TOKEN for personal gh CLI use. When App creds are present, godark mints an installation token and overrides GH_TOKEN only within its own process and the containers it spawns. Your interactive shell's GH_TOKEN is untouched, so gh commands you run yourself still use your PAT.

App Configuration

Repository permissions the App needs:

Other settings:

Once the App is created and installed on the target repo, the three values godark needs are:


Environment Variables

VariablePurposeRequired
ANTHROPIC_API_KEYAnthropic API authenticationIf OAuth not set
CLAUDE_CODE_OAUTH_TOKENAnthropic OAuth token (preferred)If API key not set
GH_TOKENGitHub authentication (PAT)If App auth not configured
GODARK_APP_IDGitHub App ID (app-based auth)App auth: all three required
GODARK_APP_INSTALLATION_IDGitHub App installation IDApp auth: all three required
GODARK_APP_PRIVATE_KEY_PATHPath to GitHub App private key (PEM)App auth: all three required

See GitHub Authentication for how App creds and GH_TOKEN interact. Additional variables listed in required_env must be set or the run will fail. These are forwarded into the Docker sandbox automatically.