Module: AgentSkillsConfigurations

Defined in:
lib/agent_skills_configurations.rb,
lib/agent_skills_configurations/agent.rb,
lib/agent_skills_configurations/version.rb,
lib/agent_skills_configurations/registry.rb

Overview

AgentSkillsConfigurations provides a unified interface for discovering and accessing skill configuration paths for various AI coding agents (Cursor, Claude Code, Codex, etc.).

This library loads agent configurations from a YAML file and resolves platform-specific paths for skill directories, taking into account environment variables, user home directories, and fallback locations. It supports detection of which agents are currently detected on the system and provides convenient query methods for accessing agent information.

Overview

Each AI coding agent has two types of skill directories:

  1. Project-level skills (skills_dir): A relative path within a project where project-specific skills are stored (e.g., .cursor/skills, .claude/skills)
  2. Global skills (global_skills_dir): An absolute path to the user's global skill repository shared across all projects (e.g., ~/.cursor/skills)

The library abstracts away the differences between agents, providing a consistent API for working with any supported agent type.

Configuration

Agent configurations are defined in agents.yml, which contains:

  • Base path definitions with environment variable references and fallbacks
  • Agent entries with names, display names, skill paths, and detection rules

Example YAML structure:

base_paths:
home:
  env_var: ""
  fallback: ""
xdg_config:
  env_var: XDG_CONFIG_HOME
  fallback: ".config"

agents:
- name: cursor
  display_name: Cursor
  skills_dir: ".cursor/skills"
  base_path: home
  global_skills_path: ".cursor/skills"
  detect_paths:
    - ".cursor"

Finding Agents

To get a specific agent configuration by name:

agent = AgentSkillsConfigurations.find("cursor")
agent.name              # => "cursor"
agent.display_name      # => "Cursor"
agent.skills_dir        # => ".cursor/skills"
agent.global_skills_dir # => "/Users/username/.cursor/skills"

Finding an unknown agent raises an error:

AgentSkillsConfigurations.find("unknown-agent")
# => raises AgentSkillsConfigurations::Error: Unknown agent: unknown-agent

Listing All Agents

To get all configured agents:

all_agents = AgentSkillsConfigurations.all
all_agents.map(&:name)
# => ["amp", "claude-code", "cursor", "codex", "windsurf", ...]

The result is cached for performance. Use AgentSkillsConfigurations.reset! to clear the cache:

AgentSkillsConfigurations.reset!

Detecting Agents

To find which agents are detected on the current machine:

detected = AgentSkillsConfigurations.detected
detected.map(&:name)
# => ["cursor", "claude-code"]

Detection works by checking configured paths:

  • String paths: Checks if the path exists relative to the user's home directory
  • Hash paths with cwd: Checks relative to the current working directory
  • Hash paths with base: Resolves using the configured base path
  • Hash paths with absolute: Checks the absolute path directly

Examples from the configuration:

detect_paths:
- ".cursor"                    # Check ~/.cursor exists
- { cwd: ".agent" }             # Check .agent exists in current dir
- { base: home, path: ".codex" } # Check ~/.codex exists
- { absolute: "/etc/codex" }    # Check /etc/codex exists

Environment Variables

Global skill paths are resolved using environment variables when available, with automatic fallbacks to default locations:

  • XDG_CONFIG_HOME: Used by Amp, Goose, and other XDG-compliant agents
  • CLAUDE_CONFIG_DIR: Used by Claude Code and OpenCode
  • CODEX_HOME: Used by Codex

Example with XDG_CONFIG_HOME:

ENV["XDG_CONFIG_HOME"] = "/custom/xdg"
agent = AgentSkillsConfigurations.find("amp")
agent.global_skills_dir  # => "/custom/xdg/agents/skills"

Without the environment variable, falls back to default:

ENV["XDG_CONFIG_HOME"] = nil
agent = AgentSkillsConfigurations.find("amp")
agent.global_skills_dir  # => "/Users/username/.config/agents/skills"

Path Resolution with Fallbacks

Some agents support multiple fallback paths for global skills. The first existing path is used:

agents:
- name: moltbot
  global_skills_path: ".moltbot/skills"
  global_skills_path_fallbacks:
    - ".clawdbot/skills"
    - ".moltbot/skills"

The library checks each candidate path in order and returns the first one that exists.

Error Handling

The library raises Error for configuration errors (unknown agents) and Psych::SyntaxError for invalid YAML syntax.

Author:

  • Lucian Ghinda

Since:

  • 0.1.0

Defined Under Namespace

Classes: Agent, Error, Registry

Constant Summary collapse

VERSION =

Gem version.

Returns:

  • (String)

Since:

  • 0.1.0

"0.1.0"

