Skip to content

Configuration

The .forgeplan/config.yaml file is the single configuration point for a Forgeplan workspace. This page is the authoritative reference for every top-level key, every nested section, and every environment variable recognised by the CLI and MCP server.

All sections are optional except the top-level metadata (version, project_name, default_depth, id_digits, created_at). Missing sections fall back to safe defaults baked into forgeplan-core.

After forgeplan init -y, the .forgeplan/ directory is created next to your code:

.forgeplan/
├── config.yaml ← workspace config (GITIGNORED — contains env refs)
├── adrs/ ← git-tracked markdown artifacts (source of truth)
├── rfcs/
├── prds/
├── epics/
├── specs/
├── problems/
├── solutions/
├── evidence/
├── notes/
├── refresh/
├── memory/ ← decision journal (git-tracked)
├── lance/ ← GITIGNORED — derived LanceDB index (rebuildable)
└── .fastembed_cache/ ← GITIGNORED — embedding model cache

Per ADR-003, markdown files are the source of truth; lance/ is a derived index you can rebuild at any time with forgeplan scan-import. Never commit lance/, .fastembed_cache/, or config.yaml — they are listed in the default .gitignore.

version: 1
project_name: ForgePlan
default_depth: standard
id_digits: 3
created_at: 2026-03-24
FieldTypeDefaultDescription
versionu321Config schema version. Bumped only on breaking schema migrations.
project_namestring""Human-readable project name. Shown in forgeplan health, reports, and export.
default_depthenumstandardDefault depth used by forgeplan route when heuristics are inconclusive. One of tactical, standard, deep, critical.
id_digitsu323Zero-padding width for artifact IDs (e.g. PRD-001 vs PRD-0001). Change only at workspace creation — existing IDs are not renumbered.
created_atdatetodayYYYY-MM-DD when the workspace was initialised. Read-only metadata.
ValueWhen to use
tacticalQuick fix, reversible in a day. No artefact required.
standardFeature 1–3 days, one clear tradeoff. PRD -> RFC pipeline. ADI recommended.
deepNew module, 1–2 weeks. PRD -> Spec -> RFC -> ADR. ADI mandatory.
criticalCross-team subsystem, strategic. Epic -> N artifacts. ADI + adversarial review.

See Depth Calibration guide for routing heuristics.

Used by forgeplan generate, forgeplan reason (ADI), forgeplan route (Level 1+), and MCP tools that call an LLM.

llm:
provider: gemini
model: gemini-3-flash-preview
api_key_env: GEMINI_API_KEY
# base_url: https://... # override for custom endpoints
# max_tokens: 4096
# temperature: 0.7
# reason_temperature: 0.3 # lower temp for structured ADI output
FieldTypeDefaultDescription
providerenumopenaiOne of openai, claude, gemini, ollama, or custom. Determines default base URL and header style.
modelstringgpt-4o-miniModel identifier passed verbatim to the provider. See recommended models below.
api_key_envstring?provider-specificName of the environment variable holding the API key. If omitted, a provider-specific default is used.
base_urlstring?provider-specificOverride base URL for self-hosted or proxy endpoints. Useful for Ollama, LiteLLM, or Azure-compatible gateways.
max_tokensu324096Max response tokens. Increase for long ADI reasoning; decrease to save cost.
temperaturef320.7Sampling temperature for generate. 0.0 = deterministic, 1.0 = creative.
reason_temperaturef32?Override used only by forgeplan reason. Structured ADI output benefits from a lower value (typically 0.20.3). Falls back to temperature if unset.
ProviderDefault API key envDefault base URLNotes
openaiOPENAI_API_KEYhttps://api.openai.com/v1OpenAI-compatible.
claudeANTHROPIC_API_KEYhttps://api.anthropic.com/v1Uses Anthropic-specific headers automatically.
geminiGEMINI_API_KEYhttps://generativelanguage.googleapis.com/v1beta/openaiUses Google’s OpenAI-compatible shim.
ollama— (none)http://localhost:11434/v1Fully local. No API key required.
customYou must set base_url and api_key_env explicitly.
ProviderModelWhen to use
Geminigemini-3-flash-previewDefault — fast, cheap, strong ADI output (currently used by the Forgeplan repo itself).
Geminigemini-3-proDeep reasoning, critical decisions, long context.
OpenAIgpt-5-miniBalanced price/quality for generate + route.
OpenAIgpt-5Critical ADI, adversarial review.
Anthropicclaude-haiku-4-5-20251001Cheap routing and classification.
Anthropicclaude-sonnet-4-6Default for generate + reason.
Anthropicclaude-opus-4-6Critical decisions, long-form reasoning.

The following environment variables override llm: fields at runtime without editing config.yaml:

Env varOverrides
FORGEPLAN_LLM_PROVIDERprovider
FORGEPLAN_LLM_MODELmodel
FORGEPLAN_LLM_BASE_URLbase_url
FORGEPLAN_LLM_MAX_TOKENSmax_tokens
FORGEPLAN_LLM_API_KEY_ENVapi_key_env (name, not value)

Priority: env var > config.yaml > default.

Configures the embedding model used for semantic search and the FPF KB vector index. Requires the semantic-search feature flag at build time (included in official release binaries).

embedding:
model: bge-m3
chunk_size: 2000
FieldTypeDefaultDescription
modelenumbge-m3Embedding model name. See table below.
chunk_sizeusize2000Max characters of artefact body included in the embedding text. Larger values give richer embeddings at the cost of cache size and ingestion time.
ModelDimLanguagesWhen to pick
bge-m31024Multilingual (100+)Default — best quality, supports Russian + English mixed workspaces.
bge-small-en384English onlyFastest, smallest cache. Pick for English-only projects on low-RAM machines.
multilingual-e5-small384MultilingualMiddle ground — faster than bge-m3, still multilingual.
multilingual-e5-base768MultilingualHigher quality than e5-small at ~2x cost.
Env varOverrides
FORGEPLAN_EMBEDDING_MODELmodel

If the semantic-search feature is disabled at build time, Forgeplan still runs — it silently falls back to BM25 keyword search. See the Search guide for details on the hybrid search stack.

storage:
driver: lancedb
# path: /custom/path # override DB location
FieldTypeDefaultDescription
driverenumlancedbStorage backend. See table below.
pathstring?.forgeplan/lance/Override the LanceDB directory. Useful to keep the derived index outside the project tree (e.g. ~/.cache/forgeplan/myproj).
DriverUse case
lancedbDefault — embedded columnar DB with native vector search. Persists to lance/. Recommended for all real projects.
sqliteLegacy / lightweight fallback. No vector search.
memoryIn-memory only, lost on process exit. Used by tests and ephemeral CI runs.
Env varOverrides
FORGEPLAN_STORAGE_DRIVERdriver
FORGEPLAN_STORAGE_PATHpath
memory:
driver: file
FieldTypeDefaultDescription
driverenumfileMemory bank driver. file persists to .forgeplan/memory/. none disables the decision journal entirely.
Env varOverrides
FORGEPLAN_MEMORY_DRIVERdriver

Configures forgeplan estimate — the multi-grade estimation model that combines your domain expertise with AI task-type multipliers. Every field is optional; omit the whole section to use defaults.

estimate:
grade_profile:
backend: middle # your grade in backend development
frontend: junior # your grade in frontend
devops: senior # your grade in devops/infra
ai_ml: principal # your grade in AI/ML
default: senior # fallback for unspecified domains
grade_multipliers:
junior: 2.0 # relative to senior (baseline 1.0)
middle: 1.5
senior: 1.0
principal: 0.7
ai: 0.4 # conservative AI base multiplier
ai_task_multipliers:
pure_coding: 0.10 # AI does coding ~10x faster
coding_infra: 0.25 # mixed coding + infrastructure
design_coding: 0.30 # design + implementation
pure_infra: 0.50 # infrastructure only
coordination: 1.00 # meetings, reviews — AI can't help
review_overhead: 0.30 # 30% added to AI time for human review
safety_margin: 0.50 # warn if sprint > 50% loaded
FieldTypeDefaultDescription
grade_profilemap<string, grade>Per-domain developer grade. Keys are free-form domain names; at minimum define default.
grade_multipliersmap<string, f64>see belowTime multiplier per grade, relative to a senior baseline of 1.0.
ai_task_multipliersmap<string, f64>see belowFraction of human time AI takes for each task type.
review_overheadf640.30Fraction added to AI-assisted time to cover human review. 0.30 = 30%.
safety_marginf640.50Sprint capacity threshold. Forgeplan warns if the sprint load exceeds this. 0.50 = 50%.
GradeDefault multiplierMeaning
junior2.0Learning the domain — takes 2x a senior’s time.
middle1.5Can ship independently — 1.5x a senior.
senior1.0Baseline.
principal0.7Deep domain expert — 30% faster than senior.
ai0.4AI as a virtual collaborator — conservative base. Refined by ai_task_multipliers.
Task typeDefaultTypical work
pure_coding0.10Writing pure code — functions, tests, refactors. AI excels here.
coding_infra0.25Coding mixed with tooling (CI, scripts, configs).
design_coding0.30Design decisions + implementation.
pure_infra0.50Infra-only work — AI helps but human validates each step.
coordination1.00Meetings, reviews, stakeholder alignment. AI cannot help.

A senior backend engineer estimates a task at 8 hours. AI handles the task as pure_coding:

