pub const OC_PARITY_TOML: &str = r#"# built-in preset: oc-parity — opencode's default surface, composed.
schema_version = 1
[core]
env_context = true
project_context = true # AGENTS.md + instructions[] concat (oc§6)
nested_instructions = true # S6/S12 home: nested AGENTS.md auto-attached only for touched-file dirs, oc default (catalog:84; opencode.md:34 "nested-AGENTS.md") — closes an oc-parity gap-ledger row
instruction_imports = true # S6/S12 home: `instructions[]` config imports, oc default (catalog:85; opencode.md:367) — closes an oc-parity gap-ledger row
max_tool_output_bytes = 51200 # tool_output.max_bytes default 51200 / 2000 lines (oc§1 Truncate service)
[core.session]
auto_title = true # S6/S12 home: hidden title+summary agents (deny-all utility agents) on small_model, oc default (catalog:150; opencode.md:169-170,235) — closes an oc-parity gap-ledger row; small_model is "" below so this falls back to the main model per D-9 until a cheap model is configured
[core.tools]
enabled = ["read_file", "bash", "edit_file", "write_file"] # oc registry core (oc§1; read subsumes ls)
schema_tier = "full"
[core.tools.read_file]
multimodal = true # images/PDFs as attachments (oc§1 read)
[core.tools.bash]
timeout_secs = 120 # flags.bashDefaultTimeoutMs default 120000 (oc§1 bash)
[core.skills]
enabled = true # skill tool + .opencode/skills + remote registries (oc§7)
[core.compaction]
enabled = true
summarize = true # compaction{auto,prune,…} (oc§6)
# ---- modules ON ----
[capabilities.tools_search]
enabled = true
# glob + grep via ripgrep (oc§1)
[capabilities.todos]
enabled = true
persist = true
# todowrite → SQLite todo table (oc§1)
[capabilities.tools_web]
enabled = true
fetch = true
search = false
# webfetch is default; websearch only under the Zen provider / exa flags (oc§1 "webSearchEnabled")
[capabilities.subagents]
enabled = true
max_depth = 2
background = false
# task tool → child session via parentID, resumable task_id (oc§1); background is env-gated experimental → off
[capabilities.tools_apply_patch]
enabled = true
per_model = true
# THE C1 precedent: swapped in (edit/write out) for gpt-* models (oc§1 apply_patch; catalog §5 conflict 1)
[capabilities.plan_mode]
enabled = false
# S18 fix (flipped from `true`): opencode's plan_enter/plan_exit TOOLS — exactly what this module is defined by (§2 module 8) — are DENY-BY-DEFAULT at the pin (opencode.md:251), and this preset's own translated rule set below denies them. What oc actually runs by default is the LEGACY generation: the plan agent is a permission-ruleset agent (edit denied) — already expressible as an agent-scoped `permissions.rules` restriction, not the tool-based `plan_mode` module. Enabling `plan_mode` here would contradict oc's own deny-default; off is the honest reading.
[capabilities.permissions]
enabled = true
approval = "on_request" # ask-flow with once|always|reject replies (oc§4 "Ask/approve flow")
sandbox = "danger_full_access" # opencode has NO OS sandbox (catalog D4: sandbox is CC+CX only)
[capabilities.permissions.rules]
enabled = true
# opencode's default policy, TRANSLATED per the C5 decision (last-match-wins → deny→ask→allow
# first-match). Source policy (oc§4 "Default policy"): {"*": allow} with carve-outs
# doom_loop: ask, external_directory: ask, question: deny, plan_enter/plan_exit: deny,
# read {*.env: ask, *.env.*: ask, *.env.example: allow}.
#
# S4 fix — this is NOT "the same fixed point" as oc's last-match algebra, and is recorded honestly
# as THREE NAMED DEVIATIONS rather than claimed as exact parity:
# 1. `.env.example` → ASK here, not ALLOW. Under first-match deny→ask→allow, a read of
# `.env.example` matches the ask-rule `read_file(*.env.*)` (glob matches) BEFORE the allow
# list is ever consulted, so it asks where stock opencode allows. The engine's rule grammar
# has no specificity/negation to express "ask unless a more-specific allow" — fixing this
# would require adding that to the grammar (not done here); the deviation is in the SAFE
# direction (stricter) and is named, not hidden.
# 2. `doom_loop` is NOT a rule-language pattern at all — it's a repetition TRIGGER (same tool
# call repeated), not a tool/path match. Routed instead to its actual mechanism: the P4
# doom-loop breaker (a call-repetition counter + PreToolHook default, §5.2 P4) — no rule
# entry for it below.
# 3. `external_directory` is an oc PERMISSION CATEGORY (any tool touching paths outside the
# worktree), not a tool name — routed instead to its actual permission category: `[core]
# additional_dirs` (Config.additional_dirs, config.rs:169) governs which extra roots are
# writable at all; paths outside cwd AND outside `additional_dirs` are simply not reachable,
# which is a stricter (not equivalent) reading of oc's ask-by-default.
deny = ["plan_enter", "plan_exit"] # matches module 8's off-by-default above (S18) and oc's own "plan_enter/plan_exit: deny"
ask = ["read_file(*.env)", "read_file(*.env.*)"] # includes .env.example per deviation 1 above (glob matches before any allow)
allow = ["*"]
[capabilities.permissions.protected_paths]
enabled = false
# oc does .env protection through rules (above), not a path module
[capabilities.trust]
enabled = true
default = "ask"
# DELIBERATE SAFETY DEVIATION: opencode LACKS a project trust gate (catalog §3 closing) yet loads
# .opencode/ plugins/tools/commands from the repo. Our resolver treats plugins→trust as a HARD dep
# (D-10: "config-borne code execution without a trust gate is an injection hole") — so oc-parity
# ships the gate ON. This only NARROWS behavior (§3.3 monotonic-tightening spirit); recorded, not hidden.
[capabilities.mcp]
enabled = true
# local/remote/OAuth servers (oc§7)
[capabilities.plugins]
enabled = true
# .opencode/plugin + npm specs (oc§7); dep on trust satisfied above
[capabilities.lsp]
enabled = true
# 38 auto-spawned servers; diagnostics into edit/write results (oc§7, oc§10)
[capabilities.formatters]
enabled = true
diff_back = true
# ~27 format-on-write formatters; diff_back honors C10 (oc§7; oc§10; catalog §5 conflict 10)
[capabilities.checkpoint]
enabled = true
# shadow-git snapshots + revert/unrevert (oc§4 "Snapshots"/"Revert")
[capabilities.session_share]
enabled = true
# share manual|auto|disabled, default manual (oc§5, oc§6)
[capabilities.server]
enabled = true
# the client/server split: every frontend is an HTTP client (oc§8)
[capabilities.model_catalog]
enabled = true
small_model = ""
# models.dev catalog + small_model config key (oc§6, oc§9)
[capabilities.tui]
enabled = true
# ---- notable OFFs ----
[capabilities.tools_question]
enabled = false
# question tool is DENY-by-default outside build/plan agents (oc§1, oc§4)
[capabilities.tools_background]
enabled = false
# background subagents are env-gated experimental at the pin (oc§1)
[capabilities.session_tree]
enabled = false
# oc sessions are parent/child linear, no in-place tree (D5; C7)
[capabilities.memory]
enabled = false
[capabilities.hooks]
enabled = false
# no config-registered hooks; the plugin API is the interception layer (oc§7)
[capabilities.deferred_tools]
enabled = false
# opencode advertises eagerly (D1: deferred is CC+CX)
[capabilities.cache]
enabled = false
[capabilities.reduction]
enabled = false
# oc "prune" is the LOSSY analog (catalog §1 UNIQUE OC note); ours stays off to match, mechanism on per §1.13
[capabilities.structured_output]
enabled = false
[capabilities.model_oauth]
enabled = false
# provider /login flows (oc§9) — module 27 deferred
"#;Expand description
oc-parity — design §4.4.