.oat Directory Structure
This document is the canonical reference for what lives under .oat/, what each file or directory does, and which parts are source-of-truth vs generated runtime state.
Scope model
OAT uses two scopes for .oat data:
- Project scope:
<repo>/.oat/ - User scope:
~/.oat/
Project scope is used for project workflows and repo-local sync state. User scope is used for global ideas and user-level sync state.
Top-level project .oat/ layout
.oat/
config.json
config.local.json
projects/
shared/
local/
archived/
ideas/
sync/
manifest.json
config.json
templates/
scripts/
repo/
knowledge/
pjm/
reference/
reviews/
archive/Top-level entries
| Path | Purpose | Notes |
|---|---|---|
.oat/config.json | Shared repo runtime config for non-sync settings | Includes worktrees.root, projects.root, git.defaultBranch, archive.*, and documentation.* |
.oat/config.local.json | Local per-developer runtime state | Gitignored; includes activeProject, lastPausedProject, activeIdea |
.oat/state.md | Generated repo state dashboard | Gitignored; rebuilt with oat state refresh from config, project artifacts, and knowledge metadata |
.oat/projects/ | OAT project artifacts | shared, local, archived scopes |
.oat/ideas/ | Project-level ideas store | Often gitignored |
.oat/sync/ | Interop sync state/config | See details below |
.oat/templates/ | Artifact templates used by OAT skills | Source for scaffolding. Includes docs-app-fuma/ (Fumadocs) and docs-app-mkdocs/ (MkDocs) templates. |
.oat/repo/ | Repo-level PJM/knowledge/reference/review artifacts | Active PJM state under pjm/; durable references (including decisions) under reference/ |
.oat/sync/ details
| Path | Purpose |
|---|---|
.oat/sync/manifest.json | Records sync-managed provider entries and drift contract state |
.oat/sync/config.json | Sync behavior config (default strategy + provider-level settings) |
config.json currently includes:
versiondefaultStrategyproviders.<provider>.enabledproviders.<provider>.strategy(optional override)
Primary ways this file is managed:
oat init --scope project(interactive provider selection)oat providers set --scope project --enabled ... --disabled ...
Config ownership (current)
Current config ownership:
.oat/config.jsonowns shared non-sync repo settings (includingworktrees.root,projects.root, anddocumentation.*)..oat/config.local.jsonowns per-developer project lifecycle state (activeProject,lastPausedProject,activeIdea).~/.oat/config.jsonowns user-level state (activeIdeaat global scope)..oat/sync/config.jsoncontinues to own sync/provider behavior.
CLI discovery surfaces:
oat config describelists the supported config surfaces and keys across shared repo, repo-local, user, and sync/provider config.oat config describe <key>prints scope, file, default, mutability, owning command, and description for one config key.oat config listprints the resolved values for the repo-scoped/local command surface.
Legacy .oat/active-project / .oat/projects-root / .oat/active-idea files may still be present in some environments but are no longer the canonical source in migrated command paths.
.oat/config.json schema
Current schema keys:
| Key | Type | Default | Description |
|---|---|---|---|
version | number | 1 | Schema version |
worktrees.root | string | ".worktrees" | Root directory for git worktrees (repo-relative or absolute) |
projects.root | string | ".oat/projects/shared" | Default root directory for OAT projects |
localPaths | string[] | - | Gitignored directories to sync between main repo and worktrees. Supports glob patterns. Managed via oat local add/remove. |
documentation.root | string | - | Root directory containing documentation source files (e.g., apps/docs/docs) |
documentation.tooling | string | - | Documentation framework identifier (mkdocs or fumadocs) |
documentation.config | string | - | Path to the documentation framework config file (e.g., mkdocs.yml, next.config.js) |
documentation.index | string | - | Path to the docs surface entry point (e.g., index.md for Fumadocs, mkdocs.yml for MkDocs). Set by oat docs init and updated by oat docs generate-index. |
documentation.requireForProjectCompletion | boolean | false | When true, OAT project completion gates require documentation to be updated |
git.defaultBranch | string | "main" | Default branch for PR creation. Auto-detected during oat init via gh repo view or origin/HEAD. Used by oat-project-pr-final and oat-project-pr-progress. |
workflow.autoReviewAtHillCheckpoints | boolean | unset | When true, completing a HiLL checkpoint automatically runs the extra lifecycle review. Does not control Tier 1 per-phase oat-reviewer gates. Can be overridden per-project via oat_auto_review_at_hill_checkpoints in plan.md frontmatter. Legacy autoReviewAtCheckpoints remains a fallback. |
workflow.dispatchPolicy.mode | string | unset | Dispatch policy mode: managed lets OAT select model/effort controls; inherit leaves controls to the host/provider defaults. |
workflow.dispatchPolicy.policy | string | unset | Managed dispatch policy: economy, balanced, high, frontier, or uncapped. Capped policies compile to provider targets; uncapped keeps OAT-managed preferred selection without provider caps. inherit mode is separate and leaves controls to the host/provider. |
workflow.dispatchCeiling.preset | string | unset | Legacy compatibility preset for capped managed policy setup (balanced, maximum, cost-conscious). maximum maps to high; cost-conscious maps to economy. |
workflow.dispatchCeiling.providers.<provider> | object or legacy scalar | unset | Reusable provider candidate ladder. The canonical shape maps economy, balanced, high, and frontier to ordered candidate cells; project and phase state record only a named maximum over that ladder. |
workflow.dispatchCeiling.providers.<provider>.<tier> | { candidates: [...] } | unset | One ordered candidate cell. Codex entries carry exact model plus effort and resolve to materialized roles; Claude entries carry a model; Cursor strings remain opaque and pass to Cursor byte-for-byte. The final candidate defines that tier's reviewer ceiling. |
workflow.dispatchCeiling.providers.{codex,claude,cursor} | string, route, or target | unset | Legacy compatibility input normalized to a one-candidate ladder. New configuration should use tiered candidate cells. The flat keys workflow.dispatchCeiling.codex and workflow.dispatchCeiling.claude were removed without migration. |
workflow.gates.skills | object | unset | Per-skill final gate config keyed by skill name. Managed with oat gate set/unset; gate-aware skills declare oat_gateable: true. |
workflow.gates.execTargets | object | built-ins | Cross-runtime exec target registry keyed by opaque target id. Managed with oat gate target set/unset; built-ins cover Codex, Claude, and Cursor defaults. |
archive.s3Uri | string | - | Base S3 URI for repo-scoped archived project sync, for example s3://bucket/oat-archive |
archive.s3SyncOnComplete | boolean | false | When true, oat-project-complete uploads the archived project to the configured S3 archive after local archive succeeds |
archive.summaryExportPath | string | - | Repo-relative directory where completion exports summary.md as a dated snapshot like 20260401-<project-name>.md for durable tracked reference |
archive.wrapUpExportPath | string | - | Repo-relative directory where oat-wrap-up writes dated reports like 20260413-wrap-up-past-week.md; when unset, the skill falls back to .oat/repo/reference/wrap-ups/ |
archive.awsProfile | string | - | Optional AWS named profile forwarded as AWS_PROFILE to every aws invocation in archive flows (oat-project-complete S3 sync, oat repo archive sync). Overrides ambient shell AWS_PROFILE / AWS_DEFAULT_PROFILE when set. |
archive.awsRegion | string | - | Optional AWS region forwarded as AWS_REGION to every aws invocation in archive flows. Overrides ambient shell AWS_REGION / AWS_DEFAULT_REGION when set. |
All documentation.* keys are managed via oat config get/set and are set automatically by oat docs init.
The git.defaultBranch key is auto-detected during oat init and can be overridden via oat config set git.defaultBranch <branch>.
Archive settings are managed via oat config get/set, and oat config describe archive.s3Uri (or the other archive keys) shows the lifecycle and ownership details from the CLI.
Workflow gate objects are structured config and are managed with oat gate, not the scalar oat config set surface. See Workflow Gates.
Example:
{
"version": 1,
"projects": {
"root": ".oat/projects/shared"
},
"worktrees": {
"root": ".worktrees"
},
"documentation": {
"root": "apps/docs/docs",
"tooling": "mkdocs",
"config": "mkdocs.yml",
"requireForProjectCompletion": false
}
}Worktree root precedence
When resolving the worktree root directory, oat-worktree-bootstrap uses this strict precedence (stops at the first match):
--path <root>flag — Explicit CLI override (highest priority)OAT_WORKTREES_ROOTenv var — Environment-level override.oat/config.jsonworktrees.root— Persisted project config- First existing directory (checked in order):
<repo>/.worktrees<repo>/worktrees../<repo-name>-worktrees
- Fallback default —
../<repo-name>-worktrees
For repo-relative values (levels 3-4), paths are resolved from the repository root. If the resolved root is project-local (.worktrees or worktrees), the skill verifies it is git-ignored before creating new worktrees.
Project artifact structure
Each OAT project lives under:
.oat/projects/shared/<project>/.oat/projects/local/<project>/.oat/projects/archived/<project>/
Archive sync behavior:
oat-project-completealways archives locally into.oat/projects/archived/<project>/.- If
archive.s3SyncOnComplete=trueandarchive.s3Uriis configured, completion also uploads a dated snapshot such as<archive.s3Uri>/<repo-slug>/projects/20260401-<project>/. oat repo archive syncsyncs all repo archived projects down from S3 into.oat/projects/archived/.oat repo archive sync <project-name>syncs the latest dated remote snapshot for a single project into.oat/projects/archived/<project-name>/.- Default archive sync is non-destructive toward unrelated local-only archive data, but it does replace a local project archive when a newer dated remote snapshot is selected for that same project.
Typical contents:
<project>/
state.md
discovery.md
spec.md
design.md
plan.md
implementation.md
summary.md
reviews/
pr/
references/Core artifact roles
| File | Purpose |
|---|---|
state.md | Lifecycle routing state (oat_phase, status, current task pointers) |
discovery.md | Problem framing and requirements discovery notes |
spec.md | Formalized requirements |
design.md | Technical architecture/design decisions |
plan.md | Executable task/phase plan and review table |
implementation.md | Execution log, progress table, outcomes, verification history |
summary.md | Institutional memory artifact — generated from project artifacts by oat-project-summary. Contains overview, key decisions, design deltas, challenges, follow-up items. Used as PR description source and archive cover page. |
reviews/*.md | Active tracked review artifacts awaiting receive/closeout |
reviews/archived/*.md | Local-only historical review artifacts after receive/closeout |
pr/*.md | PR description artifacts |
references/* | Imported or supporting source material |
Not all workflow modes require every artifact:
spec-driven: discovery + spec + design + plan + implementationquick: discovery + plan + implementation (spec/design optional)import: imported plan + implementation (spec/design optional)
.oat/repo/ structure
| Path | Purpose |
|---|---|
.oat/repo/knowledge/ | Generated codebase knowledge indexes |
.oat/repo/pjm/ | Active operational PJM layer (current-state.md, roadmap.md, and backlog/) |
.oat/repo/reference/ | Durable append-mostly references, including file-per-record decisions under decisions/ |
.oat/repo/reviews/ | Repo-scoped review artifacts (ad-hoc/non-project) |
.oat/repo/archive/ | Archived repo-level artifacts |
Canonical project-management repo-reference surface splits the active
operational layer (pjm/) from durable references (reference/):
.oat/repo/
AGENTS.md
pjm/
AGENTS.md
current-state.md
roadmap.md
backlog/
reference/
AGENTS.md
decisions/Decisions are file-per-record under reference/decisions/ (managed with the
oat decision command group), replacing the legacy single
reference/decision-record.md. Repos still on the old single-reference/
layout migrate with oat pjm migrate.
User scope (~/.oat/)
Common user-scope entries:
~/.oat/
config.json
ideas/
sync/
manifest.jsonUser scope is primarily for:
- User-level ideas
- User-level provider sync state where applicable
Practical guidance
- Treat
.oat/templates/as scaffolding source. - Treat
.oat/config.json+.oat/config.local.jsonas OAT runtime config/state (oat config get/set/list/describeis the preferred interface). - Treat
.oat/sync/manifest.jsonand.oat/sync/config.jsonas sync runtime state/config. - Treat project artifacts under
.oat/projects/**as lifecycle source-of-truth for workflow execution. - Keep
state.md,plan.md, andimplementation.mdconsistent after each workflow step.