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,285 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "zeitwerk"
|
|
4
|
+
|
|
5
|
+
loader = Zeitwerk::Loader.for_gem
|
|
6
|
+
loader.setup
|
|
7
|
+
|
|
8
|
+
# AgentSkillsConfigurations provides a unified interface for discovering and accessing
|
|
9
|
+
# skill configuration paths for various AI coding agents (Cursor, Claude Code, Codex, etc.).
|
|
10
|
+
#
|
|
11
|
+
# This library loads agent configurations from a YAML file and resolves platform-specific
|
|
12
|
+
# paths for skill directories, taking into account environment variables, user home directories,
|
|
13
|
+
# and fallback locations. It supports detection of which agents are currently detected on the
|
|
14
|
+
# system and provides convenient query methods for accessing agent information.
|
|
15
|
+
#
|
|
16
|
+
# == Overview
|
|
17
|
+
#
|
|
18
|
+
# Each AI coding agent has two types of skill directories:
|
|
19
|
+
#
|
|
20
|
+
# 1. *Project-level skills* (skills_dir): A relative path within a project where
|
|
21
|
+
# project-specific skills are stored (e.g., `.cursor/skills`, `.claude/skills`)
|
|
22
|
+
# 2. *Global skills* (global_skills_dir): An absolute path to the user's global
|
|
23
|
+
# skill repository shared across all projects (e.g., `~/.cursor/skills`)
|
|
24
|
+
#
|
|
25
|
+
# The library abstracts away the differences between agents, providing a consistent
|
|
26
|
+
# API for working with any supported agent type.
|
|
27
|
+
#
|
|
28
|
+
# == Configuration
|
|
29
|
+
#
|
|
30
|
+
# Agent configurations are defined in `agents.yml`, which contains:
|
|
31
|
+
#
|
|
32
|
+
# * Base path definitions with environment variable references and fallbacks
|
|
33
|
+
# * Agent entries with names, display names, skill paths, and detection rules
|
|
34
|
+
#
|
|
35
|
+
# Example YAML structure:
|
|
36
|
+
#
|
|
37
|
+
# base_paths:
|
|
38
|
+
# home:
|
|
39
|
+
# env_var: ""
|
|
40
|
+
# fallback: ""
|
|
41
|
+
# xdg_config:
|
|
42
|
+
# env_var: XDG_CONFIG_HOME
|
|
43
|
+
# fallback: ".config"
|
|
44
|
+
#
|
|
45
|
+
# agents:
|
|
46
|
+
# - name: cursor
|
|
47
|
+
# display_name: Cursor
|
|
48
|
+
# skills_dir: ".cursor/skills"
|
|
49
|
+
# base_path: home
|
|
50
|
+
# global_skills_path: ".cursor/skills"
|
|
51
|
+
# detect_paths:
|
|
52
|
+
# - ".cursor"
|
|
53
|
+
#
|
|
54
|
+
# == Finding Agents
|
|
55
|
+
#
|
|
56
|
+
# To get a specific agent configuration by name:
|
|
57
|
+
#
|
|
58
|
+
# agent = AgentSkillsConfigurations.find("cursor")
|
|
59
|
+
# agent.name # => "cursor"
|
|
60
|
+
# agent.display_name # => "Cursor"
|
|
61
|
+
# agent.skills_dir # => ".cursor/skills"
|
|
62
|
+
# agent.global_skills_dir # => "/Users/username/.cursor/skills"
|
|
63
|
+
#
|
|
64
|
+
# Finding an unknown agent raises an error:
|
|
65
|
+
#
|
|
66
|
+
# AgentSkillsConfigurations.find("unknown-agent")
|
|
67
|
+
# # => raises AgentSkillsConfigurations::Error: Unknown agent: unknown-agent
|
|
68
|
+
#
|
|
69
|
+
# == Listing All Agents
|
|
70
|
+
#
|
|
71
|
+
# To get all configured agents:
|
|
72
|
+
#
|
|
73
|
+
# all_agents = AgentSkillsConfigurations.all
|
|
74
|
+
# all_agents.map(&:name)
|
|
75
|
+
# # => ["amp", "claude-code", "cursor", "codex", "windsurf", ...]
|
|
76
|
+
#
|
|
77
|
+
# The result is cached for performance. Use {reset!} to clear the cache:
|
|
78
|
+
#
|
|
79
|
+
# AgentSkillsConfigurations.reset!
|
|
80
|
+
#
|
|
81
|
+
# == Detecting Agents
|
|
82
|
+
#
|
|
83
|
+
# To find which agents are detected on the current machine:
|
|
84
|
+
#
|
|
85
|
+
# detected = AgentSkillsConfigurations.detected
|
|
86
|
+
# detected.map(&:name)
|
|
87
|
+
# # => ["cursor", "claude-code"]
|
|
88
|
+
#
|
|
89
|
+
# Detection works by checking configured paths:
|
|
90
|
+
#
|
|
91
|
+
# * String paths: Checks if the path exists relative to the user's home 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
|
+
# * <tt>XDG_CONFIG_HOME</tt>: Used by Amp, Goose, and other XDG-compliant agents
|
|
110
|
+
# * <tt>CLAUDE_CONFIG_DIR</tt>: Used by Claude Code and OpenCode
|
|
111
|
+
# * <tt>CODEX_HOME</tt>: 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
|
|
138
|
+
# one that 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
|
+
# @since 0.1.0
|
|
147
|
+
module AgentSkillsConfigurations
|
|
148
|
+
# Base error type for configuration lookup and loading failures.
|
|
149
|
+
class Error < StandardError; end
|
|
150
|
+
|
|
151
|
+
class << self
|
|
152
|
+
# Find a configured agent by name.
|
|
153
|
+
#
|
|
154
|
+
# Returns an {Agent} value object containing the agent's name, display name,
|
|
155
|
+
# and resolved skill directory paths. This is the primary method for accessing
|
|
156
|
+
# agent configuration.
|
|
157
|
+
#
|
|
158
|
+
# @param name [String] agent name from `agents.yml`
|
|
159
|
+
# @return [Agent] resolved agent configuration
|
|
160
|
+
# @raise [Error] when the agent name is unknown
|
|
161
|
+
# @raise [Psych::SyntaxError] when the YAML configuration is invalid
|
|
162
|
+
#
|
|
163
|
+
# @example Find Cursor and access its paths
|
|
164
|
+
# agent = AgentSkillsConfigurations.find("cursor")
|
|
165
|
+
# agent.name # => "cursor"
|
|
166
|
+
# agent.display_name # => "Cursor"
|
|
167
|
+
# agent.skills_dir # => ".cursor/skills"
|
|
168
|
+
# agent.global_skills_dir # => "/Users/username/.cursor/skills"
|
|
169
|
+
#
|
|
170
|
+
# @example Find Claude Code with custom config directory
|
|
171
|
+
# ENV["CLAUDE_CONFIG_DIR"] = "/custom/claude"
|
|
172
|
+
# agent = AgentSkillsConfigurations.find("claude-code")
|
|
173
|
+
# agent.global_skills_dir # => "/custom/claude/skills"
|
|
174
|
+
#
|
|
175
|
+
# @example Error for unknown agent
|
|
176
|
+
# AgentSkillsConfigurations.find("unknown-agent")
|
|
177
|
+
# # => raises AgentSkillsConfigurations::Error: Unknown agent: unknown-agent
|
|
178
|
+
def find(name)
|
|
179
|
+
registry.find(name)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Return all configured agents.
|
|
183
|
+
#
|
|
184
|
+
# Returns a frozen array of all {Agent} objects defined in the configuration.
|
|
185
|
+
# The result is cached for performance. Use {reset!} to clear the cache
|
|
186
|
+
# when you need fresh results (e.g., after changing environment variables).
|
|
187
|
+
#
|
|
188
|
+
# @return [Array<Agent>] all agents defined in `agents.yml`
|
|
189
|
+
# @raise [Psych::SyntaxError] when the YAML configuration is invalid
|
|
190
|
+
#
|
|
191
|
+
# @example List all agent names
|
|
192
|
+
# all_agents = AgentSkillsConfigurations.all
|
|
193
|
+
# all_agents.map(&:name)
|
|
194
|
+
# # => ["amp", "claude-code", "cursor", "codex", "windsurf", ...]
|
|
195
|
+
#
|
|
196
|
+
# @example Iterate through all agents
|
|
197
|
+
# AgentSkillsConfigurations.all.each do |agent|
|
|
198
|
+
# puts "#{agent.display_name}: #{agent.skills_dir}"
|
|
199
|
+
# end
|
|
200
|
+
#
|
|
201
|
+
# @example Access specific agent attributes
|
|
202
|
+
# all = AgentSkillsConfigurations.all
|
|
203
|
+
# cursor = all.find { |a| a.name == "cursor" }
|
|
204
|
+
# cursor.global_skills_dir # => "/Users/username/.cursor/skills"
|
|
205
|
+
#
|
|
206
|
+
# @see #reset! Clear cached agent lists
|
|
207
|
+
# @see #installed Get only installed agents
|
|
208
|
+
def all
|
|
209
|
+
registry.all
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Return agents that appear to be installed on this machine.
|
|
213
|
+
#
|
|
214
|
+
# Installation is detected by checking the paths configured in each agent's
|
|
215
|
+
# <tt>detect_paths</tt> configuration. Different detection strategies are supported:
|
|
216
|
+
#
|
|
217
|
+
# * String paths: Check if the path exists relative to user's home directory
|
|
218
|
+
# * Hash with +cwd+: Check relative to current working directory
|
|
219
|
+
# * Hash with +base+: Resolve using a configured base path
|
|
220
|
+
# * Hash with +absolute+: Check an absolute path directly
|
|
221
|
+
#
|
|
222
|
+
# The result is cached for performance. Use {reset!} to clear the cache.
|
|
223
|
+
#
|
|
224
|
+
# @return [Array<Agent>] agents matching their detect paths
|
|
225
|
+
# @raise [Psych::SyntaxError] when the YAML configuration is invalid
|
|
226
|
+
#
|
|
227
|
+
# @example Get list of installed agents
|
|
228
|
+
# installed = AgentSkillsConfigurations.installed
|
|
229
|
+
# installed.map(&:name)
|
|
230
|
+
# # => ["cursor", "claude-code"]
|
|
231
|
+
#
|
|
232
|
+
# @example Check if a specific agent is installed
|
|
233
|
+
# installed_names = AgentSkillsConfigurations.installed.map(&:name)
|
|
234
|
+
# installed_names.include?("cursor") # => true
|
|
235
|
+
# installed_names.include?("unknown") # => false
|
|
236
|
+
#
|
|
237
|
+
# @example Iterate through installed agents
|
|
238
|
+
# AgentSkillsConfigurations.installed.each do |agent|
|
|
239
|
+
# puts "#{agent.display_name} is installed"
|
|
240
|
+
# end
|
|
241
|
+
#
|
|
242
|
+
# @see #all Get all configured agents regardless of detection status
|
|
243
|
+
# @see #reset! Clear cached agent lists
|
|
244
|
+
def detected
|
|
245
|
+
registry.detected
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Clear cached agent lists.
|
|
249
|
+
#
|
|
250
|
+
# This method clears the internal caches for {all} and {detected} results.
|
|
251
|
+
# Use this when you need fresh data, such as:
|
|
252
|
+
#
|
|
253
|
+
# * After changing environment variables that affect path resolution
|
|
254
|
+
# * After agents' paths are created or removed
|
|
255
|
+
# * After modifying the YAML configuration file
|
|
256
|
+
#
|
|
257
|
+
# @return [void]
|
|
258
|
+
# @raise [Psych::SyntaxError] when the YAML configuration is invalid
|
|
259
|
+
#
|
|
260
|
+
# @example Reset cache after changing environment variable
|
|
261
|
+
# ENV["XDG_CONFIG_HOME"] = "/new/path"
|
|
262
|
+
# AgentSkillsConfigurations.reset!
|
|
263
|
+
# agent = AgentSkillsConfigurations.find("amp")
|
|
264
|
+
# agent.global_skills_dir # => "/new/path/agents/skills"
|
|
265
|
+
#
|
|
266
|
+
# @example Reset cache for fresh detection
|
|
267
|
+
# AgentSkillsConfigurations.reset!
|
|
268
|
+
# detected = AgentSkillsConfigurations.detected
|
|
269
|
+
#
|
|
270
|
+
# @see #all Returns cached all agents
|
|
271
|
+
# @see #detected Returns cached detected agents
|
|
272
|
+
def reset!
|
|
273
|
+
registry.reset
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
private
|
|
277
|
+
|
|
278
|
+
# Lazy-load the registry.
|
|
279
|
+
#
|
|
280
|
+
# @return [Registry]
|
|
281
|
+
def registry
|
|
282
|
+
@registry ||= Registry.new
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: agent_skills_configurations
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Lucian Ghinda
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: zeitwerk
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.6'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.6'
|
|
26
|
+
description: A Ruby library that provides a unified interface for discovering and
|
|
27
|
+
accessing skill configuration paths for 49+ AI coding agents including Cursor, Claude
|
|
28
|
+
Code, Codex, Windsurf, and more. Handles platform-specific path resolution, environment
|
|
29
|
+
variable support, and automatic detection of installed agents.
|
|
30
|
+
email:
|
|
31
|
+
- lucianghinda@users.noreply.github.com
|
|
32
|
+
executables: []
|
|
33
|
+
extensions: []
|
|
34
|
+
extra_rdoc_files: []
|
|
35
|
+
files:
|
|
36
|
+
- ".yardopts"
|
|
37
|
+
- CHANGELOG.md
|
|
38
|
+
- CODE_OF_CONDUCT.md
|
|
39
|
+
- LICENSE.txt
|
|
40
|
+
- README.md
|
|
41
|
+
- Rakefile
|
|
42
|
+
- doc/AgentSkillsConfigurations.md
|
|
43
|
+
- doc/AgentSkillsConfigurations/Agent.md
|
|
44
|
+
- doc/AgentSkillsConfigurations/Error.md
|
|
45
|
+
- doc/AgentSkillsConfigurations/Registry.md
|
|
46
|
+
- doc/index.csv
|
|
47
|
+
- lib/agent_skills_configurations.rb
|
|
48
|
+
- lib/agent_skills_configurations/agent.rb
|
|
49
|
+
- lib/agent_skills_configurations/agents.yml
|
|
50
|
+
- lib/agent_skills_configurations/registry.rb
|
|
51
|
+
- lib/agent_skills_configurations/version.rb
|
|
52
|
+
- sig/agent_skills_configurations.rbs
|
|
53
|
+
homepage: https://github.com/lucianghinda/agent_skills_configurations
|
|
54
|
+
licenses:
|
|
55
|
+
- MIT
|
|
56
|
+
metadata:
|
|
57
|
+
allowed_push_host: https://rubygems.org
|
|
58
|
+
homepage_uri: https://github.com/lucianghinda/agent_skills_configurations
|
|
59
|
+
source_code_uri: https://github.com/lucianghinda/agent_skills_configurations
|
|
60
|
+
changelog_uri: https://github.com/lucianghinda/agent_skills_configurations/blob/main/CHANGELOG.md
|
|
61
|
+
rubygems_mfa_required: 'true'
|
|
62
|
+
rdoc_options: []
|
|
63
|
+
require_paths:
|
|
64
|
+
- lib
|
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - ">="
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: 3.4.0
|
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
requirements: []
|
|
76
|
+
rubygems_version: 4.0.3
|
|
77
|
+
specification_version: 4
|
|
78
|
+
summary: Unified interface for discovering AI coding agent skill paths
|
|
79
|
+
test_files: []
|