# Skills

> SKILL.md package layout, discovery paths (.grok, .agents, .claude, .cursor), priority and ignore rules, slash-command surface, and config toggles for vendor skill trees.

- Repository: xai-org/grok-build
- GitHub: https://github.com/xai-org/grok-build
- Human docs: https://grok-wiki.com/public/docs/xai-org-grok-build-90205de50458
- Complete Markdown: https://grok-wiki.com/public/docs/xai-org-grok-build-90205de50458/llms-full.txt

## Source Files

- `crates/codegen/xai-grok-pager/docs/user-guide/08-skills.md`
- `crates/codegen/xai-grok-tools/src/implementations/skills`
- `crates/codegen/xai-grok-shell/skills`
- `crates/codegen/xai-grok-shell/src/extensions/mod.rs`
- `crates/codegen/xai-hooks-plugins-types/src`
- `crates/codegen/xai-grok-pager/docs/user-guide/05-configuration.md`

---

---
title: "Skills"
description: "SKILL.md package layout, discovery paths (.grok, .agents, .claude, .cursor), priority and ignore rules, slash-command surface, and config toggles for vendor skill trees."
---

Skills are reusable prompt packages: a directory with a `SKILL.md` (YAML frontmatter plus markdown body) that Grok discovers from `.grok`, `.agents`, `.claude`, and `.cursor` trees, optional `[skills].paths`, bundled/server injections, and plugins. Discovery is owned by `list_skills` / `list_skills_with_plugins` in the agent prompt layer, with parsing and walk limits in the tools skills implementation; each skill is user-invocable as a slash command (when `user-invocable` is true) and/or model-invocable via the Skill tool unless `disable-model-invocation` is set.

## What a skill is

A skill packages task-specific instructions that are too specialized for `AGENTS.md` and too long to retype each session. Grok loads skill **metadata** (name, description, flags) for listing and matching, and injects the full markdown body only when you run the slash command or the model invokes the Skill tool.

Typical layout:

```text
~/.grok/skills/
  commit/
    SKILL.md
    scripts/          # optional helpers
    references/       # optional supporting docs
  review-pr/
    SKILL.md
```

Flat `*.md` files under a `commands/` directory next to a config root (for example `.claude/commands/frontend.md`) become user-invocable slash commands whose name is the filename stem. That matches Claude Code’s legacy custom-command layout and is discovered alongside `skills/` trees.

**Limits (parser):** skill names up to 64 characters after normalization; description capped at 1024 characters; frontmatter read capped at 4096 bytes; recursive `SKILL.md` walk depth capped at 5.

## Package format: `SKILL.md`

```markdown
---
name: commit
description: >
  Create well-formatted git commits following conventional commit standards.
  Use when the user wants to commit changes or asks for /commit.
when-to-use: commit my changes, write a commit message
argument-hint: commit message
user-invocable: true
disable-model-invocation: false
allowed-tools: [run_terminal_command]
metadata:
  short-description: "Conventional git commits"
  author: team
---

# Git Commit Skill

1. Run `git diff --staged`
2. Summarize what changed and why
3. Commit with a conventional message
```

### Core frontmatter

| Field | Role |
|-------|------|
| `name` | Slash-command identity. Lowercase letters, digits, hyphens; normalized from spaces/underscores/dots. If omitted or invalid after normalize, the parent directory name is used. |
| `description` | Primary signal for automatic / Skill-tool matching. If absent, Grok derives text from the first body heading or prose paragraph. |

### Optional frontmatter

| Field | Role |
|-------|------|
| `when-to-use` | Extra trigger phrases (also accepts `when_to_use`). |
| `allowed-tools` | YAML list or comma/space-separated string (paren groups kept whole, e.g. `Bash(git diff:*)`). |
| `argument-hint` | Autocomplete hint for slash args. |
| `user-invocable` | Default `true`. Set `false` to hide from slash / user skill menus. |
| `disable-model-invocation` | Default `false`. When `true`, only explicit slash invocation runs the skill. |
| `model` / `effort` | Optional model and reasoning-effort overrides for the skill turn. |
| `paths` | Gitignore-style globs; when set, the skill stays out of the listing until a matching file is touched. |
| `license`, `compatibility`, `metadata` | Display/metadata; `metadata.author` and `metadata.short-description` are promoted for UI. |

Frontmatter keys for multi-word fields use **kebab-case**. Boolean fields accept YAML `true` or the string `"true"`.

### Body variable expansion

When a skill is expanded, the body may use:

