Skip to content

Repo-local .agents/skills anchored to nearest git root is invisible from inside sub-repos of a non-git parent (monorepo-grouping layout) #3056

@aheritier

Description

@aheritier

Summary

Local skill discovery for repo-local .agents/skills is anchored to the nearest enclosing git root. In a layout where several independent git repositories are grouped under a non-git parent directory, a skill placed at the grouping-root's .agents/skills is only discovered when the agent's working directory is exactly that root. As soon as docker-agent runs from inside any sub-repo, the upward walk stops at the sub-repo's .git and never reaches the parent — so the grouping-level skill silently disappears.

Severity: low / latent. It does not bite when launching from the grouping root (so it's not the cause of #3054), but the behavior is surprising and undocumented.

Filesystem setup (anonymized)

A common "grouping" layout — a plain directory that is not a git repo, containing multiple independent clones, each its own repo:

~/work/dev/org/                      <- grouping root, NOT a git repo (no .git)
├── .agents/
│   └── skills/
│       └── services/
│           └── SKILL.md             <- skill name: "services"  (grouping-level skill)
├── service-a/                       <- independent repo
│   └── .git/
├── service-b/                       <- independent repo
│   └── .git/
└── docker-agent/                    <- independent repo
    └── .git/

The intent: services is a cross-repo helper skill that should be available no matter which repo you're working in.

What works vs. what doesn't

Working directory when docker-agent is launched projectSearchDirs walks Finds ~/work/dev/org/.agents/skills/services?
~/work/dev/org (grouping root, no .git) no git marker found → returns just [cwd] ✅ yes (cwd == grouping root)
~/work/dev/org/docker-agent hits docker-agent/.git immediately → stops there ❌ no (never reaches the parent)
~/work/dev/org/docker-agent/pkg/skills walks up, hits docker-agent/.git → stops there ❌ no
~/work/dev/org/service-a hits service-a/.git → stops there ❌ no

So the grouping-level services skill is only visible from the one directory that is the grouping root itself; from inside any actual repo (the normal place to do work) it vanishes.

Root cause

projectSearchDirs (in pkg/skills/local.go) walks up from cwd and stops at the first .git marker:

for current := abs; ; {
    dirs = append(dirs, current)
    if hasGitMarker(current) {   // stops at the nearest git root
        gitRoot = current
        break
    }
    parent := filepath.Dir(current)
    if parent == current { break }
    current = parent
}
if gitRoot == "" {
    return []string{abs}         // not in a git repo: only cwd
}

localSearchPaths then scans <dir>/.agents/skills for each returned dir. Because the walk terminates at the nearest git boundary, it can never cross above a repo into a non-git parent. A skill living in that non-git parent is therefore unreachable from inside any sub-repo.

Expected / discussion

At minimum the boundary behavior should be documented (it currently is not — see the doc comments below, which describe "from git root down to cwd" without noting the non-git-parent blind spot). Possible improvements for maintainers to weigh:

  • Continue walking up past a git root to also include .agents/skills in non-git ancestor directories (up to $HOME or a sane ceiling), so grouping-root skills are picked up; and/or
  • Provide an explicit, configurable extra search root (env var or config) for "umbrella"/grouping layouts; and/or
  • Document the git-root anchoring clearly so users know to place shared skills under ~/.agents/skills (the global recursive path), which is unaffected.

Affected code references

  • pkg/skills/local.goprojectSearchDirs (the upward walk that stops at the nearest .git) and localSearchPaths (which builds .agents/skills paths only from projectSearchDirs' result).
  • pkg/skills/local.golocalSearchPaths doc comment: ".agents/skills` from the git root down to cwd (closest wins)".
  • pkg/skills/skills.goLoad doc comment: ".agents/skills/` (flat, scanned from git root to cwd)".

Note

Distinct from #3054 (that issue is a slash-command dispatch loop; this one is about discovery reachability in grouping layouts).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/skillsSkills system and custom slash commandskind/fixPR fixes a bug (maps to fix: commit prefix)

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions