feat: Add OPENCODE_DISABLE_PROJECT_CONFIG for external tooling integration #4578

Closed
opened 2026-02-16 17:44:39 -05:00 by yindo · 2 comments
Owner

Originally created by @kdcokenny on GitHub (Jan 9, 2026).

Originally assigned to: @thdxr on GitHub.

Problem

I'm building OCX, a CLI extension for OpenCode that adds profile management. Profiles let users run OpenCode with different configurations depending on context—work vs personal, client A vs client B—without modifying the project's files.

To make this work today, OCX creates symlink farms: temporary directories that mirror the entire project via symlinks, excluding OpenCode's config files, then injecting the profile's config instead. OpenCode runs from this temp directory, thinking it's the real project.

This approach works, but it's fragile:

  • Complex cleanup — Orphaned temp directories from crashes need detection and removal
  • Windows issues — Symlinks require special permissions on Windows
  • Overhead — Creating hundreds of symlinks just to hide a few config files

The root cause: OpenCode always discovers configuration from the working directory. There's no way to tell it "I'm injecting config externally—ignore project files."

Proposed Solution

Add OPENCODE_DISABLE_PROJECT_CONFIG environment variable. When set to "true", OpenCode skips discovery of project-level configuration:

Disabled (project-level) Unaffected
opencode.jsonc, opencode.json in project ~/.config/opencode/ (global user config)
AGENTS.md, CLAUDE.md, CONTEXT.md in project ~/.local/share/opencode/ (session state)
.opencode/ directory (agents, skills, plugins, commands) OPENCODE_CONFIG_CONTENT (env var injection)
OPENCODE_CONFIG_DIR (env var injection)
OPENCODE_CONFIG (env var injection)

Global configuration and session state remain fully functional. Only project-level discovery is skipped, allowing external tools to inject configuration via the existing environment variable mechanisms.

Example Usage

OPENCODE_DISABLE_PROJECT_CONFIG=true \
OPENCODE_CONFIG_CONTENT='{"model":{"default":"anthropic/claude-sonnet-4-20250514"}}' \
OPENCODE_CONFIG_DIR=~/.config/opencode/profiles/work \
opencode

This runs OpenCode using the "work" profile's config and agents, completely ignoring any opencode.jsonc, AGENTS.md, or .opencode/ in the current project.

Implementation

Following the OPENCODE_DISABLE_CLAUDE_CODE pattern from PR #7205:

1. Define the flag (packages/opencode/src/flag/flag.ts):

export const OPENCODE_DISABLE_PROJECT_CONFIG = flag({
  key: "OPENCODE_DISABLE_PROJECT_CONFIG",
  description: "Disable discovery of project-level config, rules, and components",
})

2. Skip project config discovery (packages/opencode/src/config/config.ts):

In the read() function, check the flag before walking up directories for project config.

3. Skip project rule discovery (packages/opencode/src/file/system.ts):

Check the flag before discovering AGENTS.md, CLAUDE.md, CONTEXT.md in the project.

4. Skip project component loading (packages/opencode/src/app/app.ts):

Check the flag before loading agents, skills, plugins from <project>/.opencode/.

Benefits

  • Enables external tooling — Tools like OCX can inject config cleanly without filesystem hacks
  • Follows existing patterns — Same approach as OPENCODE_DISABLE_CLAUDE_CODE
  • Backwards compatible — Opt-in only, no change to default behavior
  • Minimal surface area — Single flag, conditional checks around existing discovery logic

Related

  • #7068 — Separating config directory from working directory (SDK context)
  • #6358 — Managed settings / enterprise config
  • #7205OPENCODE_DISABLE_CLAUDE_CODE pattern this follows

Happy to submit a PR if this approach works for you. Also open to discussing whether this should be a single flag or split into granular flags (e.g., separate flags for config vs rules vs components) if that's preferred.