| Token | Alias | Meaning |
|-------|-------|---------|
| `$ARGUMENTS` | — | Full args string |
| `$ARGUMENTS[N]` / `$N` | — | Nth whitespace-split arg (0-based) |
| `${SKILL_DIR}` | `${CLAUDE_SKILL_DIR}` | Directory containing `SKILL.md` |
| `${SESSION_ID}` | `${CLAUDE_SESSION_ID}` | Current session id |
| `${GROK_PLUGIN_ROOT}` | `${CLAUDE_PLUGIN_ROOT}` | Plugin root (plugin skills) |
| `${GROK_PLUGIN_DATA}` | `${CLAUDE_PLUGIN_DATA}` | Plugin data dir (plugin skills) |

If the body contains no argument tokens, arguments are appended as a traditional `**ARGUMENTS:** …` suffix. Path/session tokens expand without suppressing that suffix.

Injected skill content is wrapped in a stable envelope for the model, for example:

```text
<skill name="commit" description="…" path="…">
…body…
</skill>
```

Slash expansion can also wrap blocks in `<skill_information>` with a `<skills_referenced>` index.

## Discovery paths

At startup (and when skill roots change on disk), Grok collects config directories that may contain `skills/` and `commands/`, then walks for `SKILL.md` and flat command markdown.

### Config directory names

Always scanned:

- `.grok`
- `.agents`

Vendor trees, gated by harness compatibility (default **on**):

- `.claude` when `[compat.claude] skills = true`
- `.cursor` when `[compat.cursor] skills = true`

Codex skill cells exist in the compat registry but are **reserved/inert** — they do not enable `.codex` skill discovery.

### Where those directories are found

| Layer | Examples | `SkillScope` |
|-------|----------|--------------|
| Working tree walk | From CWD up to git root: `<dir>/.grok`, `<dir>/.agents`, optional `.claude` / `.cursor` | Local if parent is CWD; otherwise Repo under the git root |
| User home | `~/.grok`, `~/.agents`, `~/.claude`, `~/.cursor` (vendor gated) | User |
| Optional workspace-user dir | Same config names under the launcher-provided workspace user root | User-adjacent |
| `[skills].paths` | Explicit files or recursive skill dirs (`~` expanded) | Config path source |
| Server | Launcher-injected `server_skill_dirs` | Server |
| Bundled | Launcher `bundled_skill_dirs` + `~/.grok/bundled` | Bundled |
| Plugins | Skills from trusted/enabled plugins | Plugin (qualified names) |

Under each config root, Grok looks for a `skills/` subdirectory and walks nested skill packages (max depth 5). A config path that *is* a skill directory (contains `SKILL.md` at its root) is accepted as a single skill. The old Cursor-only `skills-cursor/` layout is **not** scanned.

### Priority and name collisions

Bare-name resolution prefers higher priority scopes:

**Local → Repo → User → Server → Bundled → Plugin (lowest for bare names)**

- Same skill name: higher-priority location wins.
- Plugin skills of the same bare name do **not** replace a native skill; they remain available under a **qualified** name (`plugin-name:skill-name`).
- Scope-qualified forms used in menus and the Skill tool: `local:…`, `repo:…`, `user:…`, or `plugin-name:…`.

Collision handling among same-scope files is deterministic (walk order is lexicographic; first-seen-wins on path identity).

### Gitignore vs config ignore

Skill and command discovery **does not consult `.gitignore`**. Roots under `.grok/`, `.agents/`, `.claude/`, and `.cursor/` load when present on disk even if the repo ignores them — teams often gitignore vendor config while still expecting `/frontend`-style project commands to work.

To hide a skill, use config:

```toml
[skills]
ignore = ["~/my-team-skills/wip"]   # path prefixes; skill hidden entirely
disabled = ["wip-skill"]            # name stays listed but inactive
```

| Control | Listed? | In system prompt / Skill tool? |
|---------|---------|--------------------------------|
| `ignore` | No | No |
| `disabled` | Yes (tagged disabled) | No |

`paths` and `ignore` take filesystem paths with `~` expansion. `disabled` takes **skill names**.

### Vendor default denylist

Regardless of compat toggles, skills **physically under** `/.cursor/` or `/.claude/` whose names match known vendor builtins are dropped. Examples:

- Cursor: `shell`, `canvas`, `statusline`, `create-skill`, `babysit`, …
- Claude: `pdf`, `docx`, `xlsx`, `pptx`, `skill-creator`

A user skill of the same name under `~/.grok/skills/` is **not** dropped.

### Mid-session discovery

When files are accessed during a turn, Grok can walk upward from those paths toward CWD and pick up newly visible `.grok` / `.agents` (and `.claude` if enabled) skill roots. **`.cursor` is not scanned on this dynamic path** by design; the Cursor skills toggle applies to the startup directory list only.

## Configuration

### `[skills]` in `config.toml`

```toml
[skills]
paths = ["~/my-team-skills"]
ignore = ["~/my-team-skills/wip"]
disabled = ["wip-skill"]
```

Each `paths` entry is a `SKILL.md` file or a directory walked for skills. These appear in `grok inspect` as source `config`.

