Skip to content

feat(config): per-harness config overrides via harnesses key #271

Description

@Qiiks

Summary

AFT currently uses a single shared config (~/.config/cortexkit/aft.jsonc) for all harnesses (OpenCode, Pi/OMP). The config schema has no per-harness section — hoist_builtin_tools, disabled_tools, tool_surface, etc. are global. This means a user who wants AFT to hoist tools on OpenCode (replacing opencode's natives with AFT's enhanced versions) but keep OMP's natives un-hoisted (so both read and aft_read are available) cannot express that — changing one harness's behavior changes all of them.

The same applies to per-harness LSP config, search_backend, disabled_tools, bash settings, and future harness-specific knobs. Today the only workaround is to keep separate config files and swap them manually or use project-level overrides (<project>/.cortexkit/aft.jsonc), neither of which solves the common case of "two harnesses on the same machine with different needs."

Requested solution

Add a top-level harnesses key to aft.jsonc that allows per-harness overrides:

{
  // Shared defaults (current behavior, all fields still work here)
  "hoist_builtin_tools": false,
  "disabled_tools": [],

  // Per-harness overrides — deep-merged on top of shared config
  "harnesses": {
    "opencode": {
      "hoist_builtin_tools": true,
      "disabled_tools": ["aft_conflicts"]
    },
    "pi": {
      "hoist_builtin_tools": false,
      "disabled_tools": ["aft_read", "aft_write", "aft_edit", "aft_grep", "aft_bash"]
    }
  }
}

Why this matters

The current design forces an awkward choice:

  • Shared config: every harness gets identical tool sets and behavior. The user who wants AFT exclusives (aft_callgraph, aft_insight, aft_refactor) on Pi but wants opencode to keep its own native tools has no way to express that.
  • Manual swap: keeping two files and renaming them when switching harnesses is error-prone and breaks the "one config" migration story.
  • Project overrides: only help when projects are distinct; two harnesses on the same project share the project config.

A harnesses key preserves backward compatibility (the shared top-level still works for users who don't need per-harness control) while adding the missing granularity.

Workarounds today

  1. Use <project>/.cortexkit/aft.jsonc per-project (only helps if projects are distinct).
  2. Keep separate global configs and swap them manually when switching harnesses.
  3. File a feature request and wait for upstream. 🙂

Alternatives considered

  • Separate config files per harness (aft.pi.jsonc, aft.opencode.jsonc): breaks the "one config" design, migration story becomes unclear.
  • CLI flag (--hoist per invocation): doesn't persist, doesn't cover all settings.
  • Env var per harness: limited to boolean/string values, doesn't compose with JSONC.

The harnesses key is the minimal addition that preserves backward compatibility and covers the use case cleanly.

Additional context

Relevant source: packages/config-keys.ts (currently only OPENCODE_ONLY_KEYS and PI_ONLY_KEYS exist, both single-harness), packages/config.ts (schema validation), packages/aft-bridge/src/config-tiers.ts (user+project tiers, no harness tier), packages/pi-plugin/src/index.ts (config loading).

Related prior request: OMP feature request #9972 (provider-level routing override) touches the same theme — the config system needs more granular override paths.

/cc @Alfonso (responded to #267 with the hoist_builtin_tools fix — this is the next logical step).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions