Open Agent Toolkit

Provider Interop Commands

Shared conventions

These command definitions inherit the cross-cutting CLI conventions in:

Adjacent command docs (outside provider interop scope)

Quick Look

  • What it does: defines the day-to-day provider-sync command surface for inspecting state, reconciling provider views, and changing provider enablement.
  • When to use it: after you have canonical assets in place and need to check sync state, write provider views, or change provider config.
  • Primary commands: oat status, oat sync, oat providers list, oat providers inspect, oat providers set, oat providers codex materialize

oat status

Purpose:

  • Report in_sync, drifted, missing, and stray states

Key behavior:

  • Scope support (project, user, all)
  • Optional interactive stray adoption
  • Cursor-local and Copilot-local skills are handled individually: Adopt moves the skill into the matching canonical .agents/skills directory, while Keep provider-only preserves it and records its exact path in the applicable sync config
  • Aborting a native-read skill migration preserves completed choices and leaves the current and remaining skills unresolved
  • Keep provider-only is blocked when a canonical skill has the same name; rename one skill before retrying
  • Non-interactive and JSON modes report unresolved native-read skill actions without choosing or mutating a disposition
  • JSON output for automation

oat sync

Purpose:

  • Reconcile provider views from canonical sources

Key behavior:

  • Mutates by default; use --dry-run to preview
  • Strategy-aware operations (symlink, copy, auto)
  • Configured auto may adopt an existing exact collection-directory alias. When the destination is absent, the current runtime falls back per entry; OAT does not create or unlink a collection alias without identity-bound guarded primitives. Configuring an explicit per-entry strategy does not release an owned collection: the current runtime fails closed for deferred collection-directory copies and symlinks because it cannot keep every destination ancestor identity-bound. To leave the provider directory externally owned, run oat providers set --scope <scope> --disabled <provider> and then oat sync --scope <scope> to detach OAT ownership. Then verify and remove the preserved alias before managing that directory manually. Automatic transition requires an identity-bound, non-following publication primitive. Deferred file operations and ordinary non-transition per-entry symlinks retain their existing behavior. Explicit symlink and copy remain per-entry modes; oat sync does not add a --strategy option.
  • Provider enable/disable honored via sync config
  • Invalid canonical rules stop the run before anything is applied. Sync checks every rule first and fails once with a message that names each invalid rule file exactly once, even though several provider transforms read the same rule, so one run surfaces every file to fix. See Canonical rule frontmatter for the accepted alwaysApply: true alias.
  • Cursor skills are native-read from canonical .agents/skills; sync does not create .cursor/skills mirrors
  • Copilot skills are native-read from canonical .agents/skills; sync does not create .github/skills or ~/.copilot/skills mirrors. Copilot agents and project rules still sync to .github/agents, ~/.copilot/agents, and .github/instructions.
  • Upgrade cleanup removes only verified clean legacy Cursor or Copilot skill views. Changed or unverified views are preserved and detached from obsolete manifest ownership.
  • Before the dry-run/apply branch, each scope's sync manifest oatVersion is compared with the invoking CLI version. Any difference (older or newer) logs an advisory warning naming the scope and both versions; the run continues and the apply path restamps the manifest with the invoking version. JSON output suppresses the warning and reports the same data under a top-level versionSkew array ({ scope, producingVersion, invokingVersion }) in both --dry-run and apply envelopes; a scope without skew is omitted from the array.
  • When a run's only effect is that restamp — no planned operations and no failures, but skew present — apply reports Manifest version refreshed; no content changes required. instead of No changes required., so a manifest write is never described as a no-op.
  • A faithful copy-strategy entry whose manifest row records a stale contentHash (a pre-framing legacy digest or a tampered value) is planned as skip with the reason already in sync; restamp stale manifest content hash, and --json plan entries carry the verified digest as restampContentHash. Apply writes that digest, so the next run is a no-op. Only a row that tracks the same provider path that sync checked is restamped. Dry-run then reports Run without --dry-run to restamp N stale manifest content hashes. instead of No changes to apply.. Apply reports Manifest content hash restamped for N entries; no content changes required. (combined with the version-refresh sentence when both happen), or Manifest content hash restamped for N entries. beside a partial failure.
  • A copy-strategy canonical skill directory without SKILL.md, or agent directory without AGENT.md, is planned as an error operation whose reason names the missing file, instead of a copy that never verifies and is retried on every run. It changes nothing and is not a planned operation; other entries still sync. Apply reports it as a failed result (status: failed with a failure in --json operationResults) and exits 1. Dry-run lists it, warns N entry cannot sync until its configuration error is fixed., counts it in summary.failed, and still exits 0. Symlink strategy is unaffected.

oat sync is not the only command that replaces a manifest's producer version. oat init, oat remove skill, and oat status each capture the manifest's pre-mutation oatVersion while loading and planning, compare it with the invoking CLI version, and log the same advisory immediately before a qualifying save when the two differ:

Manifest version restamp [init user]: manifest produced by oat "0.2.58" will be restamped to oat "0.2.59".

The advisory sits immediately before the save, so a run that aborts earlier never announces a restamp it did not perform; a save that fails after the advisory still leaves the manifest unrestamped. An equal or absent version stays quiet. JSON mode suppresses the human warning; oat init and oat remove skill report the applied restamps under a top-level manifestVersionRestamps array of { scope, producingVersion, invokingVersion } entries. The oat remove skill dry-run payload omits the field rather than naming a restamp no save will perform.

Preview project and user cleanup before applying it:

oat sync --scope all --dry-run

Review every planned remove and detach operation before running the same command without --dry-run.

Dry-run and apply output include a Collection aliases section with scope, provider, content kind, action, ownership, scope-relative canonical/provider directories, reason, and planned or applied result. JSON reports the same redacted fields under collectionOperations; collection proofs are reduced to status and a safe reason rather than filesystem identities or absolute scope roots. Real-directory fallback is reported as fallback-per-entry.