raw_time = 8h × grade_multipliers.senior = 8h × 1.0 = 8h
ai_time = 8h × ai_task_multipliers.pure_coding = 8h × 0.10 = 0.8h
with_review = 0.8h × (1 + review_overhead) = 0.8h × 1.30 = 1.04h

Final estimate: ~1h of human-facilitated AI time.

See forgeplan estimate for the CLI reference.

Tunes the FPF Engine: explore/exploit thresholds, reliability weights, congruence-level penalties, and ADI reasoning caps. Every sub-field has safe defaults — tune only if you have empirical reason to.

fpf:
weights:
reff: 0.5
links: 0.3
freshness: 0.2
thresholds:
explore_reff: 0.01
investigate_reff: 0.5
exploit_reff: 0.7
exploit_fgr: 0.6
explore_fgr: 0.4
cl_penalties:
cl0: 0.9
cl1: 0.4
cl2: 0.1
cl3: 0.0
decay:
expired_score: 0.1
adi:
max_hypotheses: 5
kb_sections_limit: 5
temperature_cap: 0.3
auto_save: true

fpf.weights — Reliability component weights

Section titled “fpf.weights — Reliability component weights”

Components of the reliability score inside F-G-R. Values do not need to sum to 1.0, but conventionally do.

FieldDefaultMeaning
reff0.5Weight of the R_eff score (evidence quality).
links0.3Max bonus awarded for incoming/outgoing typed links.
freshness0.2Bonus if the artefact is not stale (valid_until in the future).

fpf.thresholds — Explore/Exploit cutoffs

Section titled “fpf.thresholds — Explore/Exploit cutoffs”

Decision thresholds used by hardcoded rules and by forgeplan route.

FieldDefaultAction triggered
explore_reff0.01R_eff below this -> EXPLORE (treat as draft).
investigate_reff0.5R_eff below this -> INVESTIGATE (needs more evidence).
exploit_reff0.7R_eff at or above this -> eligible for EXPLOIT (safe to rely on).
exploit_fgr0.6F-G-R overall required to confirm EXPLOIT (combined with exploit_reff).
explore_fgr0.4F-G-R below this -> EXPLORE priority 1 (combined with explore_reff).

fpf.cl_penalties — Congruence Level penalties

Section titled “fpf.cl_penalties — Congruence Level penalties”

Penalty applied to evidence based on how well its context matches the artefact it informs. CL3 (same context) is penalty-free; CL0 (opposed context) is heavily discounted.

FieldDefaultMeaning
cl00.9Opposed context — near-zero trust.
cl10.4Different context — significant discount.
cl20.1Similar context — minor discount.
cl30.0Same context — no penalty.

See Evidence guide for how congruence_level is set on an EvidencePack body.

FieldDefaultMeaning
expired_score0.1Score assigned to evidence past valid_until. 0.1 reflects “stale, not absent” — the evidence existed, just needs re-verification.

Controls forgeplan reason behaviour.

FieldTypeDefaultMeaning
max_hypothesesu325Maximum number of competing hypotheses the LLM must generate during the Abduction phase.
kb_sections_limitusize5Max FPF KB sections injected into the ADI prompt. Higher = richer context, more tokens.
temperature_capf320.3Upper bound on temperature used for ADI reasoning, regardless of llm.temperature. Keeps ADI output structured.
auto_savebooltrueAutomatically persist ADI results as an AdiRecord linked to the artefact.

fpf.rules — Declarative explore-exploit rules (advanced)

Section titled “fpf.rules — Declarative explore-exploit rules (advanced)”

Optional list of user-defined explore/exploit rules (FPF Engine Phase 2). When empty, built-in default_rules() are used. Schema and examples live in the FPF rules guide.

Thresholds used by forgeplan health (duplicate detection, stub detection) and DoS-protection limits enforced by the MCP server on incoming forgeplan_new / forgeplan_update calls.

