Skip to content

.opencode/node_modules/ causes startup hang — scanner doesn't skip node_modules despite .gitignore #30337

Closed as not planned

Description

@gpal2study

Issue: .opencode/node_modules/ causes startup hang — scanner doesn't skip node_modules despite .gitignore

Description

When opencode discovers a .opencode/ directory in a project, startup hangs/freezes for
a long time. The root cause involves two conflicting behaviors:

  1. opencode installs @opencode-ai/plugin + its dependencies into .opencode/node_modules/
  2. opencode's own file scanner traverses .opencode/ — including node_modules/ with
    thousands of files — causing a severe startup delay

opencode already creates .opencode/.gitignore containing node_modules, package.json,
etc., but its own scanner does not read or respect .gitignore entries.

Reproduction

  1. Create .opencode/agents/my-agent.md (any agent file) in any project
  2. Start opencode in that directory
  3. Observed: startup hang while node_modules/ is installed AND scanned

Root Cause (source code references)

A) Dependency install creates node_modules/ inside .opencode/

File: packages/opencode/src/config/config.ts (around line 330-360)

for (const dir of directories) {
    if (dir.endsWith(".opencode") || dir === Flag.OPENCODE_CONFIG_DIR) { ... }
    yield* ensureGitignore(dir)
    npmSvc.install(dir, { add: [{ name: "@opencode-ai/plugin", version: ... }] })
}

The install() function (in packages/core/src/npm.ts) uses @npmcli/arborist to
reify packages directly into .opencode/node_modules/. This creates the large
directory tree that later causes the hang.

B) Scanner doesn't skip node_modules/ or respect .gitignore

opencode creates .opencode/.gitignore with node_modules excluded — but the
file discovery code (scanning for agents, skills, plugins) does not parse or
honor .gitignore patterns. It traverses everything including node_modules/.

C) Global cache already exists

Npm.add() in packages/core/src/npm.ts already uses a global cache:

const directory = (pkg: string) => path.join(global.cache, "packages", sanitize(pkg))
// resolves to ~/.cache/opencode/packages/<name>/

This global cache is used for npm-sourced plugins but NOT for the per-project
@opencode-ai/plugin SDK dependency install.

Suggested Fixes

Option 1 (minimal, scanner fix):
In the .opencode/ directory traversal code, add a guard:

if (entry.name === "node_modules") continue;

Or parse .opencode/.gitignore and honor its entries during scanning.

Option 2 (architectural, better):
Change the Npm.install(dir) call in config.ts to use a global location:

  • Reuse the existing ~/.cache/opencode/packages/ cache
  • Or install to system global npm (npm root -g)
  • This eliminates .opencode/node_modules/ entirely

Related Issues

Workaround

Delete .opencode/node_modules/ and make .opencode/ read-only:

attrib +r .opencode    # Windows
chmod -w .opencode     # Linux/macOS

This causes the canWrite check in Npm.install to skip installation.
Agent/config files in .opencode/ remain readable and functional.

Activity

  1. ulises-jeremias commented on Jun 5, 2026

    @ulises-jeremias
    Contributor

    I investigated and prepared a focused fix for this.

    Root cause confirmed

    • Config/skill discovery uses glob scans rooted at .opencode/ with recursive patterns (**/*.md, **/SKILL.md) and follows symlinks.
    • Those scans did not exclude node_modules, so once dependencies are installed in .opencode/node_modules, discovery walks huge trees and startup can stall.

    Fix implemented

    • Added ignore support to core glob wrapper (packages/core/src/util/glob.ts) so callers can pass exclusion patterns.
    • Applied ignore: ["**/node_modules/**"] to discovery scans used by:
      • agents (packages/opencode/src/config/agent.ts)
      • commands (packages/opencode/src/config/command.ts)
      • plugins (packages/opencode/src/config/plugin.ts)
      • skills (packages/opencode/src/skill/index.ts)

    Regression coverage added

    • packages/opencode/test/util/glob.test.ts
      • new test: supports ignore patterns
    • packages/opencode/test/config/config.test.ts
      • new test: ignores markdown files under .opencode/node_modules during config discovery
    • packages/opencode/test/skill/skill.test.ts
      • new test: ignores skills under .opencode/node_modules

    Opening PR now.

  2. slashinchi commented on Jul 16, 2026

    @slashinchi

    Can reproduce this on OpenCode Desktop 1.18.2 (upgraded from 1.17.18).

    Symptoms: @mention agent selector shows 27 entries from .opencode/node_modules/ — READMEs and CHANGELOGs from zod, effect, yaml, cross-spawn, etc. Normal agents (build/plan/explore) are not visible.

    Local verification:

    • .opencode/agents/ does not exist; in this case, discovery is not limited to .opencode/agents/
    • find .opencode/node_modules -name "*.md" returns exactly 27 files, matching the UI count
    • opencode.json has no custom agent discovery config; watcher.ignore includes node_modules but only affects file watching, not agent discovery
    • The .opencode/node_modules/ directory was auto-created by OC (.opencode/package.json only contains @opencode-ai/plugin)

    Context on the existing fix: PR #30847 by @ulises-jeremias already addressed this by adding ignore: ["**/node_modules/**"] to agent/command/plugin/skill discovery scans, plus regression tests. That PR was auto-closed by github-actions on Jul 5 due to age/lack of reactions — not due to technical rejection.

    Requesting maintainers to re-evaluate and merge #30847 or an equivalent fix. This makes the v2 custom agent selector (feat #36832) effectively unusable when .opencode/node_modules/ exists.

  3. ulises-jeremias commented on Jul 16, 2026

    @ulises-jeremias
    Contributor

    I have recreated the PR with the fix for this issue.

    The original PR (#30847) was auto-closed. I have reapplied the same changes on top of the latest dev and opened a new one:

    #37219 — fix(opencode): ignore node_modules during config and skill discovery

    @nexxeln @slashinchi — this should resolve the startup hang caused by .opencode/node_modules/ being scanned during config and skill discovery. The fix adds ignore: ["**/node_modules/**"] to all glob scans under .opencode/ and threads the ignore option through Glob.Options.

  4. added a commit that references this issue on Jul 16, 2026
    13fc1fc
  5. github-actions commented on Sep 15, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

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

Metadata

Metadata

Assignees

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