> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rkat.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Skills

> Domain-specific knowledge injection via markdown documents with YAML frontmatter

Skills inject domain-specific knowledge into the agent's context. A skill is a `SKILL.md` document with YAML frontmatter, addressed at runtime by `SkillKey { source_uuid, skill_name }`, and included in the system prompt or per-turn context when its required capabilities are available.

<Note>
  This page is the task-first guide. For the low-level runtime vocabulary and identity model, see [Skills reference](/reference/skills-reference).
</Note>

## What this guide is for

Use this guide when you want to:

* create or configure skill sources
* preload or inject skills into sessions
* understand `SkillKey` identity and source provenance
* understand when to use `preload_skills` vs `skill_refs`

## Skill sources

Skills are discovered from multiple source transports:

* **Embedded** builtin skills from component crates
* **Project/runtime root** (`<context-root>/.rkat/skills/`) when a context root is active
* **Configured filesystem sources**
* **Git repositories** cloned to local cache and refreshed on TTL
* **HTTP endpoints** fetched from remote skill servers
* **Stdio sources**

<Note>
  The canonical identity is the pair of `source_uuid` and `skill_name`. Two sources can both provide `task-workflow` without colliding because their source UUIDs differ. First-source-wins shadowing applies only when the same full `SkillKey` appears more than once.
</Note>

### Git sources

Configured in skills settings (typically in realm `config.toml`). Uses the system `git` executable:

```toml theme={null}
[[repositories]]
name = "company"
source_uuid = "11111111-1111-1111-1111-111111111111"
type = "git"
url = "https://github.com/company/meerkat-skills.git"
git_ref = "main"
ref_type = "branch"    # "branch", "tag", or "commit"
refresh_seconds = 300  # TTL for branch refs (tags/commits are immutable)
depth = 1              # shallow clone depth
# auth_token = "${GITHUB_TOKEN}"  # optional, env vars expanded
```

### HTTP sources

```toml theme={null}
[[repositories]]
name = "remote"
source_uuid = "22222222-2222-2222-2222-222222222222"
type = "http"
url = "https://skills.example.com/api"
auth_token = "${SKILLS_API_KEY}"
refresh_seconds = 300
timeout_seconds = 15
```

### Filesystem and stdio sources

```toml theme={null}
[[repositories]]
name = "local-shared"
source_uuid = "33333333-3333-3333-3333-333333333333"
type = "filesystem"
path = "/opt/meerkat-skills"

[[repositories]]
name = "generated"
source_uuid = "44444444-4444-4444-4444-444444444444"
type = "stdio"
command = "my-skill-server"
args = ["--json"]
```

## SKILL.md format

Each skill is a markdown file with YAML frontmatter:

```markdown theme={null}
---
name: shell-patterns
description: "Background job workflows: patterns and tips"
requires_capabilities: [builtins, shell]
---

# shell-patterns

When running background jobs...
```

### Frontmatter fields

| Field                   | Type          | Required          | Description                                                                                                   |
| ----------------------- | ------------- | ----------------- | ------------------------------------------------------------------------------------------------------------- |
| `name`                  | `String`      | Yes               | Canonical lowercase slug name for the skill. For filesystem skills, this must match the containing directory. |
| `description`           | `String`      | Yes               | One-line description                                                                                          |
| `requires_capabilities` | `Vec<String>` | No (default `[]`) | Lowercase capability IDs that must be available                                                               |

The frontmatter is delimited by `---` markers. The body (everything after the closing `---`) is stored as the skill's `body` field.

## Capability gating

Skills are filtered by their `requires_capabilities` field before being shown or injected:

* A skill is included only if **all** its required capabilities are available in the current build/config.
* A skill with an empty `requires_capabilities` list is always available.

## Capability companion skills

Companion skills are the standard agent instruction-manual pattern for
nontrivial Meerkat-owned tool families.

They are:

* embedded in the crate or tool family that owns the capability
* gated with `requires_capabilities`
* discoverable through the normal skills inventory
* loadable with `load_skill`
* not automatically preloaded

Tool descriptions should stay short and schema-focused: what the tool does and
what arguments it accepts. Companion skills explain when, how, and why to use a
tool family.

Every nontrivial agent-facing built-in tool family should have human docs plus
a companion skill, or an explicit documented exemption.

## Skill identity and resolution

Every runtime skill reference resolves to:

```json theme={null}
{
  "source_uuid": "dc256086-0d2f-4f61-a307-320d4148107f",
  "skill_name": "email-extractor"
}
```

The source identity registry applies source lifecycle gates and lineage/remap rules before load. Disabled or retired sources fail resolution; configured source rotations, renames, splits, and merges require explicit lineage and per-skill remap entries where needed.

Legacy slash-delimited strings are no longer accepted by wire `skill_refs`. Some local CLI paths still accept a bare skill slug as a convenience, but API and tool surfaces should use structured keys.

## Rendering

The renderer produces two output formats:

<Tabs>
  <Tab title="Inventory section">
    Generates an `<available_skills>` XML block listing all available skills for the system prompt:

    ```xml theme={null}
    <available_skills>
      <skill id="00000000-0000-4b11-8111-000000000001/task-workflow">
        <description>How to use task_create/task_update/task_list for structured work tracking</description>
      </skill>
      <skill id="00000000-0000-4b11-8111-000000000001/shell-patterns">
        <description>Background job patterns with shell and job management tools</description>
      </skill>
    </available_skills>
    ```

    When there are more than 12 skills, collection mode is used instead:

    ```xml theme={null}
    <available_skills mode="collections">
      <collection source="00000000-0000-4b11-8111-000000000001" count="8">Embedded skills</collection>
      <collection source="dc256086-0d2f-4f61-a307-320d4148107f" count="3">Company skills</collection>

      Use the browse_skills tool to list skills in a source or search.
      Use the load_skill tool to activate a skill by SkillKey.
    </available_skills>
    ```

    This section is injected into the system prompt via the `extra_sections` parameter of `assemble_system_prompt()` in `meerkat/src/prompt_assembly.rs`.
  </Tab>

  <Tab title="Injection block">
    Wraps the skill body in XML-style tags for per-turn injection:

    ```xml theme={null}
    <skill id="00000000-0000-4b11-8111-000000000001/shell-patterns">
    # Shell Patterns

    When running background jobs...
    </skill>
    ```
  </Tab>
</Tabs>

### Size limits

`MAX_INJECTION_BYTES` is set to 32 KiB (32 \* 1024 bytes). If an injection block exceeds this limit, it is truncated with a warning log.

## Built-in skills

The following skills are embedded in component crates:

| ID                           | Name                       | Crate               | Required capabilities |
| ---------------------------- | -------------------------- | ------------------- | --------------------- |
| `hook-authoring`             | Hook Authoring             | `meerkat-hooks`     | `hooks`               |
| `shell-patterns`             | Shell Patterns             | `meerkat-tools`     | `builtins`, `shell`   |
| `task-workflow`              | Task Workflow              | `meerkat-tools`     | `builtins`            |
| `skill-discovery-workflow`   | Skill Discovery Workflow   | `meerkat-tools`     | `skills`              |
| `builtin-utilities-workflow` | Builtin Utilities Workflow | `meerkat-tools`     | `builtins`            |
| `mcp-server-setup`           | MCP Server Setup           | `meerkat-mcp`       | (none)                |
| `memory-retrieval`           | Memory Retrieval           | `meerkat-memory`    | `memory_store`        |
| `session-management`         | Session Management         | `meerkat-session`   | `session_store`       |
| `schedule-workflow`          | Schedule Workflow          | `meerkat-schedule`  | `schedule`            |
| `workgraph-workflow`         | WorkGraph Workflow         | `meerkat-workgraph` | `work_graph`          |
| `multi-agent-comms`          | Multi-Agent Comms          | `meerkat-comms`     | `comms`               |
| `mob-communication`          | Mob Communication          | `meerkat`           | `comms`               |

## Configuration reference

| Setting                      | Default          | Description                               |
| ---------------------------- | ---------------- | ----------------------------------------- |
| `skills.enabled`             | `true`           | Enable skill loading                      |
| `skills.max_injection_bytes` | `32768` (32 KiB) | Maximum size of injected skill content    |
| `skills.inventory_threshold` | `12`             | Flat listing below, collection mode above |

## Custom skills

<Tabs>
  <Tab title="Project-level">
    Create a subdirectory under `.rkat/skills/` with a `SKILL.md` file:

    ```
    .rkat/skills/
      my-deployment/
        SKILL.md
    ```

    Example `.rkat/skills/my-deployment/SKILL.md`:

    ```markdown theme={null}
    ---
    name: my-deployment
    description: Project-specific deployment procedures
    requires_capabilities: []
    ---

    # my-deployment

    1. Run `make build` to create the release binary.
    2. Deploy via `./deploy.sh production`.
    ```
  </Tab>

  <Tab title="User-level">
    Same structure under `~/.rkat/skills/`. These are available across all projects but have lower precedence than project-level skills.
  </Tab>
</Tabs>

## Discovery tools

When skills are active and builtins are enabled, these tools are registered:

| Tool                    | Description                                               |
| ----------------------- | --------------------------------------------------------- |
| `browse_skills`         | List skill collections and search by name/description     |
| `load_skill`            | Load a skill's full instructions into the conversation    |
| `skill_list_resources`  | List skill-owned resources/artifacts                      |
| `skill_read_resource`   | Read a specific skill-owned resource                      |
| `skill_invoke_function` | Invoke a skill-defined function with structured arguments |

In collection mode (when there are more than 12 skills), the system prompt shows collection summaries. The LLM can use `browse_skills` to explore collections and `load_skill` to activate specific skills.

## Invoking skills

Skills can be activated in three ways:

### 1. CLI preload convenience

The CLI `--skill` option accepts local skill slugs and materializes builtin-source `SkillKey` values for preload:

```bash theme={null}
rkat run "Extract emails" --skill email-extractor
```

Use typed keys for API and tool surfaces.

### 2. Programmatic typed `skill_refs` (per-turn, recommended)