integrity:
duplicate_threshold: 0.7
duplicate_pairs_limit: 10
stub_marker_threshold: 3
mcp_max_title_len: 256
mcp_max_body_len: 1048576 # 1 MiB
FieldTypeDefaultRangeDescription
duplicate_thresholdf640.7[0.0, 1.0]Jaccard similarity above which two artefacts are flagged as duplicates in forgeplan health.
duplicate_pairs_limitusize10[1, 10000]Max duplicate pairs shown in health output (pagination).
stub_marker_thresholdusize3>= 1Minimum number of stub markers (TODO, TBD, empty headings, etc.) required to flag an artefact body as a stub.
mcp_max_title_lenusize256[16, 4096]Max artefact title length accepted via MCP. Prevents memory abuse from malicious clients.
mcp_max_body_lenusize1048576[1024, 104857600]Max artefact body length (bytes) accepted via MCP. Default: 1 MiB. Hard cap: 100 MiB.
VariableSectionEffect
OPENAI_API_KEYllmOpenAI API key (default for provider: openai).
ANTHROPIC_API_KEYllmAnthropic API key (default for provider: claude).
GEMINI_API_KEYllmGemini API key (default for provider: gemini).
FORGEPLAN_LLM_PROVIDERllmOverride llm.provider.
FORGEPLAN_LLM_MODELllmOverride llm.model.
FORGEPLAN_LLM_BASE_URLllmOverride llm.base_url.
FORGEPLAN_LLM_MAX_TOKENSllmOverride llm.max_tokens.
FORGEPLAN_LLM_API_KEY_ENVllmOverride llm.api_key_env (name of the env var).
FORGEPLAN_EMBEDDING_MODELembeddingOverride embedding.model.
FORGEPLAN_STORAGE_DRIVERstorageOverride storage.driver.
FORGEPLAN_STORAGE_PATHstorageOverride storage.path.
FORGEPLAN_MEMORY_DRIVERmemoryOverride memory.driver.

API keys themselves are never stored in config.yaml — only the name of the env variable is stored under api_key_env. This keeps the config file safe to share across machines (once .forgeplan/config.yaml itself is in .gitignore).

Terminal window
# 1. Export all artefacts to a portable JSON bundle
forgeplan export --output backup.json
# 2. Keep a directory-level backup of the whole workspace
cp -r .forgeplan .forgeplan-backup-$(date +%Y%m%d)
# 3. Only now it's safe to reinit
rm -rf .forgeplan
forgeplan init -y
# 4. Restore artefacts
forgeplan import backup.json
Terminal window
git clone <repo> && cd <repo>
forgeplan init -y # creates .forgeplan/config.yaml + empty lance/
$EDITOR .forgeplan/config.yaml # set llm.provider, model, api_key_env
export GEMINI_API_KEY=... # or whichever provider you chose
forgeplan scan-import # rebuilds lance/ from tracked markdown
forgeplan list # verify artefacts are back

AI agents (Claude Code, Codex, others) running Forgeplan must always use:

Terminal window
forgeplan init -y # NEVER interactive — -y is required

Interactive mode will hang in an agent harness. The -y flag accepts all defaults and writes a minimal config.yaml, which the agent can then edit.

error: LLM API key not set — expected env var GEMINI_API_KEY

Cause: llm.api_key_env points to an unset variable, or the provider default env var is unset.

Fix:

Terminal window
export GEMINI_API_KEY=your-key # for current shell
# or
export FORGEPLAN_LLM_API_KEY_ENV=MY_CUSTOM_KEY
export MY_CUSTOM_KEY=your-key

Use forgeplan health to confirm the LLM subsystem reports “ready”.

Cause: provider rate limits (Gemini free tier is especially tight).

Fix:

  1. Lower llm.max_tokens to reduce per-request cost.
  2. Switch to a cheaper model (gemini-3-flash-preview, gpt-5-mini, claude-haiku-4-5-20251001).
  3. Retry with exponential backoff — Forgeplan surfaces the provider error verbatim so you can distinguish 429 from 5xx.

Embeddings fail to load / semantic search returns empty

Section titled “Embeddings fail to load / semantic search returns empty”

Cause: one of:

  • Forgeplan binary was built without the semantic-search feature (check forgeplan --version).
  • embedding.model was changed and lance/ was not reindexed.
  • .fastembed_cache/ is corrupted.

Fix:

Terminal window
rm -rf .forgeplan/.fastembed_cache
forgeplan scan-import # re-downloads model + reindexes

If semantic search is unavailable, Forgeplan falls back to BM25 keyword search automatically — no data is lost. See the Search guide for the hybrid stack.

”Invalid config: fpf.thresholds.explore_reff must be finite”

Section titled “”Invalid config: fpf.thresholds.explore_reff must be finite””

Cause: malformed YAML — a numeric field is NaN, Infinity, or a string that didn’t parse as a number.

Fix: open .forgeplan/config.yaml and ensure every numeric field under fpf:, estimate:, and integrity: is a plain decimal. Run forgeplan health to revalidate.

”integrity.mcp_max_body_len must be in [1024, 104857600]”

Section titled “”integrity.mcp_max_body_len must be in [1024, 104857600]””

Cause: MCP body limit set outside the allowed range (1 KiB to 100 MiB).

Fix: pick a value inside the range. For most projects, the default (1 MiB) is correct.

Some upgrades add new columns to lance/. The symptom is a LanceDB error on startup.

Fix:

Terminal window
forgeplan export --output backup.json
rm -rf .forgeplan/lance
forgeplan init -y # recreates lance/
forgeplan scan-import # reindex from markdown
# markdown is the source of truth — no artefacts are lost