Repository navigation
Description
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:
- opencode installs
@opencode-ai/plugin+ its dependencies into.opencode/node_modules/ - opencode's own file scanner traverses
.opencode/— includingnode_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
- Create
.opencode/agents/my-agent.md(any agent file) in any project - Start opencode in that directory
- 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
- TUI renders blank when project has node_modules without .gitignore exclusion #27072 — "TUI renders blank when project has node_modules without .gitignore exclusion"
- Skill discovery follows symlinks into large directories, causing 120s+ startup on slow filesystems #27027 — "Skill discovery follows symlinks into large directories, causing 120s+ startup"
- Disable force dependency update while starting #8729 — "Disable force dependency update while starting"
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
ulises-jeremias commentedon Jun 5, 2026
I investigated and prepared a focused fix for this.
Root cause confirmed
.opencode/with recursive patterns (**/*.md,**/SKILL.md) and follows symlinks.node_modules, so once dependencies are installed in.opencode/node_modules, discovery walks huge trees and startup can stall.Fix implemented
ignoresupport to core glob wrapper (packages/core/src/util/glob.ts) so callers can pass exclusion patterns.ignore: ["**/node_modules/**"]to discovery scans used by:packages/opencode/src/config/agent.ts)packages/opencode/src/config/command.ts)packages/opencode/src/config/plugin.ts)packages/opencode/src/skill/index.ts)Regression coverage added
packages/opencode/test/util/glob.test.tssupports ignore patternspackages/opencode/test/config/config.test.tsignores markdown files under .opencode/node_modules during config discoverypackages/opencode/test/skill/skill.test.tsignores skills under .opencode/node_modulesOpening PR now.
slashinchi commentedon Jul 16, 2026
Can reproduce this on OpenCode Desktop 1.18.2 (upgraded from 1.17.18).
Symptoms:
@mentionagent selector shows 27 entries from.opencode/node_modules/— READMEs and CHANGELOGs fromzod,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 countopencode.jsonhas no custom agent discovery config;watcher.ignoreincludesnode_modulesbut only affects file watching, not agent discovery.opencode/node_modules/directory was auto-created by OC (.opencode/package.jsononly 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 bygithub-actionson 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.ulises-jeremias commentedon Jul 16, 2026
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
devand 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 addsignore: ["**/node_modules/**"]to all glob scans under.opencode/and threads theignoreoption throughGlob.Options.fix(opencode): ignore node_modules during config and skill discovery
github-actions commentedon Sep 15, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.