Skip to content

Configuration

All configuration is via environment variables in .env. See .env.example in the repository for the complete list with comments.

Required Variables

Jira

Variable Description
JIRA_BASE_URL Your Atlassian instance URL (e.g., https://your-org.atlassian.net)
JIRA_USER_EMAIL Service account email
JIRA_API_TOKEN Jira API token
JIRA_WEBHOOK_SECRET Secret for validating Jira webhook signatures

GitHub

Variable Description
GITHUB_TOKEN Personal Access Token with repo and read:org scopes
GITHUB_WEBHOOK_SECRET Secret for validating GitHub webhook signatures
FORGE_BOT_COMMENT_PREFIX Prefix to add to all comments made by the Forge bot (e.g., signature or identifier), also used for webhook self-comment filtering to prevent loops. Note: This configuration is intended to allow development and testing with the same user API keys that are used to comment (to prevent webhook loops), and it should not be used in production. A warning is logged at startup when this is set.

LLM

Use provider-neutral model connections. Gemini 3.5 Flash through Vertex AI is recommended. Connections declare permitted backends, models, locations, and capabilities without containing credentials; providers continue to use their native credential environment variables.

GOOGLE_CLOUD_PROJECT=your-gcp-project
GOOGLE_CLOUD_LOCATION=global
MODEL_CONNECTIONS={"vertex-prod":{"backend":"vertex-ai","project":"your-gcp-project","location":"global","allowed_models":["gemini-3.5-flash"],"capabilities":["structured_output","tools"]}}
MODEL_DEFAULT={"connection":"vertex-prod","model":"gemini-3.5-flash"}
GOOGLE_API_KEY=your-google-api-key
MODEL_CONNECTIONS={"gemini-api":{"backend":"google-genai","allowed_models":["gemini-3.5-flash"],"capabilities":["structured_output","tools"]}}
MODEL_DEFAULT={"connection":"gemini-api","model":"gemini-3.5-flash"}
ANTHROPIC_API_KEY=your-anthropic-api-key
MODEL_CONNECTIONS={"anthropic-prod":{"backend":"anthropic","allowed_models":["claude-sonnet-4-6"],"capabilities":["structured_output","tools"]}}
MODEL_DEFAULT={"connection":"anthropic-prod","model":"claude-sonnet-4-6"}

Forge validates the backend, credentials, model allowlist, capabilities, and default target at startup.

Legacy single-model configuration

Deployments that do not need named connections or per-stage selection can still set LLM_BACKEND and LLM_MODEL instead:

LLM_BACKEND=vertex-ai
GOOGLE_CLOUD_PROJECT=your-gcp-project
GOOGLE_CLOUD_LOCATION=global
LLM_MODEL=gemini-3.5-flash

LLM_BACKEND and LLM_MODEL are required together when MODEL_CONNECTIONS and MODEL_DEFAULT are not configured. Provider credentials must use the provider-native variables shown above; legacy credential aliases are not supported.

The legacy CONTAINER_LLM_MODEL override remains supported. For exact per-stage selection, administrators can add a MODEL_POLICY value to the recommended connection configuration. Jira projects can then set forge.model_policy, restricted to those connections and models:

MODEL_CONNECTIONS={"vertex-global":{"backend":"vertex-ai","project":"my-gcp-project","location":"global","allowed_models":["gemini-3.5-flash","claude-sonnet-5"],"capabilities":["structured_output","tools"]}}
MODEL_DEFAULT={"connection":"vertex-global","model":"gemini-3.5-flash"}
MODEL_POLICY={"generate_prd":{"connection":"vertex-global","model":"claude-sonnet-5"},"generate_spec":{"connection":"vertex-global","model":"gemini-3.5-flash"}}
forge project-setup MYPROJ \
  --model generate_prd=vertex-production:gemini-3.5-pro \
  --model implement_work=anthropic-production:claude-sonnet-4-6

# Set a separate project-wide fallback (individual --model overrides still win)
forge project-setup MYPROJ \
  --model-all vertex-production:gemini-3.5-pro

# Remove one stage override and preserve the rest
forge project-setup MYPROJ --remove-model generate_prd

# Delete all per-stage overrides
forge project-setup MYPROJ --clear-model-policy

# Delete the project-wide fallback
forge project-setup MYPROJ --clear-model-default

# Validate against the local runtime configuration and print every target
forge get-config MYPROJ --models

Project overrides require administrators to configure MODEL_CONNECTIONS. The user-facing project-setup command validates policy syntax and canonical stage names but does not require access to the Forge deployment's connection registry. Forge validates connection names, model allowlists, backends, and capabilities when it executes a stage. Invalid runtime policy fails closed and reports the available configured connections and models to Jira and, when an active PR exists, GitHub. The implicit legacy connection remains restricted to LLM_MODEL and CONTAINER_LLM_MODEL and is never exposed to Jira project policy.

Canonical policy keys are deliberately specific; runtime prompt, skill, and graph-node names are not accepted in Jira configuration:

Policy key Execution
generate_prd Initial PRD generation and every PRD revision
generate_spec Initial specification generation and every specification revision
decompose_epics Epic decomposition or revision
generate_tasks Task generation or revision
bug_triage Bug-report completeness triage
automated_review_triage Classification of automated review feedback
proposal_review_triage Classification of proposal review threads
task_takeover_triage Existing-task takeover triage
task_takeover_planning Existing-task implementation planning
implement_work Container implementation for feature, bug, and task-takeover workflows
task_takeover_review Existing-task qualitative review
task_takeover_question Questions about task-takeover artifacts
analyze_bug Root-cause analysis
reflect_rca Root-cause analysis reflection
plan_bug_fix Bug-fix planning
bug_local_review Local qualitative review of a bug fix
local_code_review Local feature code review
code_review Pull-request code review
implement_review_analysis Analysis of implementation review feedback
implement_review_fix Applying implementation review fixes
generate_pr_description Initial pull-request description generation
sync_pr_description Pull-request description synchronization
ci_analysis CI failure analysis
ci_fix CI failure remediation
answer_question Q&A about PRDs, specifications, plans, and other generated artifacts
rebase Container-assisted rebase conflict resolution
update_docs Documentation update generation

Unknown keys fail validation instead of silently using the default target.

Keeping artifact generation, revision, and Q&A on one model

Revisions reuse the artifact's generation policy key. For example, both initial PRD generation and later ! revision requests resolve generate_prd. Questions submitted with ? do not regenerate the artifact and resolve the separate answer_question key. Configure both keys when the answer must use the same model that created the PRD:

MODEL_POLICY={"generate_prd":{"connection":"vertex-global","model":"claude-opus-4-6"},"answer_question":{"connection":"vertex-global","model":"claude-opus-4-6"}}

forge project-setup MYPROJ \
  --model generate_prd=vertex-global:claude-opus-4-6 \
  --model answer_question=vertex-global:claude-opus-4-6

The same pattern applies to generate_spec, decompose_epics, and generate_tasks: revisions reuse their generation key, while Q&A uses answer_question. Task-takeover artifact questions are the exception and use task_takeover_question.

Some user-visible flows contain multiple model invocations with intentionally different responsibilities. Forge resolves each invocation independently, so they may use different models unless every related key is mapped to the same target:

Flow Policy keys Boundary
Generated artifact interaction generate_prd, generate_spec, decompose_epics, or generate_tasks + answer_question Creation and revision use the generation key; Q&A uses answer_question
Task takeover task_takeover_planning + task_takeover_question Plan creation and revision are separate from artifact Q&A
Automated artifact review automated_review_triage + the relevant generation key Feedback classification occurs before an accepted revision is generated
Proposal review proposal_review_triage + the relevant generation key Review-thread classification occurs before an accepted revision is generated
Implementation review implement_review_analysis + implement_review_fix Feedback analysis and code modification are separate invocations
CI remediation ci_analysis + ci_fix Failure diagnosis and code modification are separate invocations
Bug investigation analyze_bug + reflect_rca + plan_bug_fix Initial analysis, reflection, and repair planning are separate stages
Pull-request maintenance code_review + sync_pr_description Code review and description synchronization are separate tasks

Using different models for these keys is supported and can optimize cost or quality. When context continuity or consistent judgment is more important, assign all keys in the flow to the same connection and model. Run forge get-config MYPROJ --models to display the effective target for every key before testing a workflow.

Forge owns stage capability requirements. Every stage requires a connection declaring "capabilities": ["tools"] except the explicitly tool-free text or classification stages automated_review_triage, proposal_review_triage, generate_pr_description, and sync_pr_description. Jira policy cannot weaken that requirement. Per-target max_output_tokens is limited to 131072.

Resolution is project stage override (forge.model_policy), then the separate project-wide fallback (forge.model_default), then the deployment stage mapping (MODEL_POLICY), then the deployment default (MODEL_DEFAULT). Project policy does not use a * key. --model-all writes forge.model_default and does not modify per-stage overrides. When --model-policy and --model are combined, individual --model entries overwrite matching JSON keys. Used without --model-policy, --model preserves the project's other existing stage overrides; --model-policy deliberately replaces the full stage property. --remove-model removes only the named stage and deletes forge.model_policy when no overrides remain. --clear-model-policy deletes all per-stage overrides, while --clear-model-default independently deletes the project-wide fallback. When MODEL_CONNECTIONS is configured, Forge fetches the Jira project policy before each host or container agent execution, so changes apply automatically to the next stage or retry. The target remains fixed during that execution's internal model/tool loop. Legacy and global-only configurations make no extra Jira policy request. Projects without forge.model_policy fall back to the global stage mapping, then the global default, and finally the legacy LLM_BACKEND/LLM_MODEL settings.

Redis

Variable Default Description
REDIS_URL redis://localhost:6380/0 Redis connection URL

Operator APIs

Variable Description
FORGE_OPERATOR_TOKEN Bearer token required for execution and Org Pulse read APIs. The routes are disabled when it is empty.
EFFECT_OPERATOR_TOKEN Bearer token required for durable-effect inspection and replay APIs. The routes are disabled when it is unset.

Use distinct values when different operators should have workflow-read versus effect-replay authority. See operations for recovery rules.

Per-Project Repository Configuration

Production requirement

In production, Forge reads repository configuration from Jira project properties, not from environment variables. If not configured, Forge blocks the workflow and posts setup instructions on the ticket.

Set these properties per Jira project via the REST API:

# Available repos for this project
curl -X PUT \
  "https://your-org.atlassian.net/rest/api/3/project/MYPROJ/properties/forge.repos" \
  -H "Content-Type: application/json" \
  -u "you@example.com:YOUR_API_TOKEN" \
  -d '["org/repo1", "org/repo2"]'

# Alternatively, configure a repository with additional metadata (like enabling draft PRs) using an object:
curl -X PUT \
  "https://your-org.atlassian.net/rest/api/3/project/MYPROJ/properties/forge.repos" \
  -H "Content-Type: application/json" \
  -u "you@example.com:YOUR_API_TOKEN" \
  -d '[
    "org/repo1",
    {
      "name": "org/repo2",
      "draft": true
    }
  ]'