oat providers list

Purpose:

  • Summarize adapters, detection, and mapping-level health summary
  • Summarize managed collection aliases by oat-created and adopted-exact ownership in both human and JSON output

oat providers inspect <provider>

Purpose:

  • Show adapter mappings and per-scope mapping state details
  • Show each owned collection alias with scope-relative paths, ownership, and last-verification time

oat providers set

Purpose:

  • Enable or disable providers in the selected scope's sync config; project is the default scope

Key behavior:

  • Updates the selected scope's sync config to toggle provider enablement
  • Scope: --scope project|user (defaults to project)
  • Options: --enabled <providers>, --disabled <providers> (comma-separated)
  • Changes take effect on next oat sync

oat providers codex materialize

Purpose:

  • Materialize one canonical Markdown agent as a Codex TOML role and register it in Codex configuration

Required operands:

oat providers codex materialize <agent-name> \
  --model <model-id> \
  --effort <reasoning-effort>

Key behavior:

  • Project scope is the default and writes only .codex/config.toml plus the project role file; --scope user writes only under ~/.codex
  • --agent-path selects a specific canonical agent and --role-name overrides the generated role name
  • Managed role registration enables multi-agent support and merges an agents.max_depth floor of 2
  • Project writes preserve a higher existing project depth or inherited user depth without mutating user configuration; user writes do not inspect or mutate project configuration
  • Existing unrelated Codex configuration and custom roles are preserved

Notes

  • oat init --scope project is commonly used before provider-interop commands because it initializes .oat/sync/config.json.
  • User-scope known-stray choices are stored in ~/.oat/sync/config.json. Legacy ~/.oat/config.json#knownStrays entries migrate automatically before user-scope stray filtering.
  • oat doctor complements interop workflows by surfacing environment and bundled-skill version issues before or after sync operations.

Adjacent Instruction Integrity Commands

These commands are documented here because they are commonly used during interop-only repo maintenance, but they are not provider sync/drift commands.

oat instructions validate

Purpose:

  • Validate project-scoped AGENTS.md to CLAUDE.md integrity

Key behavior:

  • Read-only validation of nested project-scoped instruction directories
  • Validates the effective strategy: --strategy none|pointer|symlink|copy, else instructions.claude.shims, else none (the default, which expects no CLAUDE.md); reports it as strategy under --json
  • Reports ok, missing (shim strategies only), content_mismatch, stray, and, under none, managed_shim (drift sync removes) and unmanaged (kept, not drift)
  • Detects Claude-only adoptable directories and unreadable/broken instruction paths as drift
  • Under none, warns about every remaining CLAUDE.md, .claude/CLAUDE.md, and CLAUDE.local.md (stderr, or the warnings array under --json) without changing the exit code
  • Skips the derived documentation content root and any instructions.claude.excludes paths, using the same exclusions as oat instructions sync
  • Exit code 0 when all entries are valid, 1 when drift is detected
  • Detailed behavior: Instruction Sync

oat instructions sync

Purpose:

  • Repair project-scoped AGENTS.md to CLAUDE.md drift

Key behavior:

  • Mutates by default; use --dry-run to preview changes
  • Supports --strategy none|pointer|symlink|copy as a one-run override of instructions.claude.shims (default none)
  • Under none, removes the CLAUDE.md shims OAT created (exact @AGENTS.md pointer, symlink to the sibling AGENTS.md, or byte-identical copy), re-verifying each immediately before deletion; hand-written or modified CLAUDE.md files are reported, never deleted, and while any CLAUDE.md, .claude/CLAUDE.md, or CLAUDE.local.md has content of its own, nothing is removed (claude_md_blocks_shim_removal)
  • Under a shim strategy, creates missing CLAUDE.md files using that strategy
  • Adopts Claude-only stray files by writing canonical AGENTS.md content first, then regenerating CLAUDE.md (shim strategies) or removing it (none)
  • Under a shim strategy, skips mismatched files unless --force is provided
  • Skips unreadable canonical or Claude-only sources and reports manual-repair guidance instead of forcing recovery
  • Skips the documentation content tree (literal documentation.root for tooling markdown, including nested docs; otherwise <documentation.root>/docs when that is a directory, falling back to documentation.root) plus any instructions.claude.excludes paths, so authored pages never receive pointers; app-level instruction files such as apps/oat-docs/AGENTS.md are still synced
  • Never deletes an existing CLAUDE.md inside an excluded tree
  • Under none, warns about every CLAUDE.md that remains after sync, including inside excluded trees, because any one of them makes Claude Code ignore every AGENTS.md
  • Uses pointer content @AGENTS.md\n, file symlinks, or hard copies depending on the selected strategy
  • Detailed behavior and examples: Instruction Sync

Safe scope for routine refresh

oat sync copies or links your canonical assets (the skills, agents, and rules you edit under .agents/) into provider views, the per-tool files such as .claude/skills/<name> that each agent tool reads. The scope decides which trees it touches: project is this repository, user is your home directory, and all is both.

WARNING

A bare oat sync uses scope all, so it also writes under your home directory. Every sync also overwrites edits made directly in provider folders, replaces an untracked file sitting at a view path, and removes a view whose canonical source was deleted. Edit files under .agents/ rather than in provider folders, and pass --scope explicitly.

  • For a repository-only refresh, run oat sync --scope project --dry-run to preview, then run it again without --dry-run.
  • In CI or scripts, always pass --scope project so the run cannot touch anything in a home directory.
  • To refresh your personal skills across repositories, run oat sync --scope user.
  • If you do mean to refresh both, preview oat sync --scope all --dry-run first.

On this page