Open Agent Toolkit

.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

PathPurposeNotes
.oat/config.jsonShared repo runtime config for non-sync settingsIncludes worktrees.root, projects.root, git.defaultBranch, archive.*, and documentation.*
.oat/config.local.jsonLocal per-developer runtime stateGitignored; includes activeProject, lastPausedProject, activeIdea
.oat/state.mdGenerated repo state dashboardGitignored; rebuilt with oat state refresh from config, project artifacts, and knowledge metadata
.oat/projects/OAT project artifactsshared, local, archived scopes
.oat/ideas/Project-level ideas storeOften gitignored
.oat/sync/Interop sync state/configSee details below
.oat/templates/Artifact templates used by OAT skillsSource for scaffolding. Includes docs-app-fuma/ (Fumadocs) and docs-app-mkdocs/ (MkDocs) templates.
.oat/repo/Repo-level PJM/knowledge/reference/review artifactsActive PJM state under pjm/; durable references (including decisions) under reference/

.oat/sync/ details

PathPurpose
.oat/sync/manifest.jsonRecords sync-managed provider entries and drift contract state
.oat/sync/config.jsonSync behavior config (default strategy + provider-level settings)

config.json currently includes:

  • version
  • defaultStrategy
  • providers.<provider>.enabled
  • providers.<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.json owns shared non-sync repo settings (including worktrees.root, projects.root, and documentation.*).
  • .oat/config.local.json owns per-developer project lifecycle state (activeProject, lastPausedProject, activeIdea).
  • ~/.oat/config.json owns user-level state (activeIdea at global scope).
  • .oat/sync/config.json continues to own sync/provider behavior.

CLI discovery surfaces:

  • oat config describe lists 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 list prints 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:

KeyTypeDefaultDescription
versionnumber1Schema version
worktrees.rootstring".worktrees"Root directory for git worktrees (repo-relative or absolute)
projects.rootstring".oat/projects/shared"Default root directory for OAT projects
localPathsstring[]-Gitignored directories to sync between main repo and worktrees. Supports glob patterns. Managed via oat local add/remove.
documentation.rootstring-Root directory containing documentation source files (e.g., apps/docs/docs)
documentation.toolingstring-Documentation framework identifier (mkdocs or fumadocs)
documentation.configstring-Path to the documentation framework config file (e.g., mkdocs.yml, next.config.js)
documentation.indexstring-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.requireForProjectCompletionbooleanfalseWhen true, OAT project completion gates require documentation to be updated
git.defaultBranchstring"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.autoReviewAtHillCheckpointsbooleanunsetWhen 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.modestringunsetDispatch policy mode: managed lets OAT select model/effort controls; inherit leaves controls to the host/provider defaults.
workflow.dispatchPolicy.policystringunsetManaged 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.presetstringunsetLegacy 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 scalarunsetReusable 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: [...] }unsetOne 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 targetunsetLegacy 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.skillsobjectunsetPer-skill final gate config keyed by skill name. Managed with oat gate set/unset; gate-aware skills declare oat_gateable: true.
workflow.gates.execTargetsobjectbuilt-insCross-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.s3Uristring-Base S3 URI for repo-scoped archived project sync, for example s3://bucket/oat-archive
archive.s3SyncOnCompletebooleanfalseWhen true, oat-project-complete uploads the archived project to the configured S3 archive after local archive succeeds
archive.summaryExportPathstring-Repo-relative directory where completion exports summary.md as a dated snapshot like 20260401-<project-name>.md for durable tracked reference
archive.wrapUpExportPathstring-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.awsProfilestring-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.awsRegionstring-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):

  1. --path <root> flag — Explicit CLI override (highest priority)
  2. OAT_WORKTREES_ROOT env var — Environment-level override
  3. .oat/config.json worktrees.root — Persisted project config
  4. First existing directory (checked in order):
    • <repo>/.worktrees
    • <repo>/worktrees
    • ../<repo-name>-worktrees
  5. 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-complete always archives locally into .oat/projects/archived/<project>/.
  • If archive.s3SyncOnComplete=true and archive.s3Uri is configured, completion also uploads a dated snapshot such as <archive.s3Uri>/<repo-slug>/projects/20260401-<project>/.
  • oat repo archive sync syncs 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

FilePurpose
state.mdLifecycle routing state (oat_phase, status, current task pointers)
discovery.mdProblem framing and requirements discovery notes
spec.mdFormalized requirements
design.mdTechnical architecture/design decisions
plan.mdExecutable task/phase plan and review table
implementation.mdExecution log, progress table, outcomes, verification history
summary.mdInstitutional 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/*.mdActive tracked review artifacts awaiting receive/closeout
reviews/archived/*.mdLocal-only historical review artifacts after receive/closeout
pr/*.mdPR description artifacts
references/*Imported or supporting source material

Not all workflow modes require every artifact:

  • spec-driven: discovery + spec + design + plan + implementation
  • quick: discovery + plan + implementation (spec/design optional)
  • import: imported plan + implementation (spec/design optional)

.oat/repo/ structure

PathPurpose
.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.json

User 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.json as OAT runtime config/state (oat config get/set/list/describe is the preferred interface).
  • Treat .oat/sync/manifest.json and .oat/sync/config.json as sync runtime state/config.
  • Treat project artifacts under .oat/projects/** as lifecycle source-of-truth for workflow execution.
  • Keep state.md, plan.md, and implementation.md consistent after each workflow step.

On this page