[FEATURE] skills/, agents/, commands/ should traverse parent directories like CLAUDE.md does
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
[Feature Request] Consistent Parent Directory Traversal for Skills, Agents, and Commands
Summary
CLAUDE.md and settings.json correctly traverse parent directories when Claude Code is launched from a subdirectory. However, skills/, agents/, and commands/ do not—they currently only resolve from the immediate project's .claude/ folder. This asymmetry forces manual symlinking or duplication in monorepo and devcontainer patterns.
Use Case: Centralized Pipeline
I maintain a centralized Claude Code pipeline for a devcontainer with multiple repositories under a shared root. The intent is to define logic once at /src/.claude/ and have all child repos inherit them automatically.
Workspace Structure
/src/ ← non-git workspace root
├── .claude/
│ ├── settings.json ← hooks, permissions (shared)
│ ├── skills/ ← writing-plans, codex-review
│ ├── agents/ ← explore, bash
│ └── commands/ ← retro, plan-close
├── my-app/ ← git repo A
│ └── .claude/skillbook/ ← localskillbook + retros
└── my-service/ ← git repo B
└── .claude/skillbook/ ← local skillbook + retros
Current Capability Matrix
| Component | Traverses to Parent? | Notes |
| :--- | :---: | :--- |
| CLAUDE.md / rules/ | ✅ Yes | Documented; works correctly |
| settings.json | ✅ Yes | Merges additively with local |
| hooks/ | ✅ Yes | Inherited via settings.json |
| skills/ | ❌ No | Only resolves from immediate project |
| agents/ | ❌ No | Only resolves from immediate project |
| commands/ | ❌ No | Only resolves from immediate project |
The Issue: When a session opens at /src/my-app, Claude finds the parent settings.json but fails to find Skill: writing-plans because it only searches /src/my-app/.claude/skills/.
Current Workaround (and its problems)
I currently force inheritance using symlinks:
ln -s /src/.claude/skills /src/my-app/.claude/skills
ln -s /src/.claude/agents /src/my-app/.claude/agents
ln -s /src/.claude/commands /src/my-app/.claude/commands
Pain Points:
- Requires custom setup scripts to manage links.
- Breaks if the parent path changes or during container rebuilds.
- Introduces circular-symlink risks if the pipeline root is misconfigured.
Expected Behavior
The Skill tool, Task subagent resolver, and slash-command resolver should walk up the directory tree exactly as CLAUDE.md does, stopping at the home directory or filesystem root.
- Precedence: Deeper directories (local) should take precedence over parent directories (global/shared), matching the existing override logic for rules.
Related Issues
- #12962 — Settings.json parent directory traversal (open)
- #10061 — Sub-agents load skills from global dir instead of project dir (closed)
- #10145, #10443 — Skills not loading from project/git root
Proposed Solution
Proposed Solution
Extend the same parent directory traversal that already works for CLAUDE.md to cover skills/, agents/, and commands/ resolution.
Resolution order (most specific wins):
- Immediate project: <cwd>/.claude/skills/<name>/
- Parent directories: walk up the tree, checking <parent>/.claude/skills/<name>/ at each level
- Global user: ~/.claude/skills/<name>/
This mirrors how CLAUDE.md files are already composed — deeper files take precedence, parent files fill in the gaps.
Scope
The same logic should apply consistently to all three lookup paths:
- skills/ — Skill tool invocation
- agents/ — Task tool subagent type resolution
- commands/ — slash command resolution
All three currently share the same "immediate project only" limitation, so the fix should be applied uniformly rather than piecemeal.
Traversal boundary
Stop at the user's home directory (same boundary as CLAUDE.md traversal), or at the first directory where no .claude/ folder exists. Do not cross into unrelated filesystem roots.
No breaking changes
Projects that already have a full local skills/ are unaffected — local definitions take precedence. The traversal only activates when a definition is not found locally.
---
Short, concrete, matches the pattern they already ship for CLAUDE.md. Should slot straight in.
Alternative Solutions
What have I tried / Alternative Solutions
Symlinks per child repo
Our current workaround: cc-work (our pipeline setup tool) creates symlinks in each child repo pointing to the parent pipeline:
ln -s /src/.claude/skills /src/my-app/.claude/skills
ln -s /src/.claude/agents /src/my-app/.claude/agents
ln -s /src/.claude/commands /src/my-app/.claude/commands
This works but has several drawbacks:
- Requires setup tooling to create and manage the symlinks on every new repo
- Silent failure mode: if the symlink is missing (e.g. new developer, fresh clone), skills resolve from global ~/.claude/ without any error — wrong behaviour with no diagnostic
- Circular symlink risk: if the pipeline root itself is accidentally included in the setup loop, skills -> skills (self-referential). I had to add explicit guard logic to detect and skip this case
- Repos with custom local skills (e.g. a project-specific code reviewer) cannot use a directory-level symlink — they need the real directory, which then loses access to all parent skills entirely
Copying skills into every child repo
Rejected: creates multiple out-of-sync copies. Every pipeline update requires re-copying to all downstream repos. Defeats the purpose of a centralised pipeline.
Global ~/.claude/skills/
Rejected: global skills apply to every project on the machine, not just repos under the shared pipeline. Breaks isolation between unrelated projects
Priority
Medium - Would be very helpful
Feature Category
CLI commands and flags
Use Case Example
_No response_
Additional Context
Use Case Example
A devcontainer workspace with multiple repos under a shared root:
/src/ ← non-git workspace root
├── .claude/
│ ├── CLAUDE.md ← inherited ✅ (traversal works today)
│ ├── settings.json ← inherited ✅ (traversal works today)
│ ├── hooks/ ← inherited ✅ (via settings.json)
│ ├── skills/
│ │ ├── planning-skill/ ← NOT inherited ❌
│ │ └── code-review-skill/ ← NOT inherited ❌
│ ├── agents/
│ │ ├── fast-search.md ← NOT inherited ❌
│ │ └── test-runner.md ← NOT inherited ❌
│ └── commands/
│ ├── retrospective.md ← NOT inherited ❌
│ └── close-task.md ← NOT inherited ❌
│
├── my-app/ ← git repo, session opened here
│ └── .claude/
│ └── project-data/
│
└── my-service/ ← git repo
└── .claude/
└── project-data/
A Claude Code session opened at /src/my-app correctly picks up /src/.claude/CLAUDE.md and /src/.claude/settings.json. However:
> Skill: planning-skill
Error: skill not found
The skill exists at /src/.claude/skills/planning-skill/ but Claude only checks /src/my-app/.claude/skills/ — which doesn't exist. The session falls back to ~/.claude/skills/ (global), finds nothing, and fails.
The same applies to custom agents and slash commands. A session at /src/my-app cannot use fast-search as a Task subagent type, and /retrospective is not available as a command — despite both being defined one directory level up.
With the proposed fix, all three would resolve through parent traversal exactly as CLAUDE.md does today. No symlinks, no duplication, no setup tooling required.
Showing cached comments. Read the full discussion on GitHub ↗
15 Comments
this is weird, it was working exactly as described in the feature request. Even it's documented here:
<img width="836" height="485" alt="Image" src="https://github.com/user-attachments/assets/8c835e63-99a6-44a4-813a-2c263c8d2d7f" />
claudelog.com/faqs/what-is-nested-skills-discovery-in-claude-code/ (you dont have to access the link, image shows documented example)
I have a whole folder that just stopped working as it used to be, with several projects inside, all of them were able to access to skills from root.
+1 — hitting this exact issue in a monorepo with multiple apps under one git root.
I have a project-level skill in
package/w3geekery/sme-mart-angular/.claude/skills/sme-mart-angular-architect.mdthat's scoped to one Angular app in the monorepo. It has proper frontmatter (name,description,tools) but Claude Code never discovers it because skill resolution only checks the git root's.claude/skills/.Moving it to the root would be wrong — the skill is specific to one package and irrelevant to the other apps in the repo. The current workaround is asking Claude to manually read the file, which works but loses the slash-command invocation UX.
CLAUDE.mdalready handles this correctly with parent directory traversal — skills should do the same.today is working again as before, can you check OP, is this what are you looking for ?
<img width="3054" height="1322" alt="Image" src="https://github.com/user-attachments/assets/126f41dd-178d-43ca-a76c-07b02fb0bcaf" />
+1, this is a real friction point.
Our workaround in production (managing 112 skills across multiple projects):
Option 1: Symlink to a central skills directory
Option 2: Install script that copies to ~/.claude/skills/
We use a global installer that puts all skills in
~/.claude/skills/(the user-level directory). This way, skills are available in every project regardless of directory structure:Option 3: Category-based install for project-specific needs
The root issue is valid — skills should traverse parent directories like CLAUDE.md does. But until that's implemented, user-level
~/.claude/skills/is the most portable solution.+1 on this!
This would be great to have!
please!
I ran into a situation today that made me search for a feature like this: scoping architectural skills to specific apps in the monorepo.
I'd love this feature!
+1, we've ended up making a custom MCP to dynamically search through all nested files and "reassemble" them for the root Claude Code to use. It's a lot of extra overhead.
We're also hoping this could handle MCPs for nested subagents too. We have a monorepo use case where at the root we don't include a Figma MCP. But we have a frontend service within the monorepo, and there we define the Figma MCP in its own .mcp.json for just that frontend service. Ideally we would want the root level Claude Code instance to be able to inherit the frontend service's subagents, run them, and those subagents would have access to only their set of MCPs (like Figma).
/tmp/issue-26489-comment.md
+1 I would really appreciate this feature! Right now the workaround for me is the use of symlinks from the parent folder
+1 we need this asap. it will be great for monorepos
+1
+1 We could really use this!
+1, and this is more urgent than it sounds. A few related problems all stem from the same root cause (no upward traversal for
.claude/):1. Inconsistency across
.claude/contentsCLAUDE.mdtraverses upward ✅skills/,agents/,commands/do not ❌.claude/settings.json(includingenabledPlugins) does not ❌A user installs a plugin at "project scope," sees CLAUDE.md working correctly from a subdirectory, and reasonably assumes everything else under
.claude/behaves the same way. It doesn't — the plugin silently isn't loaded, with no warning, no log, no indication anything is wrong.2. The install UI makes a promise it doesn't keep
The
/plugininstall prompt literally describes project scope as "Install for all collaborators on this repository." That wording makes a concrete promise about repo-wide reach. The actual behavior is "install for collaborators who launch claude from this exact directory" — a completely different contract. Either the traversal needs to be added to match the promise, or the wording needs to change to something honest like "Install for collaborators who launch from this directory."3. Project scope becomes indistinguishable from local scope
The moment you
cdinto any subdirectory — which is most of the time in a real repo — project scope silently stops applying. So the three scopes (user / project / local) effectively collapse into two: "user" and "this exact directory." That defeats the purpose of having a project tier at all.4. Littered config files
Because there's no traversal, users accumulate
.claude/settings.local.json(and.claude/directories generally) scattered across subdirectories of a single repo — one per directory they happened to launch from. Results:find . -name settings.local.jsonand diff..gitignorehas to cover arbitrary depths).5. Inconsistent with every other tool in the ecosystem
git, npm, pnpm, cargo, tsconfig, .gitignore, direnv, editorconfig — all walk up to find the project root. Claude Code not doing so means users have to either launch from repo root every time (fragile), symlink
.claude/into every subdir (gross), or fall back to user scope (defeats per-project install).The fix
Uniform upward traversal for everything under
.claude/, matching how essentially every other dev tool resolves project config. This isn't a nice-to-have — the current behavior makes project-scoped plugins a footgun and makes the install UI actively misleading. Please prioritize.