# Default repo when no explicit assignment is made
curl -X PUT \
  "https://your-org.atlassian.net/rest/api/3/project/MYPROJ/properties/forge.default_repo" \
  -H "Content-Type: application/json" \
  -u "you@example.com:YOUR_API_TOKEN" \
  -d '"org/repo1"'

Setting up via the Forge CLI

Instead of using raw curl requests, you can use the forge project-setup CLI command to configure these properties. When running in automation, use the --json flag to retrieve structured mutation output:

# Set default repository and output changes as pretty-printed JSON
forge project-setup MYPROJ --default-repo org/repo1 --json

Output format on success:

{
  "project": "MYPROJ",
  "mutations": {
    "forge.default_repo": {
      "operation": "set",
      "value": "org/repo1"
    }
  }
}

This JSON output is easily consumable with tools like jq:

# Get the mutated value of a specific property using jq
forge project-setup MYPROJ --default-repo org/repo1 --json | jq '.mutations["forge.default_repo"].value'
# Output: "org/repo1"

Error Handling in JSON Mode

When running with --json, if an error or exception occurs during execution: - Standard output (stdout) is completely suppressed and remains empty. - The error description is written directly to standard error (stderr). - The command exits with a non-zero exit code (1).

Repository labels on managed tickets use repo:<owner>/<repo>. Forge validates that assignment against the project's configured repositories before workspace setup or implementation. A missing or invalid assignment blocks the workflow instead of selecting a repository implicitly.

