Skip to content

Commit 0dab0e7

Browse files
committed
Fix 4 project-scope bugs: idempotency check, list label, update guard, agent prompt
1. allAgentsHaveSkill now uses agentSkillsDirForScope so the idempotency check looks in the correct directory during --project installs. 2. list --project with no installed state now shows "(project)" instead of "(global)" in the summary line. 3. UpdateSkills now returns an error when all detected agents are incompatible with project scope, matching the install flow guard. 4. Install prompt pre-filters agents by project-scope compatibility, so users only see agents that can actually receive the skills. Co-authored-by: Isaac
1 parent 76235f1 commit 0dab0e7

File tree

4 files changed

+29
-5
lines changed

4 files changed

+29
-5
lines changed

experimental/aitools/cmd/install.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ Supported agents: Claude Code, Cursor, Codex CLI, OpenCode, GitHub Copilot, Anti
5353
return nil
5454
}
5555

56+
// For project scope, pre-filter to compatible agents before prompting.
57+
if scope == installer.ScopeProject {
58+
detected = filterProjectScopeAgents(detected)
59+
if len(detected) == 0 {
60+
return fmt.Errorf("no detected agents support project-scoped skills")
61+
}
62+
}
63+
5664
switch {
5765
case len(detected) == 1:
5866
targetAgents = detected
@@ -120,6 +128,17 @@ func resolveAgentNames(ctx context.Context, names string) ([]*agents.Agent, erro
120128
return result, nil
121129
}
122130

131+
// filterProjectScopeAgents returns only agents that support project-scoped skills.
132+
func filterProjectScopeAgents(detected []*agents.Agent) []*agents.Agent {
133+
var compatible []*agents.Agent
134+
for _, a := range detected {
135+
if a.SupportsProjectScope {
136+
compatible = append(compatible, a)
137+
}
138+
}
139+
return compatible
140+
}
141+
123142
// printNoAgentsMessage prints the "no agents detected" message.
124143
func printNoAgentsMessage(ctx context.Context) {
125144
cmdio.LogString(ctx, color.YellowString("No supported coding agents detected."))

experimental/aitools/cmd/list.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,10 @@ func defaultListSkills(cmd *cobra.Command, scope string) error {
132132
cmdio.LogString(ctx, fmt.Sprintf("%d/%d skills installed (global), %d/%d (project)", globalCount, len(names), projectCount, len(names)))
133133
case projectState != nil:
134134
cmdio.LogString(ctx, fmt.Sprintf("%d/%d skills installed (project)", projectCount, len(names)))
135+
case scope == installer.ScopeProject:
136+
cmdio.LogString(ctx, fmt.Sprintf("%d/%d skills installed (project)", 0, len(names)))
135137
default:
136-
installedCount := globalCount
137-
cmdio.LogString(ctx, fmt.Sprintf("%d/%d skills installed (global)", installedCount, len(names)))
138+
cmdio.LogString(ctx, fmt.Sprintf("%d/%d skills installed (global)", globalCount, len(names)))
138139
}
139140
return nil
140141
}

experimental/aitools/lib/installer/installer.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ func InstallSkillsForAgents(ctx context.Context, src ManifestSource, targetAgent
174174
// dir exists, AND every requested agent already has the skill on disk.
175175
if state != nil && state.Skills[name] == meta.Version {
176176
skillDir := filepath.Join(baseDir, name)
177-
if _, statErr := os.Stat(skillDir); statErr == nil && allAgentsHaveSkill(ctx, name, targetAgents) {
177+
if _, statErr := os.Stat(skillDir); statErr == nil && allAgentsHaveSkill(ctx, name, targetAgents, scope, cwd) {
178178
log.Debugf(ctx, "%s v%s already installed for all agents, skipping", name, meta.Version)
179179
continue
180180
}
@@ -371,9 +371,9 @@ func hasSkillsOnDisk(dir string) bool {
371371

372372
// allAgentsHaveSkill returns true if every agent in the list has the named
373373
// skill directory present (either as a real directory or symlink).
374-
func allAgentsHaveSkill(ctx context.Context, skillName string, targetAgents []*agents.Agent) bool {
374+
func allAgentsHaveSkill(ctx context.Context, skillName string, targetAgents []*agents.Agent, scope, cwd string) bool {
375375
for _, agent := range targetAgents {
376-
agentSkillDir, err := agent.SkillsDir(ctx)
376+
agentSkillDir, err := agentSkillsDirForScope(ctx, agent, scope, cwd)
377377
if err != nil {
378378
return false
379379
}

experimental/aitools/lib/installer/update.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@ func UpdateSkills(ctx context.Context, src ManifestSource, targetAgents []*agent
6161
if err != nil {
6262
return nil, fmt.Errorf("failed to determine working directory: %w", err)
6363
}
64+
incompatible := incompatibleAgentNames(targetAgents)
6465
targetAgents = filterProjectAgents(ctx, targetAgents)
66+
if len(targetAgents) == 0 {
67+
return nil, fmt.Errorf("no agents support project-scoped skills. The following detected agents are global-only: %s", strings.Join(incompatible, ", "))
68+
}
6569
}
6670

6771
state, err := LoadState(baseDir)

0 commit comments

Comments
 (0)