Skip to content

reference configuration

Dylan McCavitt edited this page Jul 4, 2026 · 1 revision

Configuration

Garnish storage layout, environment variables, and the generated config files. All state lives under a Garnish-owned storage root so the learner's real harness config is never touched.

Storage root

The storage root defaults to ~/.garnish and is overridable via GARNISH_ROOT. runtimePaths in src/adapter/runtime.ts computes every path under it, and assertGarnishOwnedPaths verifies none escape the root.

<GARNISH_ROOT>/
  runtime/pi/omp-16.2.13/bin/omp     certified binary copy
  agent/                              PI_CODING_AGENT_DIR target
    config.yml                        generated gate config (merged with providers)
    mcp.json                          generated MCP gate config
    APPEND_SYSTEM.md                  static tutor framing
    extensions/garnish/index.js       bundled extension (bun build --target node)
    garnish/
      events.jsonl                    append-only event log (source of truth)
      state.json                      derived snapshot
      graph.json                      progression graph
      quests.json                     full quest definitions
      packs/                          copied quest packs (l0-tutorial-island, l1-first-quest, l2-lore)
  home/                               isolated HOME for launched sessions
  auth/omp-auth-broker-snapshot.enc   auth broker snapshot cache
  bin/garnish                         CLI shim for in-session use
  sandbox/                            default sandbox dir (quests operate here)

garnish init creates this tree. The certified binary lives at runtime/pi/omp-16.2.13/bin/omp, versioned by the certified release. The agent dir is the PI_CODING_AGENT_DIR target. The garnish/ subdir holds the event log, the derived state, the pre-serialized graph and quests the extension reads synchronously at session start, and the copied packs. See architecture for the isolation model and data models for the file schemas.

Environment variables

Variable Set by Purpose
GARNISH_ROOT User Points Garnish at a different storage root (default ~/.garnish).
GARNISH_OMP_SOURCE User Points ensureRuntime at a binary to copy into Garnish-owned storage when no certified binary is installed.
GARNISH_BIN User Override for the garnish shim location.
PI_CODING_AGENT_DIR createLaunchSpec Points the certified binary at the Garnish-owned agent dir for isolated config, extensions, and auth.
OMP_AUTH_BROKER_SNAPSHOT_CACHE createLaunchSpec Points the auth broker at the Garnish-owned snapshot path.
HOME createLaunchSpec Overridden to the Garnish-owned home/ dir for launched sessions.

The launch spec in src/adapter/runtime.ts sets PI_CODING_AGENT_DIR, OMP_AUTH_BROKER_SNAPSHOT_CACHE, and HOME on every launched session so the certified binary runs fully isolated. See Pi adapter and debugging.

Generated config.yml

renderGateConfig in src/adapter/gates.ts produces the config.yml that physically enables or disables Pi surfaces. The file starts with a generated header and a garnish marker:

# Generated by Garnish. Do not edit; Garnish owns these arrays and replaces them wholesale.
garnish:
  owner: garnish
  generated: true
  arraysReplaceWholesale:
    - disabledExtensions
    - disabledProviders
    - skills.includeSkills
    - mcp.disabledServers

The body contains:

  • Tool toggles — per-tool enabled flags (e.g. bash.enabled, edit.enabled, read.enabled) derived from the tool:bash, tool:file, tool:shell catalog entries.
  • Skillsskills.enabled and skills.includeSkills (an allowlist of globs) derived from the skills catalog entry.
  • disabledProviders — the providers still locked (derived from the context catalog entry). Unlocked providers are absent from this list.
  • disabledExtensions — the extensions still locked (derived from the extensions catalog entry).
  • mcp.enableProjectConfig — whether project-level MCP config is enabled (derived from the mcp catalog entry).
  • tools.approvalMode — the strongest unlocked approval mode (always-ask, write, or yolo).
  • providers — preserved from the existing file through the read-merge-write path in writeGateConfig. The learner's apiKeyRef lives here.

Garnish owns the arrays listed in arraysReplaceWholesale and replaces them wholesale on re-render. Non-owned keys (like providers) survive gate re-renders. Serialization is stable: keys are sorted alphabetically and the YAML is regenerated deterministically. See Pi adapter and capability gating.

Generated mcp.json

renderGateConfig also produces the mcp.json:

{
  "$schema": "https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/src/config/mcp-schema.json",
  "garnish": {
    "owner": "garnish",
    "generated": true,
    "arraysReplaceWholesale": ["disabledExtensions", "disabledProviders", "skills.includeSkills", "mcp.disabledServers"]
  },
  "mcpServers": {},
  "disabledServers": ["garnish-demo"]
}

Garnish owns mcpServers (empty in v1) and disabledServers (the MCP servers still locked). mcp.enableProjectConfig in config.yml gates whether project-level .omp/mcp.json is read.

The garnish shim

garnish init writes a garnish shim into the Garnish-owned bin/ dir. The shim lets the learner run garnish status, garnish quest, and the other CLI commands from within a launched session without needing the dev install on PATH. See CLI commands.

Wholesale array replacement

Because Pi config layers replace arrays wholesale, Garnish must own any array it manages. The garnish.generated.arraysReplaceWholesale marker in every generated file declares which arrays Garnish owns: disabledExtensions, disabledProviders, skills.includeSkills, and mcp.disabledServers. User hand-edits to these arrays get clobbered on regeneration; the generated header warns against manual edits. Non-owned keys are preserved. This is ADR-5. See design decisions and security.

Clone this wiki locally