If the deployment uses FORGE_REPOS_CONFIG_PATH to load a repos.yaml registry, the process caches that registry for its lifetime. Restart the gateway and every worker after changing the file. See operations for the safe deployment and recovery model.

GitLab repositories use explicit connections (there is no implicit GitLab default), which supports both GitLab.com and self-managed instances:

Set base_url to either the GitLab host/root URL (including any self-managed path prefix) or an explicit REST API v4 URL. Forge normalizes host/root URLs by appending /api/v4; explicit URLs ending in /api/v4 are accepted as-is.

connections:
  engineering-gitlab:
    provider: gitlab
    base_url: https://gitlab.example.com
    credential_env: ENGINEERING_GITLAB_TOKEN
    webhook_secret_env: ENGINEERING_GITLAB_WEBHOOK_SECRET
repositories:
  payments-api:
    provider: gitlab
    connection: engineering-gitlab
    namespace: platform/payments-api
    default_branch: main
    change_request_mode: direct

Proposal review configuration

Projects can opt into GitHub pull-request review for PRDs and specifications. Set forge.prd_proposals_repo to an owner/repo repository and optionally set forge.prd_proposals_path to a base directory. Forge then creates prd.md and design.md under {path}/{TICKET}/ on separate proposal branches; merge is approval and review feedback requests regeneration.

