on main help sign in
feat: discover skills from git root in monorepos (#3078)
commit363ffec9ec38bf84fd2476d28c6906965cda9822 authorTai Groot <tai@taigrr.com> dateThu 4 Jun 2026, 12:00 (4 months ago) parent58348ab
1 file changed+28−6
internal/config/load.go+28−6
internal/config/load.go+28−6
@@ -1046,15 +1046,37 @@ func GlobalSkillsDirs() []string {
10461046 return paths
10471047}
10481048
1049+// projectSkillSubdirs lists the conventional subdirectories where
1050+// project-level skills are discovered. Shared across working-dir and
1051+// git-root lookups to prevent drift when a new convention is added.
1052+var projectSkillSubdirs = []string{
1053+ ".agents/skills",
1054+ ".crush/skills",
1055+ ".claude/skills",
1056+ ".cursor/skills",
1057+}
1058+
10491059// ProjectSkillsDir returns the default project directories for which Crush
1050−// will look for skills.
1060+// will look for skills. In addition to the working directory, it also
1061+// checks the git working tree root so that monorepo-level skills are
1062+// discovered when the user is inside a subdirectory.
1063+// Working-directory paths come first so local skills take precedence
1064+// over monorepo-level ones.
10511065func ProjectSkillsDir(workingDir string) []string {
1052− return []string{
1053− filepath.Join(workingDir, ".agents/skills"),
1054− filepath.Join(workingDir, ".crush/skills"),
1055− filepath.Join(workingDir, ".claude/skills"),
1056− filepath.Join(workingDir, ".cursor/skills"),
1066+ dirs := make([]string, 0, len(projectSkillSubdirs)*2)
1067+ for _, sub := range projectSkillSubdirs {
1068+ dirs = append(dirs, filepath.Join(workingDir, sub))
1069+ }
1070+
1071+ // When the working directory is inside a git repository, also look at
1072+ // the repository root so monorepo-level .agents/skills are found.
1073+ if root := worktreeRoot(workingDir); root != "" && root != workingDir {
1074+ for _, sub := range projectSkillSubdirs {
1075+ dirs = append(dirs, filepath.Join(root, sub))
1076+ }
10571077 }
1078+
1079+ return dirs
10581080}
10591081
10601082func isAppleTerminal() bool { return os.Getenv("TERM_PROGRAM") == "Apple_Terminal" }