agent_skills_configurations 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +16 -0
- data/CODE_OF_CONDUCT.md +11 -0
- data/LICENSE.txt +13 -0
- data/README.md +289 -0
- data/Rakefile +17 -0
- data/doc/AgentSkillsConfigurations/Agent.md +112 -0
- data/doc/AgentSkillsConfigurations/Error.md +10 -0
- data/doc/AgentSkillsConfigurations/Registry.md +278 -0
- data/doc/AgentSkillsConfigurations.md +297 -0
- data/doc/index.csv +18 -0
- data/lib/agent_skills_configurations/agent.rb +74 -0
- data/lib/agent_skills_configurations/agents.yml +415 -0
- data/lib/agent_skills_configurations/registry.rb +589 -0
- data/lib/agent_skills_configurations/version.rb +8 -0
- data/lib/agent_skills_configurations.rb +285 -0
- data/sig/agent_skills_configurations.rbs +4 -0
- metadata +79 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
# Class: AgentSkillsConfigurations::Registry
|
|
2
|
+
**Inherits:** Object
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
Loads agent configurations, resolves paths, and exposes query helpers.
|
|
6
|
+
|
|
7
|
+
The Registry is the internal implementation class that handles:
|
|
8
|
+
|
|
9
|
+
* Loading and parsing the YAML configuration file
|
|
10
|
+
* Resolving environment variables to absolute paths
|
|
11
|
+
* Handling fallback paths for missing directories
|
|
12
|
+
* Detecting which agents are installed on the system
|
|
13
|
+
* Caching results for performance
|
|
14
|
+
|
|
15
|
+
This class is typically used through the public API methods in the
|
|
16
|
+
{AgentSkillsConfigurations} module, but can also be used directly for advanced
|
|
17
|
+
use cases.
|
|
18
|
+
|
|
19
|
+
## Path Resolution
|
|
20
|
+
|
|
21
|
+
The Registry uses a sophisticated path resolution system that respects
|
|
22
|
+
environment variables and provides fallback locations. The resolution process
|
|
23
|
+
works as follows:
|
|
24
|
+
|
|
25
|
+
1. Check if the configured environment variable is set and non-empty
|
|
26
|
+
2. If set, use that value as the base path
|
|
27
|
+
3. If not set, use the configured fallback path (often relative to home)
|
|
28
|
+
4. Expand relative paths using the user's home directory
|
|
29
|
+
|
|
30
|
+
Example resolution flow for XDG_CONFIG_HOME:
|
|
31
|
+
|
|
32
|
+
# Configuration in YAML:
|
|
33
|
+
base_paths:
|
|
34
|
+
xdg_config:
|
|
35
|
+
env_var: XDG_CONFIG_HOME
|
|
36
|
+
fallback: ".config"
|
|
37
|
+
|
|
38
|
+
# With environment variable set:
|
|
39
|
+
ENV["XDG_CONFIG_HOME"] = "/custom/xdg"
|
|
40
|
+
# => resolves to "/custom/xdg"
|
|
41
|
+
|
|
42
|
+
# Without environment variable:
|
|
43
|
+
ENV["XDG_CONFIG_HOME"] = nil
|
|
44
|
+
# => resolves to "/Users/username/.config"
|
|
45
|
+
|
|
46
|
+
# Empty environment variable treated as unset:
|
|
47
|
+
ENV["XDG_CONFIG_HOME"] = ""
|
|
48
|
+
# => resolves to "/Users/username/.config"
|
|
49
|
+
|
|
50
|
+
## Global Skills Path Resolution
|
|
51
|
+
|
|
52
|
+
Global skills paths are resolved relative to the agent's base path and support
|
|
53
|
+
multiple fallbacks. The Registry checks each candidate path in order and
|
|
54
|
+
returns the first one that exists:
|
|
55
|
+
|
|
56
|
+
# Configuration in YAML:
|
|
57
|
+
agents:
|
|
58
|
+
- name: moltbot
|
|
59
|
+
base_path: home
|
|
60
|
+
global_skills_path: ".moltbot/skills"
|
|
61
|
+
global_skills_path_fallbacks:
|
|
62
|
+
- ".clawdbot/skills"
|
|
63
|
+
- ".moltbot/skills"
|
|
64
|
+
|
|
65
|
+
# Resolution order:
|
|
66
|
+
# 1. Check ~/.moltbot/skills
|
|
67
|
+
# 2. Check ~/.clawdbot/skills
|
|
68
|
+
# 3. Check ~/.moltbot/skills (fallback)
|
|
69
|
+
# 4. Return first existing path, or primary path if none exist
|
|
70
|
+
|
|
71
|
+
## Installation Detection
|
|
72
|
+
|
|
73
|
+
The Registry determines whether an agent is installed by checking the paths
|
|
74
|
+
configured in the agent's `detect_paths` array. Each path spec can be one of
|
|
75
|
+
several types:
|
|
76
|
+
|
|
77
|
+
* **String**: Check if the path exists relative to the user's home directory
|
|
78
|
+
* *Hash with `cwd`*: Check if the path exists relative to the current
|
|
79
|
+
working directory
|
|
80
|
+
* *Hash with `base` and `path`*: Check if the path exists relative to a
|
|
81
|
+
configured base path
|
|
82
|
+
* *Hash with `absolute`*: Check if the absolute path exists
|
|
83
|
+
|
|
84
|
+
An agent is considered installed if **any** of its detect paths exists.
|
|
85
|
+
|
|
86
|
+
Examples of detect paths:
|
|
87
|
+
|
|
88
|
+
agents:
|
|
89
|
+
- name: cursor
|
|
90
|
+
detect_paths:
|
|
91
|
+
- ".cursor" # Check ~/.cursor exists
|
|
92
|
+
|
|
93
|
+
- name: antigravity
|
|
94
|
+
detect_paths:
|
|
95
|
+
- { cwd: ".agent" } # Check .agent exists in current dir
|
|
96
|
+
- { base: home, path: ".gemini/antigravity" } # Check ~/.gemini/antigravity exists
|
|
97
|
+
|
|
98
|
+
- name: codex
|
|
99
|
+
detect_paths:
|
|
100
|
+
- "" # Always considered installed (empty string matches)
|
|
101
|
+
- { absolute: "/etc/codex" } # Check /etc/codex exists
|
|
102
|
+
|
|
103
|
+
## Caching
|
|
104
|
+
|
|
105
|
+
The Registry caches the results of {all} and {installed} to avoid repeatedly
|
|
106
|
+
parsing the YAML file and checking file system paths. The cache can be cleared
|
|
107
|
+
using {reset}.
|
|
108
|
+
|
|
109
|
+
Use {reset} when:
|
|
110
|
+
|
|
111
|
+
* Environment variables that affect path resolution have changed
|
|
112
|
+
* Agents have been installed or uninstalled
|
|
113
|
+
* The YAML configuration file has been modified
|
|
114
|
+
|
|
115
|
+
**@see** [] Public API module that uses this class
|
|
116
|
+
|
|
117
|
+
**@see** [] Path to the configuration file
|
|
118
|
+
|
|
119
|
+
**@since** [] 0.1.0
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# Instance Methods
|
|
124
|
+
## all() [](#method-i-all)
|
|
125
|
+
Return all configured agents.
|
|
126
|
+
|
|
127
|
+
Returns a frozen array of all {Agent} objects defined in the configuration.
|
|
128
|
+
The result is cached on first call for performance. Path resolution happens
|
|
129
|
+
once during caching and the results are reused on subsequent calls.
|
|
130
|
+
|
|
131
|
+
Use {reset} to clear the cache and force re-resolution when needed.
|
|
132
|
+
|
|
133
|
+
**@raise** [Psych::SyntaxError] when the YAML is invalid (only on first call)
|
|
134
|
+
|
|
135
|
+
**@return** [Array<Agent>] frozen array of all agents with resolved paths
|
|
136
|
+
|
|
137
|
+
**@see** [] Clear the cache
|
|
138
|
+
|
|
139
|
+
**@see** [] Get only installed agents
|
|
140
|
+
|
|
141
|
+
**@since** [] 0.1.0
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
**@example**
|
|
145
|
+
```ruby
|
|
146
|
+
registry = AgentSkillsConfigurations::Registry.new
|
|
147
|
+
all = registry.all
|
|
148
|
+
all.map(&:name)
|
|
149
|
+
# => ["amp", "claude-code", "cursor", "codex", ...]
|
|
150
|
+
```
|
|
151
|
+
**@example**
|
|
152
|
+
```ruby
|
|
153
|
+
registry = AgentSkillsConfigurations::Registry.new
|
|
154
|
+
first_call = registry.all
|
|
155
|
+
second_call = registry.all
|
|
156
|
+
first_call.equal?(second_call) # => true (same object)
|
|
157
|
+
first_call.frozen? # => true
|
|
158
|
+
```## find(name) [](#method-i-find)
|
|
159
|
+
Find an agent by name.
|
|
160
|
+
|
|
161
|
+
Looks up an agent configuration by its canonical name and returns an {Agent}
|
|
162
|
+
value object with resolved paths. This method performs path resolution each
|
|
163
|
+
time it's called, so it reflects the current environment variables and file
|
|
164
|
+
system state.
|
|
165
|
+
|
|
166
|
+
**@param** [String] the canonical agent name from agents.yml
|
|
167
|
+
|
|
168
|
+
**@raise** [Error] when the agent name is unknown
|
|
169
|
+
|
|
170
|
+
**@return** [Agent] the resolved agent configuration with absolute paths
|
|
171
|
+
|
|
172
|
+
**@since** [] 0.1.0
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
**@example**
|
|
176
|
+
```ruby
|
|
177
|
+
registry = AgentSkillsConfigurations::Registry.new
|
|
178
|
+
agent = registry.find("cursor")
|
|
179
|
+
agent.name # => "cursor"
|
|
180
|
+
agent.global_skills_dir # => "/Users/username/.cursor/skills"
|
|
181
|
+
```
|
|
182
|
+
**@example**
|
|
183
|
+
```ruby
|
|
184
|
+
registry.find("unknown-agent")
|
|
185
|
+
# => raises AgentSkillsConfigurations::Error: Unknown agent: unknown-agent
|
|
186
|
+
```## initialize() [](#method-i-initialize)
|
|
187
|
+
Create a registry from the YAML configuration.
|
|
188
|
+
|
|
189
|
+
Loads the agents.yml file and parses it into a data structure that can be
|
|
190
|
+
queried for agent information. The YAML is loaded safely with permitted
|
|
191
|
+
classes for security.
|
|
192
|
+
|
|
193
|
+
**@raise** [Psych::SyntaxError] when the YAML is invalid or malformed
|
|
194
|
+
|
|
195
|
+
**@return** [Registry] a new registry instance with loaded configuration
|
|
196
|
+
|
|
197
|
+
**@since** [] 0.1.0
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
**@example**
|
|
201
|
+
```ruby
|
|
202
|
+
registry = AgentSkillsConfigurations::Registry.new
|
|
203
|
+
registry.find("cursor").name # => "cursor"
|
|
204
|
+
```## installed() [](#method-i-installed)
|
|
205
|
+
Return agents detected as installed on this machine.
|
|
206
|
+
|
|
207
|
+
Filters the list of all agents to those that are detected as installed.
|
|
208
|
+
Installation detection uses the paths configured in each agent's
|
|
209
|
+
`detect_paths` configuration. An agent is considered installed if **any** of
|
|
210
|
+
its detect paths exists.
|
|
211
|
+
|
|
212
|
+
Detection strategies:
|
|
213
|
+
|
|
214
|
+
* String: Check if path exists relative to user's home directory
|
|
215
|
+
* Hash with `cwd`: Check relative to current working directory
|
|
216
|
+
* Hash with `base` and `path`: Check relative to configured base path
|
|
217
|
+
* Hash with `absolute`: Check absolute path directly
|
|
218
|
+
|
|
219
|
+
The result is cached on first call. Use {reset} to clear the cache.
|
|
220
|
+
|
|
221
|
+
**@raise** [Psych::SyntaxError] when the YAML is invalid (only on first call)
|
|
222
|
+
|
|
223
|
+
**@return** [Array<Agent>] frozen array of installed agents with resolved paths
|
|
224
|
+
|
|
225
|
+
**@see** [] Get all configured agents
|
|
226
|
+
|
|
227
|
+
**@see** [] Clear the cache
|
|
228
|
+
|
|
229
|
+
**@since** [] 0.1.0
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
**@example**
|
|
233
|
+
```ruby
|
|
234
|
+
registry = AgentSkillsConfigurations::Registry.new
|
|
235
|
+
installed = registry.installed
|
|
236
|
+
installed.map(&:name)
|
|
237
|
+
# => ["cursor", "claude-code"]
|
|
238
|
+
```
|
|
239
|
+
**@example**
|
|
240
|
+
```ruby
|
|
241
|
+
registry = AgentSkillsConfigurations::Registry.new
|
|
242
|
+
installed_names = registry.installed.map(&:name)
|
|
243
|
+
installed_names.include?("cursor") # => true (if installed)
|
|
244
|
+
installed_names.include?("unknown") # => false
|
|
245
|
+
```## reset() [](#method-i-reset)
|
|
246
|
+
Clear cached agent lists.
|
|
247
|
+
|
|
248
|
+
Clears the internal caches for {all} and {installed} results. This forces path
|
|
249
|
+
resolution to be re-executed on the next call, which is useful when:
|
|
250
|
+
|
|
251
|
+
* Environment variables affecting path resolution have changed
|
|
252
|
+
* Agents have been installed or uninstalled
|
|
253
|
+
* The YAML configuration file has been modified
|
|
254
|
+
|
|
255
|
+
**@return** [void]
|
|
256
|
+
|
|
257
|
+
**@see** [] Get all agents
|
|
258
|
+
|
|
259
|
+
**@see** [] Get installed agents
|
|
260
|
+
|
|
261
|
+
**@since** [] 0.1.0
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
**@example**
|
|
265
|
+
```ruby
|
|
266
|
+
registry = AgentSkillsConfigurations::Registry.new
|
|
267
|
+
ENV["XDG_CONFIG_HOME"] = "/new/path"
|
|
268
|
+
registry.reset
|
|
269
|
+
agent = registry.find("amp")
|
|
270
|
+
agent.global_skills_dir # => "/new/path/agents/skills"
|
|
271
|
+
```
|
|
272
|
+
**@example**
|
|
273
|
+
```ruby
|
|
274
|
+
registry = AgentSkillsConfigurations::Registry.new
|
|
275
|
+
# Install an agent...
|
|
276
|
+
registry.reset
|
|
277
|
+
registry.installed # => includes newly installed agent
|
|
278
|
+
```
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# Module: AgentSkillsConfigurations
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
AgentSkillsConfigurations provides a unified interface for discovering and
|
|
5
|
+
accessing skill configuration paths for various AI coding agents (Cursor,
|
|
6
|
+
Claude Code, Codex, etc.).
|
|
7
|
+
|
|
8
|
+
This library loads agent configurations from a YAML file and resolves
|
|
9
|
+
platform-specific paths for skill directories, taking into account environment
|
|
10
|
+
variables, user home directories, and fallback locations. It supports
|
|
11
|
+
detection of which agents are currently installed on the system and provides
|
|
12
|
+
convenient query methods for accessing agent information.
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
Each AI coding agent has two types of skill directories:
|
|
17
|
+
|
|
18
|
+
1. *Project-level skills* (skills_dir): A relative path within a project
|
|
19
|
+
where project-specific skills are stored (e.g., `.cursor/skills`,
|
|
20
|
+
`.claude/skills`)
|
|
21
|
+
2. *Global skills* (global_skills_dir): An absolute path to the user's global
|
|
22
|
+
skill repository shared across all projects (e.g., `~/.cursor/skills`)
|
|
23
|
+
|
|
24
|
+
The library abstracts away the differences between agents, providing a
|
|
25
|
+
consistent API for working with any supported agent type.
|
|
26
|
+
|
|
27
|
+
## Configuration
|
|
28
|
+
|
|
29
|
+
Agent configurations are defined in `agents.yml`, which contains:
|
|
30
|
+
|
|
31
|
+
* Base path definitions with environment variable references and fallbacks
|
|
32
|
+
* Agent entries with names, display names, skill paths, and detection rules
|
|
33
|
+
|
|
34
|
+
Example YAML structure:
|
|
35
|
+
|
|
36
|
+
base_paths:
|
|
37
|
+
home:
|
|
38
|
+
env_var: ""
|
|
39
|
+
fallback: ""
|
|
40
|
+
xdg_config:
|
|
41
|
+
env_var: XDG_CONFIG_HOME
|
|
42
|
+
fallback: ".config"
|
|
43
|
+
|
|
44
|
+
agents:
|
|
45
|
+
- name: cursor
|
|
46
|
+
display_name: Cursor
|
|
47
|
+
skills_dir: ".cursor/skills"
|
|
48
|
+
base_path: home
|
|
49
|
+
global_skills_path: ".cursor/skills"
|
|
50
|
+
detect_paths:
|
|
51
|
+
- ".cursor"
|
|
52
|
+
|
|
53
|
+
## Finding Agents
|
|
54
|
+
|
|
55
|
+
To get a specific agent configuration by name:
|
|
56
|
+
|
|
57
|
+
agent = AgentSkillsConfigurations.find("cursor")
|
|
58
|
+
agent.name # => "cursor"
|
|
59
|
+
agent.display_name # => "Cursor"
|
|
60
|
+
agent.skills_dir # => ".cursor/skills"
|
|
61
|
+
agent.global_skills_dir # => "/Users/username/.cursor/skills"
|
|
62
|
+
|
|
63
|
+
Finding an unknown agent raises an error:
|
|
64
|
+
|
|
65
|
+
AgentSkillsConfigurations.find("unknown-agent")
|
|
66
|
+
# => raises AgentSkillsConfigurations::Error: Unknown agent: unknown-agent
|
|
67
|
+
|
|
68
|
+
## Listing All Agents
|
|
69
|
+
|
|
70
|
+
To get all configured agents:
|
|
71
|
+
|
|
72
|
+
all_agents = AgentSkillsConfigurations.all
|
|
73
|
+
all_agents.map(&:name)
|
|
74
|
+
# => ["amp", "claude-code", "cursor", "codex", "windsurf", ...]
|
|
75
|
+
|
|
76
|
+
The result is cached for performance. Use {reset!} to clear the cache:
|
|
77
|
+
|
|
78
|
+
AgentSkillsConfigurations.reset!
|
|
79
|
+
|
|
80
|
+
## Detecting Installed Agents
|
|
81
|
+
|
|
82
|
+
To find which agents are installed on the current machine:
|
|
83
|
+
|
|
84
|
+
installed = AgentSkillsConfigurations.installed
|
|
85
|
+
installed.map(&:name)
|
|
86
|
+
# => ["cursor", "claude-code"]
|
|
87
|
+
|
|
88
|
+
Installation detection works by checking configured paths:
|
|
89
|
+
|
|
90
|
+
* String paths: Checks if the path exists relative to the user's home
|
|
91
|
+
directory
|
|
92
|
+
* Hash paths with `cwd`: Checks relative to the current working directory
|
|
93
|
+
* Hash paths with `base`: Resolves using the configured base path
|
|
94
|
+
* Hash paths with `absolute`: Checks the absolute path directly
|
|
95
|
+
|
|
96
|
+
Examples from the configuration:
|
|
97
|
+
|
|
98
|
+
detect_paths:
|
|
99
|
+
- ".cursor" # Check ~/.cursor exists
|
|
100
|
+
- { cwd: ".agent" } # Check .agent exists in current dir
|
|
101
|
+
- { base: home, path: ".codex" } # Check ~/.codex exists
|
|
102
|
+
- { absolute: "/etc/codex" } # Check /etc/codex exists
|
|
103
|
+
|
|
104
|
+
## Environment Variables
|
|
105
|
+
|
|
106
|
+
Global skill paths are resolved using environment variables when available,
|
|
107
|
+
with automatic fallbacks to default locations:
|
|
108
|
+
|
|
109
|
+
* `XDG_CONFIG_HOME`: Used by Amp, Goose, and other XDG-compliant agents
|
|
110
|
+
* `CLAUDE_CONFIG_DIR`: Used by Claude Code and OpenCode
|
|
111
|
+
* `CODEX_HOME`: Used by Codex
|
|
112
|
+
|
|
113
|
+
Example with XDG_CONFIG_HOME:
|
|
114
|
+
|
|
115
|
+
ENV["XDG_CONFIG_HOME"] = "/custom/xdg"
|
|
116
|
+
agent = AgentSkillsConfigurations.find("amp")
|
|
117
|
+
agent.global_skills_dir # => "/custom/xdg/agents/skills"
|
|
118
|
+
|
|
119
|
+
Without the environment variable, falls back to default:
|
|
120
|
+
|
|
121
|
+
ENV["XDG_CONFIG_HOME"] = nil
|
|
122
|
+
agent = AgentSkillsConfigurations.find("amp")
|
|
123
|
+
agent.global_skills_dir # => "/Users/username/.config/agents/skills"
|
|
124
|
+
|
|
125
|
+
## Path Resolution with Fallbacks
|
|
126
|
+
|
|
127
|
+
Some agents support multiple fallback paths for global skills. The first
|
|
128
|
+
existing path is used:
|
|
129
|
+
|
|
130
|
+
agents:
|
|
131
|
+
- name: moltbot
|
|
132
|
+
global_skills_path: ".moltbot/skills"
|
|
133
|
+
global_skills_path_fallbacks:
|
|
134
|
+
- ".clawdbot/skills"
|
|
135
|
+
- ".moltbot/skills"
|
|
136
|
+
|
|
137
|
+
The library checks each candidate path in order and returns the first one that
|
|
138
|
+
exists.
|
|
139
|
+
|
|
140
|
+
## Error Handling
|
|
141
|
+
|
|
142
|
+
The library raises {AgentSkillsConfigurations::Error} for configuration errors
|
|
143
|
+
(unknown agents) and {Psych::SyntaxError} for invalid YAML syntax.
|
|
144
|
+
|
|
145
|
+
**@author** [] Lucian Ghinda
|
|
146
|
+
|
|
147
|
+
**@since** [] 0.1.0
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# Class Methods
|
|
151
|
+
## all() [](#method-c-all)
|
|
152
|
+
Return all configured agents.
|
|
153
|
+
|
|
154
|
+
Returns a frozen array of all {Agent} objects defined in the configuration.
|
|
155
|
+
The result is cached for performance. Use {reset!} to clear the cache when you
|
|
156
|
+
need fresh results (e.g., after changing environment variables).
|
|
157
|
+
**@raise** [Psych::SyntaxError] when the YAML configuration is invalid
|
|
158
|
+
|
|
159
|
+
**@return** [Array<Agent>] all agents defined in `agents.yml`
|
|
160
|
+
|
|
161
|
+
**@see** [] Clear cached agent lists
|
|
162
|
+
|
|
163
|
+
**@see** [] Get only installed agents
|
|
164
|
+
|
|
165
|
+
**@since** [] 0.1.0
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
**@example**
|
|
169
|
+
```ruby
|
|
170
|
+
all_agents = AgentSkillsConfigurations.all
|
|
171
|
+
all_agents.map(&:name)
|
|
172
|
+
# => ["amp", "claude-code", "cursor", "codex", "windsurf", ...]
|
|
173
|
+
```
|
|
174
|
+
**@example**
|
|
175
|
+
```ruby
|
|
176
|
+
AgentSkillsConfigurations.all.each do |agent|
|
|
177
|
+
puts "#{agent.display_name}: #{agent.skills_dir}"
|
|
178
|
+
end
|
|
179
|
+
```
|
|
180
|
+
**@example**
|
|
181
|
+
```ruby
|
|
182
|
+
all = AgentSkillsConfigurations.all
|
|
183
|
+
cursor = all.find { |a| a.name == "cursor" }
|
|
184
|
+
cursor.global_skills_dir # => "/Users/username/.cursor/skills"
|
|
185
|
+
```## find(name ) [](#method-c-find)
|
|
186
|
+
Find a configured agent by name.
|
|
187
|
+
|
|
188
|
+
Returns an {Agent} value object containing the agent's name, display name, and
|
|
189
|
+
resolved skill directory paths. This is the primary method for accessing agent
|
|
190
|
+
configuration.
|
|
191
|
+
**@param** [String] agent name from `agents.yml`
|
|
192
|
+
|
|
193
|
+
**@raise** [Error] when the agent name is unknown
|
|
194
|
+
|
|
195
|
+
**@raise** [Psych::SyntaxError] when the YAML configuration is invalid
|
|
196
|
+
|
|
197
|
+
**@return** [Agent] resolved agent configuration
|
|
198
|
+
|
|
199
|
+
**@since** [] 0.1.0
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
**@example**
|
|
203
|
+
```ruby
|
|
204
|
+
agent = AgentSkillsConfigurations.find("cursor")
|
|
205
|
+
agent.name # => "cursor"
|
|
206
|
+
agent.display_name # => "Cursor"
|
|
207
|
+
agent.skills_dir # => ".cursor/skills"
|
|
208
|
+
agent.global_skills_dir # => "/Users/username/.cursor/skills"
|
|
209
|
+
```
|
|
210
|
+
**@example**
|
|
211
|
+
```ruby
|
|
212
|
+
ENV["CLAUDE_CONFIG_DIR"] = "/custom/claude"
|
|
213
|
+
agent = AgentSkillsConfigurations.find("claude-code")
|
|
214
|
+
agent.global_skills_dir # => "/custom/claude/skills"
|
|
215
|
+
```
|
|
216
|
+
**@example**
|
|
217
|
+
```ruby
|
|
218
|
+
AgentSkillsConfigurations.find("unknown-agent")
|
|
219
|
+
# => raises AgentSkillsConfigurations::Error: Unknown agent: unknown-agent
|
|
220
|
+
```## installed() [](#method-c-installed)
|
|
221
|
+
Return agents that appear to be installed on this machine.
|
|
222
|
+
|
|
223
|
+
Installation is detected by checking the paths configured in each agent's
|
|
224
|
+
`detect_paths` configuration. Different detection strategies are supported:
|
|
225
|
+
|
|
226
|
+
* String paths: Check if the path exists relative to user's home directory
|
|
227
|
+
* Hash with `cwd`: Check relative to current working directory
|
|
228
|
+
* Hash with `base`: Resolve using a configured base path
|
|
229
|
+
* Hash with `absolute`: Check an absolute path directly
|
|
230
|
+
|
|
231
|
+
The result is cached for performance. Use {reset!} to clear the cache.
|
|
232
|
+
**@raise** [Psych::SyntaxError] when the YAML configuration is invalid
|
|
233
|
+
|
|
234
|
+
**@return** [Array<Agent>] agents matching their detect paths
|
|
235
|
+
|
|
236
|
+
**@see** [] Get all configured agents regardless of installation status
|
|
237
|
+
|
|
238
|
+
**@see** [] Clear cached agent lists
|
|
239
|
+
|
|
240
|
+
**@since** [] 0.1.0
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
**@example**
|
|
244
|
+
```ruby
|
|
245
|
+
installed = AgentSkillsConfigurations.installed
|
|
246
|
+
installed.map(&:name)
|
|
247
|
+
# => ["cursor", "claude-code"]
|
|
248
|
+
```
|
|
249
|
+
**@example**
|
|
250
|
+
```ruby
|
|
251
|
+
installed_names = AgentSkillsConfigurations.installed.map(&:name)
|
|
252
|
+
installed_names.include?("cursor") # => true
|
|
253
|
+
installed_names.include?("unknown") # => false
|
|
254
|
+
```
|
|
255
|
+
**@example**
|
|
256
|
+
```ruby
|
|
257
|
+
AgentSkillsConfigurations.installed.each do |agent|
|
|
258
|
+
puts "#{agent.display_name} is installed"
|
|
259
|
+
end
|
|
260
|
+
```## reset!() [](#method-c-reset!)
|
|
261
|
+
Clear cached agent lists.
|
|
262
|
+
|
|
263
|
+
This method clears the internal caches for {all} and {installed} results. Use
|
|
264
|
+
this when you need fresh data, such as:
|
|
265
|
+
|
|
266
|
+
* After changing environment variables that affect path resolution
|
|
267
|
+
* After installing or uninstalling agents
|
|
268
|
+
* After modifying the YAML configuration file
|
|
269
|
+
**@raise** [Psych::SyntaxError] when the YAML configuration is invalid
|
|
270
|
+
|
|
271
|
+
**@return** [void]
|
|
272
|
+
|
|
273
|
+
**@see** [] Returns cached all agents
|
|
274
|
+
|
|
275
|
+
**@see** [] Returns cached installed agents
|
|
276
|
+
|
|
277
|
+
**@since** [] 0.1.0
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
**@example**
|
|
281
|
+
```ruby
|
|
282
|
+
ENV["XDG_CONFIG_HOME"] = "/new/path"
|
|
283
|
+
AgentSkillsConfigurations.reset!
|
|
284
|
+
agent = AgentSkillsConfigurations.find("amp")
|
|
285
|
+
agent.global_skills_dir # => "/new/path/agents/skills"
|
|
286
|
+
```
|
|
287
|
+
**@example**
|
|
288
|
+
```ruby
|
|
289
|
+
AgentSkillsConfigurations.reset!
|
|
290
|
+
installed = AgentSkillsConfigurations.installed
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
# Documentation
|
|
294
|
+
|
|
295
|
+
- [AgentSkillsConfigurations/Agent.md](AgentSkillsConfigurations/Agent.md)
|
|
296
|
+
- [AgentSkillsConfigurations/Error.md](AgentSkillsConfigurations/Error.md)
|
|
297
|
+
- [AgentSkillsConfigurations/Registry.md](AgentSkillsConfigurations/Registry.md)
|
data/doc/index.csv
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name,type,path
|
|
2
|
+
AgentSkillsConfigurations,Module,AgentSkillsConfigurations.md
|
|
3
|
+
AgentSkillsConfigurations.all,Method,AgentSkillsConfigurations.md#method-c-all
|
|
4
|
+
AgentSkillsConfigurations.find,Method,AgentSkillsConfigurations.md#method-c-find
|
|
5
|
+
AgentSkillsConfigurations.installed,Method,AgentSkillsConfigurations.md#method-c-installed
|
|
6
|
+
AgentSkillsConfigurations.reset!,Method,AgentSkillsConfigurations.md#method-c-reset!
|
|
7
|
+
AgentSkillsConfigurations::Error,Class,AgentSkillsConfigurations/Error.md
|
|
8
|
+
AgentSkillsConfigurations::Agent,Class,AgentSkillsConfigurations/Agent.md
|
|
9
|
+
display_name,Attribute,AgentSkillsConfigurations/Agent.md#attribute-i-display_name
|
|
10
|
+
global_skills_dir,Attribute,AgentSkillsConfigurations/Agent.md#attribute-i-global_skills_dir
|
|
11
|
+
name,Attribute,AgentSkillsConfigurations/Agent.md#attribute-i-name
|
|
12
|
+
skills_dir,Attribute,AgentSkillsConfigurations/Agent.md#attribute-i-skills_dir
|
|
13
|
+
AgentSkillsConfigurations::Registry,Class,AgentSkillsConfigurations/Registry.md
|
|
14
|
+
AgentSkillsConfigurations::Registry.all,Method,AgentSkillsConfigurations/Registry.md#method-i-all
|
|
15
|
+
AgentSkillsConfigurations::Registry.find,Method,AgentSkillsConfigurations/Registry.md#method-i-find
|
|
16
|
+
AgentSkillsConfigurations::Registry.initialize,Method,AgentSkillsConfigurations/Registry.md#method-i-initialize
|
|
17
|
+
AgentSkillsConfigurations::Registry.installed,Method,AgentSkillsConfigurations/Registry.md#method-i-installed
|
|
18
|
+
AgentSkillsConfigurations::Registry.reset,Method,AgentSkillsConfigurations/Registry.md#method-i-reset
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AgentSkillsConfigurations
|
|
4
|
+
# Value object describing a configured agent and its skill locations.
|
|
5
|
+
#
|
|
6
|
+
# An Agent represents a single AI coding agent configuration with information about
|
|
7
|
+
# where to find project-level skills and global skills for that agent. This is a
|
|
8
|
+
# read-only data structure returned by {AgentSkillsConfigurations.find} and other
|
|
9
|
+
# query methods.
|
|
10
|
+
#
|
|
11
|
+
# == Agent Attributes
|
|
12
|
+
#
|
|
13
|
+
# Each agent has four key attributes:
|
|
14
|
+
#
|
|
15
|
+
# * +name+ - The canonical identifier used in code (e.g., "cursor", "claude-code")
|
|
16
|
+
# * +display_name+ - A human-friendly name for UI/display purposes (e.g., "Cursor", "Claude Code")
|
|
17
|
+
# * +skills_dir+ - A relative path for project-specific skills (e.g., ".cursor/skills")
|
|
18
|
+
# * +global_skills_dir+ - An absolute path to the user's global skill repository
|
|
19
|
+
#
|
|
20
|
+
# == Understanding Skill Directories
|
|
21
|
+
#
|
|
22
|
+
# AI coding agents typically support two types of skills:
|
|
23
|
+
#
|
|
24
|
+
# 1. *Project Skills* ({skills_dir}): These are specific to a single project and
|
|
25
|
+
# live alongside the project code. For example, a project might have a
|
|
26
|
+
# <tt>.cursor/skills</tt> directory containing skills tailored to that project.
|
|
27
|
+
#
|
|
28
|
+
# 2. *Global Skills* ({global_skills_dir}): These are shared across all projects
|
|
29
|
+
# and typically live in the user's home directory. For example,
|
|
30
|
+
# <tt>~/.cursor/skills</tt> contains reusable skills that work with any project.
|
|
31
|
+
#
|
|
32
|
+
# When working with skills, you typically:
|
|
33
|
+
#
|
|
34
|
+
# * Check the project's +skills_dir+ for project-specific skills
|
|
35
|
+
# * Fall back to +global_skills_dir+ for general-purpose skills
|
|
36
|
+
# * Combine both sources to give the agent full access to available skills
|
|
37
|
+
#
|
|
38
|
+
# == Accessing Agent Information
|
|
39
|
+
#
|
|
40
|
+
# Since Agent is a Data object, all attributes are accessible via reader methods:
|
|
41
|
+
#
|
|
42
|
+
# agent = AgentSkillsConfigurations.find("cursor")
|
|
43
|
+
# agent.name # => "cursor"
|
|
44
|
+
# agent.display_name # => "Cursor"
|
|
45
|
+
# agent.skills_dir # => ".cursor/skills"
|
|
46
|
+
# agent.global_skills_dir # => "/Users/username/.cursor/skills"
|
|
47
|
+
#
|
|
48
|
+
# You can also convert to a Hash:
|
|
49
|
+
#
|
|
50
|
+
# agent.to_h
|
|
51
|
+
# # => { name: "cursor",
|
|
52
|
+
# # display_name: "Cursor",
|
|
53
|
+
# # skills_dir: ".cursor/skills",
|
|
54
|
+
# # global_skills_dir: "/Users/username/.cursor/skills" }
|
|
55
|
+
#
|
|
56
|
+
# @attr_reader [String] name Canonical agent name from `agents.yml`. This is the
|
|
57
|
+
# identifier used when finding agents via {AgentSkillsConfigurations.find}.
|
|
58
|
+
#
|
|
59
|
+
# @attr_reader [String] display_name Human-friendly label for UI/display purposes.
|
|
60
|
+
# This is the name shown to users, e.g., in menus or configuration interfaces.
|
|
61
|
+
#
|
|
62
|
+
# @attr_reader [String] skills_dir Relative directory where project-specific
|
|
63
|
+
# skills live. This path is relative to the project root and should not start
|
|
64
|
+
# with a slash (e.g., ".cursor/skills", not "/.cursor/skills").
|
|
65
|
+
#
|
|
66
|
+
# @attr_reader [String] global_skills_dir Absolute resolved path to global skills.
|
|
67
|
+
# This path is resolved from the YAML configuration, taking into account
|
|
68
|
+
# environment variables and fallbacks. It always begins with a slash.
|
|
69
|
+
#
|
|
70
|
+
# @see AgentSkillsConfigurations.find Find an agent by name
|
|
71
|
+
# @see AgentSkillsConfigurations.all Get all agents
|
|
72
|
+
# @see AgentSkillsConfigurations.detected Get detected agents
|
|
73
|
+
Agent = Data.define(:name, :display_name, :skills_dir, :global_skills_dir)
|
|
74
|
+
end
|