Originally created by @kdcokenny on GitHub (Jan 9, 2026). Originally assigned to: @thdxr on GitHub. ### Problem I'm building [OCX](https://github.com/kdcokenny/ocx), a CLI extension for OpenCode that adds profile management. Profiles let users run OpenCode with different configurations depending on context—work vs personal, client A vs client B—without modifying the project's files. To make this work today, OCX creates **symlink farms**: temporary directories that mirror the entire project via symlinks, excluding OpenCode's config files, then injecting the profile's config instead. OpenCode runs from this temp directory, thinking it's the real project. This approach works, but it's fragile: - **Complex cleanup** — Orphaned temp directories from crashes need detection and removal - **Windows issues** — Symlinks require special permissions on Windows - **Overhead** — Creating hundreds of symlinks just to hide a few config files The root cause: OpenCode always discovers configuration from the working directory. There's no way to tell it "I'm injecting config externally—ignore project files." ### Proposed Solution Add `OPENCODE_DISABLE_PROJECT_CONFIG` environment variable. When set to `"true"`, OpenCode skips discovery of project-level configuration: | Disabled (project-level) | Unaffected | | ------------------------------------------------------------- | ----------------------------------------------- | | `opencode.jsonc`, `opencode.json` in project | `~/.config/opencode/` (global user config) | | `AGENTS.md`, `CLAUDE.md`, `CONTEXT.md` in project | `~/.local/share/opencode/` (session state) | | `.opencode/` directory (agents, skills, plugins, commands) | `OPENCODE_CONFIG_CONTENT` (env var injection) | | | `OPENCODE_CONFIG_DIR` (env var injection) | | | `OPENCODE_CONFIG` (env var injection) | Global configuration and session state remain fully functional. Only project-level discovery is skipped, allowing external tools to inject configuration via the existing environment variable mechanisms. ### Example Usage ```bash OPENCODE_DISABLE_PROJECT_CONFIG=true \ OPENCODE_CONFIG_CONTENT='{"model":{"default":"anthropic/claude-sonnet-4-20250514"}}' \ OPENCODE_CONFIG_DIR=~/.config/opencode/profiles/work \ opencode ``` This runs OpenCode using the "work" profile's config and agents, completely ignoring any `opencode.jsonc`, `AGENTS.md`, or `.opencode/` in the current project. ### Implementation Following the `OPENCODE_DISABLE_CLAUDE_CODE` pattern from PR #7205: **1. Define the flag** (`packages/opencode/src/flag/flag.ts`): ```typescript export const OPENCODE_DISABLE_PROJECT_CONFIG = flag({ key: "OPENCODE_DISABLE_PROJECT_CONFIG", description: "Disable discovery of project-level config, rules, and components", }) ``` **2. Skip project config discovery** (`packages/opencode/src/config/config.ts`): In the `read()` function, check the flag before walking up directories for project config. **3. Skip project rule discovery** (`packages/opencode/src/file/system.ts`): Check the flag before discovering `AGENTS.md`, `CLAUDE.md`, `CONTEXT.md` in the project. **4. Skip project component loading** (`packages/opencode/src/app/app.ts`): Check the flag before loading agents, skills, plugins from `<project>/.opencode/`. ### Benefits - **Enables external tooling** — Tools like OCX can inject config cleanly without filesystem hacks - **Follows existing patterns** — Same approach as `OPENCODE_DISABLE_CLAUDE_CODE` - **Backwards compatible** — Opt-in only, no change to default behavior - **Minimal surface area** — Single flag, conditional checks around existing discovery logic ### Related - #7068 — Separating config directory from working directory (SDK context) - #6358 — Managed settings / enterprise config - #7205 — `OPENCODE_DISABLE_CLAUDE_CODE` pattern this follows Happy to submit a PR if this approach works for you. Also open to discussing whether this should be a single flag or split into granular flags (e.g., separate flags for config vs rules vs components) if that's preferred.
yindo closed this issue 2026-02-16 17:44:39 -05:00
Author
Owner

@github-actions[bot] commented on GitHub (Jan 9, 2026):

This issue might be a duplicate or related to existing issues. Please check:

  • #7068: Allow separate config directory and working directory in SDK - addresses similar need to separate config location from working directory
  • #6358: Managed settings with admin-controlled priority for enterprise - related to config precedence and separation of concerns
  • #7136: Config Flag to mark part of the global config as non-overridable per project - related to config hierarchy and preventing project-level overrides

Your proposed OPENCODE_DISABLE_PROJECT_CONFIG flag complements these discussions. If you haven't already, consider reviewing these issues to ensure your approach aligns with the broader config management architecture being discussed.

@github-actions[bot] commented on GitHub (Jan 9, 2026): This issue might be a duplicate or related to existing issues. Please check: - #7068: Allow separate config directory and working directory in SDK - addresses similar need to separate config location from working directory - #6358: Managed settings with admin-controlled priority for enterprise - related to config precedence and separation of concerns - #7136: Config Flag to mark part of the global config as non-overridable per project - related to config hierarchy and preventing project-level overrides Your proposed OPENCODE_DISABLE_PROJECT_CONFIG flag complements these discussions. If you haven't already, consider reviewing these issues to ensure your approach aligns with the broader config management architecture being discussed.
Author
Owner

@ucirello commented on GitHub (Jan 13, 2026):

Alternatively, I used XDG env vars to achieve the same. Some kind of application native behavior would be neat.

@ucirello commented on GitHub (Jan 13, 2026): Alternatively, I used XDG env vars to achieve the same. Some kind of application native behavior would be neat.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#4578