Use forge project-setup MYPROJ --prd-proposals-repo owner/repo to configure the repository and --prd-proposals-path path to configure the base path. Set either option to an empty value to remove/reset it. When project configuration is not required, PRD_PROPOSALS_REPO and PRD_PROPOSALS_PATH provide global fallbacks. See proposal review for the distinction between this workflow behavior and core-project design proposals.

Local Development Overrides

Use these to skip the Jira project property requirement during local development:

Variable Description
FORGE_REQUIRE_PROJECT_CONFIG Set to false to use env var fallbacks instead of Jira project properties
GITHUB_DEFAULT_REPO Default repo (org/repo) when FORGE_REQUIRE_PROJECT_CONFIG=false
GITHUB_KNOWN_REPOS Comma-separated list of known repos

CI and Validation

Variable Description
CI_IGNORED_CHECKS Comma-separated list of check name substrings to permanently ignore (e.g., tide,queue)
CI_MAX_FIX_ATTEMPTS Maximum CI fix attempts before blocking (default: 5)

Container Execution

Variable Description
CONTAINER_IMAGE Container image for task execution (default: forge-dev:latest)
CONTAINER_MEMORY_LIMIT Memory limit for task containers (default: 4g)
CONTAINER_CPU_LIMIT CPU limit for task containers (default: 2)

Auto-Review

Settings for the automatic review loop that runs after skill execution. See the Auto-Review Guide for details.

Variable Default Description
AUTO_REVIEW_MAX_RETRIES 3 Default maximum retry attempts when a skill's review.md doesn't specify max_retries
AUTO_REVIEW_POLL_INTERVAL 5.0 Polling interval in seconds for detecting review cycle files during container execution
AUTO_REVIEW_RECORD_POLLED_FILES (none) Recording mode for polled review cycle files: log logs cycle data at INFO level, copy copies files to recording directory

Observability

Langfuse Tracing

Variable Description
LANGFUSE_PUBLIC_KEY Langfuse public key
LANGFUSE_SECRET_KEY Langfuse secret key
LANGFUSE_HOST Langfuse host (defaults to cloud; set for self-hosted)
LANGFUSE_TRACE_TAGS Comma-separated list of trace attributes to attach as Langfuse tags. Available values: ticket_key, ticket_type, project_id, workflow_step, repo, pr_number, ci_status, event_source, event_type, llm_model. Default: empty (no tags).
LANGFUSE_TRACE_METADATA Comma-separated list of trace attributes to attach as Langfuse metadata. Available values: same as tags plus retry_count, system_prompt_length. Default: empty (no metadata).

Grafana Dashboards

These variables are used by docker-compose.yml, devtools/docker-compose.dev.yml, and devtools/grafana/compose.grafana.yml.

Variable Description
GRAFANA_PORT Host port for Grafana (default: 3010)
GRAFANA_ADMIN_USER Grafana admin user (default: admin)
GRAFANA_ADMIN_PASSWORD Grafana admin password (default: grafana)
LANGFUSE_DOCKER_NETWORK External Docker/Podman network for self-hosted Langfuse when using devtools/grafana/compose.langfuse-network.yml (default: langfuse_default)
CLICKHOUSE_HOST Langfuse ClickHouse host reachable from the Grafana container
CLICKHOUSE_PORT Langfuse ClickHouse native protocol port (default: 9000)
CLICKHOUSE_DATABASE Langfuse ClickHouse database (default: default)
CLICKHOUSE_USER Langfuse ClickHouse user
CLICKHOUSE_PASSWORD Langfuse ClickHouse password
PROMETHEUS_HOST Prometheus host for standalone Grafana compose
PROMETHEUS_PORT Prometheus port for standalone Grafana compose
REDIS_HOST Redis host for standalone Grafana compose
REDIS_PORT Redis port for standalone Grafana compose

MCP Servers

MCP server configuration lives in mcp-servers.json, not .env. See the MCP servers section of the repository.

test-skill Commands

Local skill testing and evaluation. See Testing Skills Locally for the full guide.

forge test-skill run

Run a skill against test cases using deepagents.

Flag Required Description
--skill NAME Yes Skill name (e.g., generate-prd)
--skill-dir PATH Yes Path to skill directory containing SKILL.md
--output DIR Yes Output directory for results and trace
--input FILE One of input/dataset Single input.yaml test case
--dataset DIR One of input/dataset Directory of test cases (runs all)
--project NAME No Project name for skill path (overrides config.yaml)
--model MODEL No Override model (default: from config.yaml)
--references FILE No JSON file with reference docs (same format as forge.references)
--repos DIR [DIR...] No Local repo directories to copy into workspace
--mlflow URI No MLflow tracking URI for auto-tracing
--mlflow-experiment NAME No MLflow experiment name (default: forge-skill-eval)

forge test-skill eval

Evaluate skill outputs against gold standards. See Skill Evaluation for criteria format.

Flag Required Description
--criteria FILE Yes Path to criteria YAML file
--output DIR Yes Output directory for reports
--generated FILE Single mode Path to generated artifact
--gold FILE Single mode Path to gold standard artifact
--dataset DIR Batch mode Dataset directory
--results-dir DIR Batch mode Runner output directory
--mlflow URI No MLflow tracking URI
--mlflow-experiment NAME No MLflow experiment name