#10016: fix: prevent FD exhaustion from skill watcher scanning artifact trees
agents
stale
Cluster:
Skill Enhancements and Fixes
## Summary
- Expand `DEFAULT_SKILLS_WATCH_IGNORED` to cover Python (`venv`, `.venv`, `__pycache__`, `site-packages`, `.tox`, `.mypy_cache`, `.pytest_cache`, `.ruff_cache`, `__pypackages__`, `*.egg-info`), build (`build`, `target`, `.gradle`, `.next`), and `.disabled` directories — prevents chokidar from opening kqueue/inotify FDs for every file in heavy artifact trees
- Filter out `.disabled` skill directories from `loadSkillEntries` so renaming a skill dir to `my-skill.disabled` disables it
- Exclude artifact directories when copying skills to sandbox workspaces via `syncSkillsToWorkspace`
Fixes #9960
## Test plan
- [x] `npx vitest run src/agents/skills/refresh.test.ts` — 5 tests pass (new ignore pattern coverage)
- [x] `npx vitest run src/agents/skills/workspace.test.ts` — 4 tests pass (disabled dir filtering + copy exclusion)
- [x] `pnpm check` (tsgo + lint + format) — clean
- [x] `pnpm test` — 825/825 non-memory test files pass
- [ ] Manual: create a skill with a `venv/` containing many files, start gateway, verify FD count stays stable (`lsof -p <pid> | wc -l`)
- [ ] Manual: rename a skill dir to `my-skill.disabled`, verify it no longer appears in skill listing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR expands the skill watcher ignore list to cover common heavy artifact trees (Python venv/cache dirs, build outputs, Next.js, Gradle, etc.) to prevent chokidar FD exhaustion when scanning large workspaces. It also adds copy-time exclusions when syncing skills into sandbox workspaces, and introduces a `.disabled` convention intended to disable skills by renaming the directory (plus tests for the new ignore/exclusion patterns and workspace sync behavior).
<h3>Confidence Score: 4/5</h3>
- Mostly safe to merge once the `.disabled` filtering logic is made consistent with the regex-based ignores/excludes.
- Changes are scoped and well-tested for the new ignore/exclude patterns, but the `.disabled` filter currently uses `endsWith(".disabled")`, which can fail for trailing-slash baseDir values and break the intended disable-by-rename behavior.
- src/agents/skills/workspace.ts
<!-- greptile_other_comments_section -->
<sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#12076: fix(skills): recursive directory filtering to actually exclude venv...
by xiaoyaner0201 · 2026-02-08
88.4%
#8291: Fix: Add Python virtual environment ignore patterns to skills watcher
by vishaltandale00 · 2026-02-03
87.9%
#14023: fix: filter skills watcher to relevant file types to prevent FD exh...
by funmerlin · 2026-02-11
86.4%
#6777: fix(skills): ignore Python venvs and caches in skills watcher
by kirkluokun · 2026-02-02
85.9%
#9595: fix(skills): ignore .venv, __pycache__, and .openclaw to prevent FD...
by amoghacloud · 2026-02-05
83.5%
#11250: fix: expand skills watcher ignore list and improve session repair l...
by zhangzhefang-github · 2026-02-07
83.4%
#23749: fix some issues
by tronpis · 2026-02-22
82.3%
#8075: fix(skills): add --ignore-scripts to all package managers
by yubrew · 2026-02-03
81.4%
#19707: fix(agents): apply per-agent skills filter to all run paths
by mcaxtr · 2026-02-18
80.4%
#8150: fix(skills): block dangerous environment variables from skill config
by yubrew · 2026-02-03
80.3%