Pass tagged `skill_refs` in API requests to resolve and inject skills for a specific turn:

```json theme={null}
{
  "method": "turn/start",
  "params": {
    "session_id": "...",
    "prompt": "Extract emails from this text",
    "skill_refs": [
      {
        "kind": "structured",
        "source_uuid": "dc256086-0d2f-4f61-a307-320d4148107f",
        "skill_name": "email-extractor"
      }
    ]
  }
}
```

Legacy `skill_references` strings are retired and rejected; use structured `skill_refs`.

### 3. Preloading at session creation

Pass `preload_skills` to inject skills into the system prompt at session creation:

```json theme={null}
{
  "method": "session/create",
  "params": {
    "prompt": "Hello!",
    "preload_skills": [
      {
        "source_uuid": "dc256086-0d2f-4f61-a307-320d4148107f",
        "skill_name": "extraction-email"
      },
      {
        "source_uuid": "dc256086-0d2f-4f61-a307-320d4148107f",
        "skill_name": "formatting-markdown"
      }
    ]
  }
}
```

See the [Python SDK](/sdks/python/reference) and [TypeScript SDK](/sdks/typescript/reference#skills) for SDK wrappers. CLI `--skill` is the preload-oriented path for runtime-local skill loading; it is not the same surface as typed per-turn `skill_refs`.

## Skill introspection

Skill introspection lets you see all skills — including shadowed ones — with their provenance information. This is useful for debugging skill resolution, understanding which source provides which skills, and inspecting shadowed skills before overriding them.

### Surfaces

| Surface  | Method                                                          | Description                                     |
| -------- | --------------------------------------------------------------- | ----------------------------------------------- |
| CLI      | `rkat skill list [--json]`                                      | List all skills with provenance                 |
| CLI      | `rkat skill inspect <skill-name> --source-uuid <uuid> [--json]` | Inspect a skill's full body                     |
| RPC      | `skills/list`                                                   | List skills with provenance                     |
| REST     | `GET /skills`                                                   | List skills                                     |
| MCP      | `meerkat_skills` tool (`action: "list"` or `"inspect"`)         | List skills or inspect one by typed `skill_key` |
| Rust SDK | `SkillRuntime::list_all_with_provenance()`                      | Programmatic access                             |
| Rust SDK | `SkillRuntime::load_from_source()`                              | Load a typed key from a specific source UUID    |

### Shadowing

When multiple sources provide the same full `SkillKey`, the first source in the runtime composite wins. Introspection shows both the active skill and the shadowed entries. The common case is that matching `skill_name` values from different sources remain separate active skills because their `source_uuid` values differ:

```json theme={null}
[
  {
    "key": {
      "source_uuid": "00000000-0000-4b11-8111-000000000001",
      "skill_name": "task-workflow"
    },
    "name": "Task Workflow",
    "scope": "builtin",
    "is_active": true
  },
  {
    "key": {
      "source_uuid": "dc256086-0d2f-4f61-a307-320d4148107f",
      "skill_name": "task-workflow"
    },
    "name": "Custom Task Workflow",
    "scope": "project",
    "is_active": true
  }
]
```

Use a full `SkillKey` (`skill_name` plus `source_uuid`) when inspecting or loading a specific source.

### Rust SDK

```rust theme={null}
use meerkat::{AgentFactory, SkillRuntime, SkillFilter};
use meerkat_core::{Config, skills::{SkillKey, SkillName, SourceUuid}};

let config = Config::load().await?;
let factory = AgentFactory::new(store_path);

// Build a SkillRuntime (requires "skills" feature)
if let Some(runtime) = factory.build_skill_runtime(&config).await? {
    // List all skills with provenance
    let entries = runtime.list_all_with_provenance(&SkillFilter::default()).await?;
    for entry in &entries {
        println!(
            "{}: active={}, source={}",
            entry.descriptor.key,
            entry.is_active,
            entry.descriptor.source_name,
        );
    }

    // Load a specific skill's body (bypassing first-wins)
    let key = SkillKey::new(
        SourceUuid::parse("dc256086-0d2f-4f61-a307-320d4148107f")?,
        SkillName::parse("task-workflow")?,
    );
    let doc = runtime.load_from_source(&key, Some("dc256086-0d2f-4f61-a307-320d4148107f")).await?;
    println!("{}", doc.body);
}
```

## Configuration

Skills are configured via `SkillsConfig` (realm-scoped at runtime, with optional user/project layering when those files are present):

```toml theme={null}
# realm config (or ~/.rkat/skills.toml and .rkat/skills.toml in layered compatibility mode)
enabled = true
max_injection_bytes = 32768    # max size of injected skill content
inventory_threshold = 12       # flat listing below, collection mode above

[[repositories]]
name = "company"
source_uuid = "55555555-5555-5555-5555-555555555555"
type = "git"
url = "https://github.com/company/skills.git"
```

When layered user/project files are used, project settings override user settings and repositories are merged by name.

## See also

* [Examples: Skills](/examples/skills)
* [Concepts overview](/concepts/overview)
* [Composability](/concepts/composability)