### Vendor skill trees: `[compat.*]`

```toml
[compat.cursor]
skills = true     # ~/.cursor/skills/ and project .cursor/skills/

[compat.claude]
skills = true     # ~/.claude/skills/ and project .claude/skills/
```

Resolution order for each compat cell: **environment variable → `config.toml` → default (on)**.

| Env var | Effect |
|---------|--------|
| `GROK_CURSOR_SKILLS_ENABLED` | `false` / `0` stops scanning Cursor skill dirs |
| `GROK_CLAUDE_SKILLS_ENABLED` | `false` / `0` stops scanning Claude skill dirs |

`.grok` and `.agents` cannot be turned off via these cells.

Managed / remote settings may also supply `cursor_skills_enabled` and `claude_skills_enabled`; see configuration precedence on the configure and reference pages.

## Slash-command and model surfaces

### User invocation

- Type `/` in the TUI: builtins and every **user-invocable** skill appear; filter as you type.
- Run by bare name: `/commit`, `/review-pr`.
- Pass arguments after the name: `/commit fix the build`.
- Disambiguate collisions with qualified names: `/local:commit`, `/user:commit`, `/my-plugin:deploy`.

`/create-skill` (bundled) interactively scaffolds a project (`<repo>/.grok/skills/<name>/`) or user (`~/.grok/skills/<name>/`) package and reloads when files change on disk.

### Model invocation

The Skill tool takes:

```json
{ "skill": "commit", "args": "optional string" }
```

`skill` may be bare or fully qualified (`user:commit`). Skills with `disable-model-invocation: true` or `enabled: false` are excluded from model invocation while remaining slash-runnable if user-invocable and enabled.

Automatic invocation depends on prompt match against `description` and `when-to-use`. Write specific trigger language in those fields.

### Bundled skills

Grok ships platform skills (for example `create-skill`, `help`, `check-work`) extracted into the user/bundled skill tree on startup. `grok inspect` labels them `bundled`. A same-named **local or repo** skill overrides the bundled bare name; a plugin twin remains under its qualified form.

### Plugin skills

Plugins may bundle skills. After install and trust, they list with source `plugin: <name>` and resolve as `plugin-name:skill-name`. See the plugins page for marketplace install, `plugin.json`, and `GROK_PLUGIN_ROOT` / `GROK_PLUGIN_DATA`.

## Inspect and verify

```bash
grok inspect          # human summary, Skills section with source tags
grok inspect --json   # name, description, source path, userInvocable, …
```

Sources you may see: `project`, `user`, `bundled`, `config`, `server`, `plugin: <name>`. Disabled skills (config or vendor surface off) are tagged `[disabled]` in the human report. The inspect path honors the same `[skills]` and compat rules as a live session.

## Operational notes

1. **Descriptions drive auto-invoke** — name the task and slash form (`Use when … or /commit`).
2. **One workflow per skill** — prefer `deploy` and `rollback` over a combined mega-skill.
3. **Commit project skills** under `<repo>/.grok/skills/` for team sharing; keep personal packs in `~/.grok/skills/`.
4. **Do not rely on `.gitignore` to hide skills** — use `[skills].ignore` or `disabled`.
5. **Vendor noise** — turn off `compat.cursor.skills` / `compat.claude.skills` (or the env vars) if foreign trees pollute the slash menu; vendor builtins are already denylisted by path.
6. **Test with `/name`** before depending on automatic matching.
7. Skill packs are **portable files and directories** (or catalog/plugin sources), not a model-provider dependency — the same tree works with Grok-native, Claude-compat, or Cursor-compat roots depending on which roots you enable.

## Related pages

<CardGroup cols={2}>
  <Card title="Plugins" href="/plugins">
    Install skill bundles, marketplace trust, plugin roots and data dirs.
  </Card>
  <Card title="Slash commands" href="/slash-commands">
    Interactive `/` menu, builtins vs skill-provided commands.
  </Card>
  <Card title="Configure Grok" href="/configure-grok">
    config.toml precedence, feature flags, inspect dumps.
  </Card>
  <Card title="Configuration reference" href="/configuration-reference">
    Schema for `[skills]`, `[compat]`, and related keys.
  </Card>
  <Card title="Project rules and memory" href="/project-rules-and-memory">
    AGENTS.md vs skills: always-on rules versus on-demand packages.
  </Card>
  <Card title="Subagents and personas" href="/subagents">
    Child agents that can preload or constrain skill sets.
  </Card>
</CardGroup>

## Next

<CardGroup cols={2}>
  <Card title="Plugins" href="/plugins">
    Ship and consume multi-skill packages.
  </Card>
  <Card title="Slash commands" href="/slash-commands">
    How skill names show up next to pager and shell builtins.
  </Card>
</CardGroup>
