# `ClaudeWrapper.Skills`
[🔗](https://github.com/genagent/claude_wrapper_ex/blob/main/lib/claude_wrapper/skills.ex#L67)

Read-side access to Claude Code's on-disk **skill** definitions.

Claude Code resolves user-level skills from
`~/.claude/skills/<dir_stem>/SKILL.md`. Unlike agents (which are flat
`.md` files), each skill is a *directory* containing a `SKILL.md`
plus optional bundled assets (`scripts/`, `reference/`, etc.). The
frontmatter on `SKILL.md` carries the skill's metadata (name,
description); the body is the skill's instructions.

This module is read-only on purpose -- mutations (create / update /
delete) are deferred. Creating a skill is more involved than a file
write because it implies directory layout and optional scaffold
assets.

Two levels of granularity:

  * `list/1` -- enumerate every skill at the root with summary
    metadata (name, description, dir path, has_assets).
  * `get/2` -- read one skill's full record including the
    instructions body.

## Frontmatter format

Real-world skills look like:

    ---
    name: recall
    description: Search mente for memories by topic, text, tags, or ranked search
    ---

    # Search mente for memories
    ...

The parser is permissive: only `name` and `description` are typed.
Any other `key: value` pairs land in `Skill.extra` so unknown future
keys survive a round trip. Frontmatter is optional -- a body-only
`SKILL.md` parses fine, with `name` defaulting to the directory stem.

## Stem, name, directory

By convention a skill's `name` matches its directory name:
`~/.claude/skills/recall/SKILL.md` carries `name: recall`. The two
can diverge -- the parser keeps both. `get/2` looks up by directory
stem (because that's what the filesystem indexes), not by the
frontmatter `name`.

## Pointing at a different root

The default is `~/.claude/skills`. Pass an explicit path to `at/1`
to point at a different directory -- a temp dir in tests, a
non-default Claude Code install. The on-disk layout
(`<root>/<dir_stem>/SKILL.md`) is the same regardless of root.

## Example

    {:ok, root} = ClaudeWrapper.Skills.home()
    {:ok, summaries} = ClaudeWrapper.Skills.list(root)

    for s <- summaries do
      IO.puts("#{s.dir_stem}: #{s.description}")
    end

    {:ok, skill} = ClaudeWrapper.Skills.get(root, "recall")
    IO.puts(skill.body)

# `t`

```elixir
@type t() :: %ClaudeWrapper.Skills{root: String.t()}
```

# `at`

```elixir
@spec at(String.t()) :: t()
```

Use a specific path as the skills root. Useful for tests (point at a
temp dir) and non-default installs.

# `get`

```elixir
@spec get(t(), String.t()) ::
  {:ok, ClaudeWrapper.Skills.Skill.t()} | {:error, ClaudeWrapper.Error.t()}
```

Read one skill by directory stem (the basename of the `<dir_stem>/`
directory under the root) into a full `Skill`.

Returns `{:error, %ClaudeWrapper.Error{kind: :not_found}}` when no such
directory exists or it has no `SKILL.md`.

# `home`

```elixir
@spec home() :: {:ok, t()} | {:error, ClaudeWrapper.Error.t()}
```

Resolve the default skills root, `~/.claude/skills`.

Returns `{:error, %ClaudeWrapper.Error{kind: :no_home}}` when the user
home cannot be determined.

# `list`

```elixir
@spec list(t()) ::
  {:ok, [ClaudeWrapper.Skills.Summary.t()]} | {:error, ClaudeWrapper.Error.t()}
```

List every skill at the root, sorted by directory stem.

A "skill" is any direct child directory of the root that contains a
`SKILL.md`. Directories without `SKILL.md` and non-directory entries
are ignored. Returns `{:ok, []}` when the root directory does not
exist (a fresh install with no user skills). Directories whose
`SKILL.md` fails to read are skipped rather than failing the whole
listing.

# `root`

```elixir
@spec root(t()) :: String.t()
```

The configured root directory.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
