Skip to content

fix(opencode): mirror default ~/.config/opencode when OPENCODE_CONFIG_DIR is unset - #9192

Closed
inaemin wants to merge 1 commit into
stablyai:mainfrom
inaemin:fix/opencode-default-config-dir-overlay
Closed

inaemin wants to merge 1 commit into
stablyai:mainfrom
inaemin:fix/opencode-default-config-dir-overlay

Conversation

@inaemin

@inaemin inaemin commented Jul 17, 2026 •

Copy link
Copy Markdown

Summary

When a user launches OpenCode in Orca without explicitly setting OPENCODE_CONFIG_DIR, Orca handed OpenCode a bare shared/ directory that contained only Orca's status plugin. The user's default OpenCode config at ~/.config/opencode/ (opencode.json, oh-my-openagent.json, auth, plugins) was never mirrored, so it was invisible to the OpenCode process.

Concretely, oh-my-openagent agents such as sisyphus still appeared by name (their definitions load from the un-redirected package cache ~/.cache/opencode/packages/), but their per-agent model mapping — which lives in ~/.config/opencode/oh-my-openagent.json — was dropped, so they silently ran under claude-opus-4-7 instead of the configured opencode-go/* model.

This PR makes OpenCodeHookService.buildPtyEnv() detect the default OpenCode config directory via the same XDG fallback OpenCode/OMO use (XDG_CONFIG_HOME/opencode → ~/.config/opencode) and mirror it into the source-scoped overlay alongside Orca's status plugin, exactly as it already does when the user sets OPENCODE_CONFIG_DIR explicitly. When no default dir exists, behavior is unchanged (bare shared plugin dir).

Fixes #9186.

Screenshots

No visual change. This is a main-process env/overlay fix with no renderer surface.

Testing

  • pnpm lint (oxlint clean on changed files)
  • pnpm typecheck
  • pnpm test (src/main/opencode/hook-service.test.ts — 29/29 passing)
  • pnpm build
  • Added or updated high-quality tests that would catch regressions

Added a regression test asserting that, with no explicit OPENCODE_CONFIG_DIR, buildPtyEnv mirrors the default XDG config dir into an overlay that contains both the user's opencode.json and Orca's plugins/orca-opencode-status.js — not the bare shared/ dir. Existing tests were isolated by pointing XDG_CONFIG_HOME at an empty temp dir in beforeAll, so a real ~/.config/opencode on the dev machine can no longer leak in and flip them onto the overlay path.

Also verified end-to-end on a clean build: without the change the agent runs under claude-opus-4-7; with it, the agent runs under the configured opencode-go/* model.

AI Review Report

Reviewed with the AI coding agent for:

  • Cross-platform (macOS/Linux/Windows): The new getDefaultOpenCodeConfigDir() uses path.join + os.homedir() (no hardcoded separators) and reads XDG_CONFIG_HOME. It only detects and returns a source dir; the actual mirroring reuses the existing mirrorUserConfig / overlay-mirror path that already handles Windows junctions vs POSIX symlinks. No new shortcut, label, or shell behavior was introduced.
  • SSH/remote/local: The change is inside OpenCodeHookService, invoked only on the host-local PTY path (buildPtyHostEnv), which callers already skip for SSH connections. No assumption of local-only execution was added.
  • Agent/integration compatibility: Detection is gated on existsSync(configDir), so users without a default OpenCode config keep the previous bare-shared behavior. The explicit-OPENCODE_CONFIG_DIR path is untouched. A typo'd/non-existent source dir is still passed through verbatim (no mkdir -p of the user's path), preserving the collision-avoidance behavior in docs/opencode-config-dir-collision.md.
  • Performance: Adds one existsSync per PTY spawn on the fallback path; negligible and off the hot path.
  • Security: No new input handling, command execution, or secret handling. The detected path is only used as a mirror source; overlay creation stays best-effort inside try/catch and falls back to the user's dir on failure.

Security Audit

  • Path handling: Source dir is derived from trusted env (XDG_CONFIG_HOME) / homedir(), joined with path.join. It is never used to build a shell command; it feeds the existing symlink/junction mirror, which already refuses to operate outside the overlay root during teardown (overlay-mirror.ts, issue [Bug]: work with Pi #1083 hardening).
  • No writes to the user's config: The default dir is only read/mirrored; Orca's plugin is written into the overlay's plugins/ dir, and writePluginIntoOverlay unlinks before write so a mirrored symlink can never be followed back into the user's real files.
  • Secrets/auth: This fix makes the user's own auth/config visible to their own OpenCode process (the intended behavior); it does not transmit or log anything. No follow-up needed.

Notes

  • Only affects the case where OPENCODE_CONFIG_DIR is unset and a default ~/.config/opencode (or $XDG_CONFIG_HOME/opencode) exists. No behavior change when the var is set explicitly or when no default dir exists.
  • The linked issue's earlier draft blamed an outdated oh-my-opencode@3.15.2 in the package cache; that was verified to be a red herring (cache held the current 4.18.2). The real cause is the missing default-config detection fixed here.

X (Twitter): @inaemin

ELI5

OpenCode launched from Orca without OPENCODE_CONFIG_DIR only saw a tiny shared plugin folder, not your real ~/.config/opencode setup. Default config is mirrored so plugins and auth work as outside Orca.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: df95c171-32ea-446b-9f6a-0af32f7efaab

📥 Commits

Reviewing files that changed from the base of the PR and between d95cbb1912e80f0bd26785aa429dc2c82d3ae678 and 0cc003b90bb5d21ee400a86ed5d8145395f38b69.

📒 Files selected for processing (12)
  • src/main/ipc/pty-buffer-snapshot-dispatch.test.ts
  • src/main/ipc/pty-controller-ownership-routing.test.ts
  • src/main/ipc/pty-daemon-spawn-session-identity.test.ts
  • src/main/ipc/pty-dead-owner-respawn.test.ts
  • src/main/ipc/pty-ipc-mock-registry.ts
  • src/main/ipc/pty-ipc-suite-environment.ts
  • src/main/ipc/pty-pane-reservation-settlement.test.ts
  • src/main/ipc/pty-persisted-incarnation-repair.test.ts
  • src/main/ipc/pty-restore-record-seeding.test.ts
  • src/main/ipc/pty-runtime-ssh-binding-persistence.test.ts
  • src/main/ipc/pty-serializer-settlement-mapping.test.ts
  • src/main/ipc/pty-session-liveness-and-ownership.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/ipc/pty-buffer-snapshot-dispatch.test.ts
  • src/main/ipc/pty-pane-reservation-settlement.test.ts
  • src/main/ipc/pty-session-liveness-and-ownership.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Added resolveDefaultOpenCodeConfigDir to resolve an existing OpenCode configuration directory from PTY or process environment values, shell startup configuration, or ~/.config. PTY environment construction now uses this resolver as a fallback. Added resolver tests, PTY environment propagation coverage, and shared mocks for the new configuration-source module.

Severity of issue fixed: Medium

Merge Risk: 🔵 Low · up to 0cc00

The fallback may treat an existing regular file as an OpenCode configuration directory, which could make configuration loading fail or behave incorrectly for affected users. The change is otherwise validated and appears mergeable with owner awareness of this edge case.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 51 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: mirroring the default ~/.config/opencode directory when OPENCODE_CONFIG_DIR is unset.
Description check ✅ Passed The description explains the problem, solution, scope, linked issue, testing, security, compatibility, and the absence of UI changes. It does not use every template heading or checklist item, but it p…
Linked Issues check ✅ Passed The implementation satisfies issue #9186 by resolving XDG_CONFIG_HOME/opencode or ~/.config/opencode from the PTY environment and mirroring it into the overlay with Orca's status plugin. It preserves …
Out of Scope Changes check ✅ Passed The changes remain focused on default OpenCode configuration resolution and test isolation. The added PTY test mocks support the new module dependency and do not introduce unrelated product behavior.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brennanb2025

Copy link
Copy Markdown
Contributor

Taking a look!

@inaemin
inaemin force-pushed the fix/opencode-default-config-dir-overlay branch from 01dd83a to 285bbda Compare July 20, 2026 11:17
@inaemin

inaemin commented Jul 20, 2026

Copy link
Copy Markdown
Author

Rebased onto latest main to resolve the conflict — sorry for the churn while you're looking.

The conflict came from #9543 (refactor(comments): slim verbose comments in main integrations), which condensed the comments in hook-service.ts at exactly the three spots this PR touches (buildPtyEnv's fallback branch, the existsSync guard, and the catch). I kept main's shortened comment style and re-applied only the sourceConfigDir logic on top, and shortened the new helper's comment to match.

No logic changes from the version you started reviewing. Re-verified after the rebase: pnpm test (hook-service 29/29), oxlint, and pnpm typecheck all pass.

@brennanb2025
brennanb2025 force-pushed the fix/opencode-default-config-dir-overlay branch from 285bbda to 24c9e75 Compare July 21, 2026 01:34
@brennanb2025

Copy link
Copy Markdown
Contributor

Thanks for the fix — I took this over and pushed a refined version. The default config source is now resolved from the actual PTY environment (including XDG/HOME and static shell exports) before reusing Orca's existing source-scoped overlay, so app/shell environment differences and nested Orca sessions keep the user's config while the status plugin remains installed. I also rebased onto current main and added focused coverage; 344 relevant tests, node typecheck, touched-file lint, and the max-lines gate all pass.

@inaemin

inaemin commented Jul 25, 2026

Copy link
Copy Markdown
Author

@brennanb2025 Thanks again for taking the time to refine this and pushing the updates!

I tested the latest version locally, and it seems to be working as expected. Is there anything else needed from my side before this can be merged?

@nwparker nwparker added the bug Something isn't working label Jul 27, 2026
@inaemin
inaemin force-pushed the fix/opencode-default-config-dir-overlay branch from 24c9e75 to c848bc9 Compare August 1, 2026 12:27
@greptile-apps

greptile-apps Bot commented Aug 1, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR fixes a bug where OpenCode launched from Orca without OPENCODE_CONFIG_DIR only received a bare shared/ plugin directory, causing user config (model mappings, auth, plugins) in ~/.config/opencode to be invisible to the OpenCode process.

  • Adds a new config-source.ts module with resolveDefaultOpenCodeConfigDir() that replicates OpenCode/XDG's own fallback chain (XDG_CONFIG_HOME/opencode → ~/.config/opencode), including a best-effort probe of shell startup files for GUI-launched Orca where XDG_CONFIG_HOME may not be in the process environment.
  • Updates resolveOpenCodeSourceConfigDir in pi-agent.ts to call this new function when neither an explicit OPENCODE_CONFIG_DIR nor a shell-startup value is found, mirroring the detected directory into the overlay exactly as already done for the explicit-env case.
  • Adds 29 new unit tests and retrofits mocks across all 47 existing IPC test files to prevent the real ~/.config/opencode from leaking into tests on developer machines.

Confidence Score: 5/5

  • Safe to merge — the change is narrowly scoped to the fallback path when OPENCODE_CONFIG_DIR is unset, the new directory detection is gated on existsSync, and the actual mirroring reuses the hardened existing overlay-mirror path.
  • The new module adds one existsSync check and delegates to already-tested infrastructure. The explicit-OPENCODE_CONFIG_DIR and Orca-overlay paths are completely untouched. Mocks are correctly wired across all 47 IPC test files, and the new unit tests cover the four meaningful cases (XDG precedence, HOME fallback, shell-startup probe, missing dir).
  • No files require special attention.

Important Files Changed

Filename Overview
src/main/opencode/config-source.ts New module that resolves the default OpenCode config directory via XDG fallbacks; logic is correct and the bootstrap problem (can't pass XDG_CONFIG_HOME to discover itself for fish config) is handled acceptably.
src/main/ipc/pty/host-env/pi-agent.ts Extends resolveOpenCodeSourceConfigDir to fall back to resolveDefaultOpenCodeConfigDir when no explicit config dir is found; the early-return guard structure is clean and preserves all existing paths.
src/main/opencode/config-source.test.ts New test file with four well-scoped cases covering XDG precedence, HOME fallback, shell-startup probe (zsh), and the missing-dir guard; uses unique mkdtempSync roots to avoid cache collisions.
src/main/ipc/pty-ipc-mock-registry.ts Adds openCodeConfigSourceModuleMock and resolveDefaultOpenCodeConfigDirMock; clean extension of the existing mock registry pattern.
src/main/ipc/pty-ipc-suite-environment.ts Correctly resets resolveDefaultOpenCodeConfigDirMock and seeds it with undefined in the default env setup, preventing real ~/.config/opencode from influencing unrelated IPC tests.
src/main/ipc/pty-spawn-env-agent-overlays.test.ts Adds the key integration regression test asserting that a resolved default config dir is forwarded to buildPtyEnv and reflected in ORCA_OPENCODE_SOURCE_CONFIG_DIR and OPENCODE_CONFIG_DIR.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[PTY spawn — OpenCode agent] --> B{OPENCODE_CONFIG_DIR set\nin PTY env or shell startup?}
    B -- yes, Orca-owned overlay --> C[Return undefined\nno source mirror]
    B -- yes, user-set --> D[Return explicit config dir\nas source for overlay]
    B -- no --> E[resolveDefaultOpenCodeConfigDir]

    E --> F{ptyEnv.XDG_CONFIG_HOME?}
    F -- yes --> G[configHome = ptyEnv.XDG_CONFIG_HOME]
    F -- no --> H{processEnv.XDG_CONFIG_HOME?}
    H -- yes --> I[configHome = processEnv.XDG_CONFIG_HOME]
    H -- no --> J[readShellStartupEnvVar XDG_CONFIG_HOME\nfrom shell startup files]
    J --> K{Found in shell?}
    K -- yes --> L[configHome = shell value]
    K -- no --> M[configHome = HOME/.config]

    G & I & L & M --> N[configDir = configHome/opencode]
    N --> O{existsSync configDir?}
    O -- yes --> P[Return configDir as source]
    O -- no --> Q[Return undefined\nno mirror, bare shared/ dir]

    P --> R[buildPtyEnv with sourceConfigDir\nmirrors user config into overlay]
    D --> R
    Q --> S[buildPtyEnv with no sourceConfigDir\nbare plugin dir only]
Loading

Reviews (3): Last reviewed commit: "fix(opencode): mirror default config whe..." | Re-trigger Greptile

@inaemin
inaemin force-pushed the fix/opencode-default-config-dir-overlay branch from c848bc9 to c2190f8 Compare August 1, 2026 12:47
@inaemin
inaemin force-pushed the fix/opencode-default-config-dir-overlay branch from c2190f8 to cb32e11 Compare August 13, 2026 09:51
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7bc46d55-4826-4819-9e50-352f370db084

📥 Commits

Reviewing files that changed from the base of the PR and between dd63d35 and cb32e1184c6bf65b4c3cd957db76b7baf0e0dda3.

📒 Files selected for processing (4)
  • src/main/ipc/pty.test.ts
  • src/main/ipc/pty.ts
  • src/main/opencode/config-source.test.ts
  • src/main/opencode/config-source.ts

readShellStartupEnvVar('XDG_CONFIG_HOME', home, shell) ||
join(home, '.config')
const configDir = join(configHome, 'opencode')
return existsSync(configDir) ? configDir : undefined

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/sh
set -eu

rg -n -C 4 'resolveDefaultOpenCodeConfigDir|ORCA_OPENCODE_SOURCE_CONFIG_DIR|openCodeBuildPtyEnv' src/main

Repository: stablyai/orca

Length of output: 1941


🏁 Script executed:

#!/bin/sh
set -eu

printf '%s\n' '--- target file ---'
wc -l src/main/opencode/config-source.ts
cat -n src/main/opencode/config-source.ts

printf '%s\n' '--- related symbols and tests ---'
rg -n -C 5 'resolveDefaultOpenCodeConfigDir|ORCA_OPENCODE_SOURCE_CONFIG_DIR|openCodeBuildPtyEnv|config-source' src/main src/renderer test tests 2>/dev/null || true

Repository: stablyai/orca

Length of output: 1912


🌐 Web query:

stablyai/orca src/main/opencode/config-source.ts resolveDefaultOpenCodeConfigDir

💡 Result:

In the context of the stablyai/orca repository, resolveDefaultOpenCodeConfigDir is a utility function responsible for determining the default directory for OpenCode configuration files. While specific implementation details can evolve with the codebase, this function typically follows standard configuration path resolution patterns found in similar CLI and agent orchestration tools [1][2][3]. It generally prioritizes the following order to ensure flexible profile isolation and adherence to platform conventions: 1. Environment variable override: It checks for an OPENCODE_CONFIG_DIR environment variable, which allows users to explicitly define a custom configuration directory [4][1][3]. 2. Standard XDG or platform-specific defaults: If the override is not set, it falls back to the standard configuration directory based on the host operating system, such as XDG_CONFIG_HOME/opencode on Linux or corresponding user profile directories on macOS and Windows [1][2]. The function is integral to Orca's ability to manage OpenCode environments, ensuring that configuration, agent settings, and plugin data are correctly located and loaded for the various agents that Orca orchestrates [5][6][7]. Recent updates in the repository have emphasized centralizing and hardening these path resolution strategies to support cross-platform consistency and improve reliability in parallel agent execution [8][9].

Citations:


🌐 Web query:

site:github.com/stablyai/orca/blob "return existsSync(configDir) ? configDir : undefined"

💡 Result:

The expression return existsSync(configDir)? configDir: undefined is a conditional assignment or return pattern used in Node.js applications to safely resolve a path [1][2]. It performs the following logic: 1. It checks if the path represented by the variable configDir exists on the filesystem using the Node.js built-in fs.existsSync function [1][3]. 2. If the path exists, it returns the value of configDir [1][2]. 3. If the path does not exist, it returns undefined [2]. This pattern is commonly used for validating configuration or directory paths before attempting to use them in downstream operations, such as reading files or initializing application state [1][4][2]. Using undefined as the fallback is a standard way to explicitly represent the absence of a valid path in JavaScript/TypeScript [4][3].

Citations:


🏁 Script executed:

#!/bin/sh
set -eu

base='https://raw.githubusercontent.com/stablyai/orca/main'
for path in \
  src/main/opencode/config-source.ts \
  src/main/opencode/config-source.test.ts \
  src/main/opencode/config-source.spec.ts
do
  printf '\n--- %s ---\n' "$path"
  curl -fsSL "$base/$path" | sed -n '1,220p' || true
done

printf '\n--- GitHub code search metadata ---\n'
curl -fsSL 'https://api.github.com/repos/stablyai/orca/contents/src/main/opencode' |
  jq -r '.[].name' 2>/dev/null || true

Repository: stablyai/orca

Length of output: 1912


Require an existing directory.

existsSync also returns true for a regular file. Return undefined when <configHome>/opencode is not a directory, and add a regression test for an opencode file.

@inaemin
inaemin force-pushed the fix/opencode-default-config-dir-overlay branch from cb32e11 to 089f9e6 Compare August 15, 2026 22:32
@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@inaemin
inaemin force-pushed the fix/opencode-default-config-dir-overlay branch from 089f9e6 to d95cbb1 Compare September 1, 2026 06:40
@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: 67d9f9c5-d594-455e-acbd-df83f4716d98

📥 Commits

Reviewing files that changed from the base of the PR and between f088872 and d95cbb1912e80f0bd26785aa429dc2c82d3ae678.

📒 Files selected for processing (52)
  • src/main/ipc/pty-applied-size-reporting.test.ts
  • src/main/ipc/pty-buffer-snapshot-dispatch.test.ts
  • src/main/ipc/pty-codex-account-attribution.test.ts
  • src/main/ipc/pty-controller-owner-recovery.test.ts
  • src/main/ipc/pty-controller-ownership-routing.test.ts
  • src/main/ipc/pty-controller-spawn-admission.test.ts
  • src/main/ipc/pty-cumulative-ack-accounting.test.ts
  • src/main/ipc/pty-daemon-controller-teardown.test.ts
  • src/main/ipc/pty-daemon-spawn-agent-home-env.test.ts
  • src/main/ipc/pty-daemon-spawn-codex-auth.test.ts
  • src/main/ipc/pty-daemon-spawn-session-identity.test.ts
  • src/main/ipc/pty-daemon-spawn-wsl-runtime.test.ts
  • src/main/ipc/pty-daemon-ssh-lease-lifecycle.test.ts
  • src/main/ipc/pty-dead-owner-respawn.test.ts
  • src/main/ipc/pty-delivery-health-heal.test.ts
  • src/main/ipc/pty-dispatcher-handshake-osc-answers.test.ts
  • src/main/ipc/pty-global-renderer-credit.test.ts
  • src/main/ipc/pty-hidden-at-spawn-mark.test.ts
  • src/main/ipc/pty-ipc-hidden-delivery-gate.test.ts
  • src/main/ipc/pty-ipc-mock-registry.ts
  • src/main/ipc/pty-ipc-producer-flow-control.test.ts
  • src/main/ipc/pty-ipc-suite-environment.ts
  • src/main/ipc/pty-listener-teardown-and-orphans.test.ts
  • src/main/ipc/pty-login-shell-startup-commands.test.ts
  • src/main/ipc/pty-output-batching-drain.test.ts
  • src/main/ipc/pty-output-drain-rounds.test.ts
  • src/main/ipc/pty-pane-claim-arbitration.test.ts
  • src/main/ipc/pty-pane-materialization-race.test.ts
  • src/main/ipc/pty-pane-reservation-settlement.test.ts
  • src/main/ipc/pty-pending-output-cap.test.ts
  • src/main/ipc/pty-persisted-incarnation-repair.test.ts
  • src/main/ipc/pty-renderer-inflight-credit.test.ts
  • src/main/ipc/pty-renderer-lifecycle-delivery-reset.test.ts
  • src/main/ipc/pty-renderer-send-failure-recovery.test.ts
  • src/main/ipc/pty-restore-record-seeding.test.ts
  • src/main/ipc/pty-runtime-kill-and-exit.test.ts
  • src/main/ipc/pty-runtime-ssh-binding-persistence.test.ts
  • src/main/ipc/pty-serializer-settlement-mapping.test.ts
  • src/main/ipc/pty-session-liveness-and-ownership.test.ts
  • src/main/ipc/pty-spawn-cwd-fallback.test.ts
  • src/main/ipc/pty-spawn-env-agent-overlays.test.ts
  • src/main/ipc/pty-spawn-env-codex-home-routing.test.ts
  • src/main/ipc/pty-spawn-env-codex-resume-provenance.test.ts
  • src/main/ipc/pty-spawn-env-terminal-basics.test.ts
  • src/main/ipc/pty-spawn-runtime-handle-binding.test.ts
  • src/main/ipc/pty-startup-barrier-and-listing.test.ts
  • src/main/ipc/pty-windows-shell-selection.test.ts
  • src/main/ipc/pty-write-ipc-validation.test.ts
  • src/main/ipc/pty-wsl-cwd-validation.test.ts
  • src/main/ipc/pty/host-env/pi-agent.ts
  • src/main/opencode/config-source.test.ts
  • src/main/opencode/config-source.ts
🚧 Files skipped from review as they are similar to previous changes (51)
  • src/main/ipc/pty-renderer-inflight-credit.test.ts
  • src/main/ipc/pty-spawn-runtime-handle-binding.test.ts
  • src/main/ipc/pty-serializer-settlement-mapping.test.ts
  • src/main/ipc/pty-buffer-snapshot-dispatch.test.ts
  • src/main/ipc/pty-pane-reservation-settlement.test.ts
  • src/main/ipc/pty-cumulative-ack-accounting.test.ts
  • src/main/ipc/pty-restore-record-seeding.test.ts
  • src/main/ipc/pty-pending-output-cap.test.ts
  • src/main/ipc/pty-login-shell-startup-commands.test.ts
  • src/main/ipc/pty-session-liveness-and-ownership.test.ts
  • src/main/ipc/pty-spawn-env-terminal-basics.test.ts
  • src/main/ipc/pty-output-drain-rounds.test.ts
  • src/main/ipc/pty-daemon-spawn-wsl-runtime.test.ts
  • src/main/ipc/pty-dead-owner-respawn.test.ts
  • src/main/ipc/pty-daemon-controller-teardown.test.ts
  • src/main/ipc/pty-runtime-kill-and-exit.test.ts
  • src/main/ipc/pty-controller-ownership-routing.test.ts
  • src/main/ipc/pty-hidden-at-spawn-mark.test.ts
  • src/main/ipc/pty-wsl-cwd-validation.test.ts
  • src/main/ipc/pty-runtime-ssh-binding-persistence.test.ts
  • src/main/ipc/pty-pane-materialization-race.test.ts
  • src/main/ipc/pty-global-renderer-credit.test.ts
  • src/main/ipc/pty-applied-size-reporting.test.ts
  • src/main/ipc/pty-persisted-incarnation-repair.test.ts
  • src/main/ipc/pty-ipc-hidden-delivery-gate.test.ts
  • src/main/ipc/pty-write-ipc-validation.test.ts
  • src/main/ipc/pty-spawn-env-agent-overlays.test.ts
  • src/main/ipc/pty-ipc-suite-environment.ts
  • src/main/ipc/pty-ipc-producer-flow-control.test.ts
  • src/main/opencode/config-source.ts
  • src/main/ipc/pty-listener-teardown-and-orphans.test.ts
  • src/main/ipc/pty-dispatcher-handshake-osc-answers.test.ts
  • src/main/ipc/pty-renderer-send-failure-recovery.test.ts
  • src/main/ipc/pty-pane-claim-arbitration.test.ts
  • src/main/ipc/pty-daemon-ssh-lease-lifecycle.test.ts
  • src/main/ipc/pty-startup-barrier-and-listing.test.ts
  • src/main/ipc/pty-daemon-spawn-agent-home-env.test.ts
  • src/main/ipc/pty-spawn-env-codex-home-routing.test.ts
  • src/main/ipc/pty-output-batching-drain.test.ts
  • src/main/ipc/pty-ipc-mock-registry.ts
  • src/main/ipc/pty-controller-spawn-admission.test.ts
  • src/main/ipc/pty-delivery-health-heal.test.ts
  • src/main/ipc/pty-controller-owner-recovery.test.ts
  • src/main/opencode/config-source.test.ts
  • src/main/ipc/pty-spawn-env-codex-resume-provenance.test.ts
  • src/main/ipc/pty-daemon-spawn-codex-auth.test.ts
  • src/main/ipc/pty-spawn-cwd-fallback.test.ts
  • src/main/ipc/pty-daemon-spawn-session-identity.test.ts
  • src/main/ipc/pty-codex-account-attribution.test.ts
  • src/main/ipc/pty-renderer-lifecycle-delivery-reset.test.ts
  • src/main/ipc/pty-windows-shell-selection.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.

if (explicitConfigDir) {
return explicitConfigDir
}
return resolveDefaultOpenCodeConfigDir(baseEnv)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 4 'existsSync|statSync|isDirectory|resolveDefaultOpenCodeConfigDir' \
  src/main/opencode/config-source.ts

rg -n -C 8 'resolveOpenCodeSourceConfigDir|sourceConfigDir|copy|cp|overlay' \
  src/main/ipc/pty

Repository: stablyai/orca

Length of output: 19535


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- repository guidance ---'
find /tmp/coderabbit-repo-knowledge/stablyai/orca-89dc44e4 -maxdepth 2 -type f -name '*.md' -print

printf '%s\n' '--- config resolver ---'
cat -n src/main/opencode/config-source.ts

printf '%s\n' '--- changed resolver and its caller ---'
sed -n '1,18p;186,214p' src/main/ipc/pty/host-env/pi-agent.ts
sed -n '70,92p' src/main/ipc/pty/host-env/assembly.ts

printf '%s\n' '--- overlay consumer definitions ---'
rg -n -C 8 'buildPtyEnv|OPENCODE_CONFIG_DIR|copyFile|cp\(|mkdir|readdir|configDir' src/main/opencode src/main/ipc/pty --glob '*.ts'

Repository: stablyai/orca

Length of output: 268


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- repository guidance ---'
find /tmp/coderabbit-repo-knowledge/stablyai-orca-89dc44e4 -maxdepth 2 -type f -name '*.md' -print

printf '%s\n' '--- config resolver ---'
cat -n src/main/opencode/config-source.ts

printf '%s\n' '--- changed resolver and its caller ---'
sed -n '1,18p;186,214p' src/main/ipc/pty/host-env/pi-agent.ts
sed -n '70,92p' src/main/ipc/pty/host-env/assembly.ts

printf '%s\n' '--- overlay consumer definitions ---'
rg -n -C 8 'buildPtyEnv|OPENCODE_CONFIG_DIR|copyFile|cp\(|mkdir|readdir|configDir' src/main/opencode src/main/ipc/pty --glob '*.ts'

Repository: stablyai/orca

Length of output: 50369


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- applicable conventions and learnings ---'
cat /tmp/coderabbit-repo-knowledge/stablyai-orca-89dc44e4/conventions/repo-wide.md
printf '%s\n' '--- PTY learnings ---'
cat /tmp/coderabbit-repo-knowledge/stablyai-orca-89dc44e4/learnings/src-main-pty.md

printf '%s\n' '--- exact overlay flow ---'
sed -n '68,106p;108,120p;155,172p;205,221p' src/main/opencode/hook-service.ts

printf '%s\n' '--- resolver tests, including missing-path behavior ---'
sed -n '1,90p' src/main/opencode/config-source.test.ts

printf '%s\n' '--- documented OPENCODE_CONFIG_DIR contract ---'
cat docs/opencode-config-dir-collision.md

Repository: stablyai/orca

Length of output: 8267


🌐 Web query:

OpenCode OPENCODE_CONFIG_DIR environment variable directory configuration documentation

💡 Result:

In OpenCode, the OPENCODE_CONFIG_DIR environment variable is used to specify a custom directory for configuration [1][2][3]. When set, OpenCode searches this custom directory for agents, commands, modes, and plugins, using the same structure as the default.opencode directory [1][3]. Because this custom directory is loaded after the global configuration and the standard.opencode directory, any settings defined within it can override those from the default locations [1][2][3]. You can set this variable in your terminal before running OpenCode commands [1][3]: export OPENCODE_CONFIG_DIR=/path/to/my/config-directory opencode run "Hello world" OpenCode is an open-source AI coding agent developed by Anomaly that assists with software development tasks via terminal, desktop, or IDE interfaces [4][5]. The implementation of this configuration logic is managed within the OpenCode codebase, where the value is retrieved dynamically at runtime [6].

Citations:


Require the fallback path to be a directory.

existsSync(configDir) also accepts regular files. If ~/.config/opencode is a file, the overlay flow can return it as OPENCODE_CONFIG_DIR, although OpenCode expects a configuration directory. Use a directory check or add a regression test.

Source: Linters/SAST tools

Resolve the default config source from each PTY environment, including static shell exports, before creating the existing source-scoped overlay. This preserves user models, plugins, and auth while keeping the Orca status plugin installed.

Fixes stablyai#9186.

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
@inaemin
inaemin force-pushed the fix/opencode-default-config-dir-overlay branch from 7e1d7cb to e0b85d2 Compare September 19, 2026 12:10
@nwparker

nwparker commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

PR #25296 is merged and credits @inaemin for this proposal. It fixes Orca putting OpenCode hooks in the wrong config directory when a terminal uses a different HOME, XDG_CONFIG_HOME, or shell. Validation with installed OpenCode 2.0.16 found the hook active in all five tested launch cases.

This PR remains open for its broader default model and OhMyOpenCode support; those are still outstanding.

@nwparker

Copy link
Copy Markdown
Contributor

Thanks @inaemin for the detailed write-up and the fix! This is already fixed on main by #21854 (438744c). When OPENCODE_CONFIG_DIR isn't set, Orca no longer points OpenCode at a bare shared directory. It leaves OPENCODE_CONFIG_DIR unset and installs its status plugin into OpenCode's default config directory ($XDG_CONFIG_HOME/opencode, falling back to ~/.config/opencode), so opencode.json, oh-my-openagent.json, and your per-agent model mappings load normally. #25296 later made that path resolve from the terminal's own shell environment. If you still see agents falling back to the wrong model on the latest build, please comment here or reopen and we'll take another look.

@nwparker nwparker closed this Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: OpenCode in Orca ignores default ~/.config/opencode — agents run with the wrong model when OPENCODE_CONFIG_DIR is unset

3 participants