Class Method Summary collapse

Class Method Details

.allArray<Agent>

Return all configured agents.

Returns a frozen array of all Agent objects defined in the configuration. The result is cached for performance. Use reset! to clear the cache when you need fresh results (e.g., after changing environment variables).

Examples:

List all agent names

all_agents = AgentSkillsConfigurations.all
all_agents.map(&:name)
# => ["amp", "claude-code", "cursor", "codex", "windsurf", ...]

Iterate through all agents

AgentSkillsConfigurations.all.each do |agent|
  puts "#{agent.display_name}: #{agent.skills_dir}"
end

Access specific agent attributes

all = AgentSkillsConfigurations.all
cursor = all.find { |a| a.name == "cursor" }
cursor.global_skills_dir # => "/Users/username/.cursor/skills"

Returns:

  • (Array<Agent>)

    all agents defined in agents.yml

Raises:

  • (Psych::SyntaxError)

    when the YAML configuration is invalid

See Also:

  • Clear cached agent lists
  • Get only installed agents

Since:

  • 0.1.0



208
209
210
# File 'lib/agent_skills_configurations.rb', line 208

def all
  registry.all
end

.detectedArray<Agent>

Return agents that appear to be installed on this machine.

Installation is detected by checking the paths configured in each agent's detect_paths configuration. Different detection strategies are supported:

  • String paths: Check if the path exists relative to user's home directory
  • Hash with cwd: Check relative to current working directory
  • Hash with base: Resolve using a configured base path
  • Hash with absolute: Check an absolute path directly

The result is cached for performance. Use reset! to clear the cache.

Examples:

Get list of installed agents

installed = AgentSkillsConfigurations.installed
installed.map(&:name)
# => ["cursor", "claude-code"]

Check if a specific agent is installed

installed_names = AgentSkillsConfigurations.installed.map(&:name)
installed_names.include?("cursor")  # => true
installed_names.include?("unknown") # => false

Iterate through installed agents

AgentSkillsConfigurations.installed.each do |agent|
  puts "#{agent.display_name} is installed"
end

Returns:

  • (Array<Agent>)

    agents matching their detect paths

Raises:

  • (Psych::SyntaxError)

    when the YAML configuration is invalid

See Also:

  • Get all configured agents regardless of detection status
  • Clear cached agent lists

Since:

  • 0.1.0



244
245
246
# File 'lib/agent_skills_configurations.rb', line 244

def detected
  registry.detected
end

.find(name) ⇒ Agent

Find a configured agent by name.

Returns an Agent value object containing the agent's name, display name, and resolved skill directory paths. This is the primary method for accessing agent configuration.

Examples:

Find Cursor and access its paths

agent = AgentSkillsConfigurations.find("cursor")
agent.name              # => "cursor"
agent.display_name      # => "Cursor"
agent.skills_dir        # => ".cursor/skills"
agent.global_skills_dir # => "/Users/username/.cursor/skills"

Find Claude Code with custom config directory

ENV["CLAUDE_CONFIG_DIR"] = "/custom/claude"
agent = AgentSkillsConfigurations.find("claude-code")
agent.global_skills_dir # => "/custom/claude/skills"

Error for unknown agent

AgentSkillsConfigurations.find("unknown-agent")
# => raises AgentSkillsConfigurations::Error: Unknown agent: unknown-agent

Parameters:

  • name (String)

    agent name from agents.yml

Returns:

  • (Agent)

    resolved agent configuration

Raises:

  • (Error)

    when the agent name is unknown

  • (Psych::SyntaxError)

    when the YAML configuration is invalid

Since:

  • 0.1.0



178
179
180
# File 'lib/agent_skills_configurations.rb', line 178

def find(name)
  registry.find(name)
end

.reset!void

This method returns an undefined value.

Clear cached agent lists.

This method clears the internal caches for all and detected results. Use this when you need fresh data, such as:

  • After changing environment variables that affect path resolution
  • After agents' paths are created or removed
  • After modifying the YAML configuration file

Examples:

Reset cache after changing environment variable

ENV["XDG_CONFIG_HOME"] = "/new/path"
AgentSkillsConfigurations.reset!
agent = AgentSkillsConfigurations.find("amp")
agent.global_skills_dir # => "/new/path/agents/skills"

Reset cache for fresh detection

AgentSkillsConfigurations.reset!
detected = AgentSkillsConfigurations.detected

Raises:

  • (Psych::SyntaxError)

    when the YAML configuration is invalid

See Also:

  • Returns cached all agents
  • Returns cached detected agents

Since:

  • 0.1.0



272
273
274
# File 'lib/agent_skills_configurations.rb', line 272

def reset!
  registry.reset
end