slikk
by kibarayhan
README.md
<p align="center">
<img src="brand/slikk-readme-header.png" alt="Slikk — skill context, optimized" width="100%">
</p>
> **slikk** — *skill*, rearranged. A sleek, minimal MCP server that resolves
> skill names to their filesystem path + metadata, without loading every
> skill's full content into context.
The name is an anagram of **skill** that lands on *sleek* — which is the whole
design goal: stay out of the way, add almost no weight, hand back a path and
nothing more.
## How slikk recovers your context budget
The token savings don't come from slikk doing something clever at runtime —
they come from **where your skills live**. Move your skills out of the default
`~/.claude/skills` into any directory you like (set `SKILLS_DIR`), and Claude
Code's native loader finds an **empty** default folder, so it injects **zero**
skill metadata into the system prompt at startup. slikk, pointed at the real
directory, then becomes the on-demand way to discover and resolve skills —
returning just a path Claude can `Read` when it actually needs one.
That's the difference from index-and-search tools: slikk doesn't depend on any
Claude Code "name-only" loading flag and keeps **no derived store** — no
embeddings, no vector database, no background indexer. It's relocate-and-resolve,
not index-and-search.
## Install & register
**1. Install deps** (needs Python 3.10+):
```bash
cd /path/to/slikk # the repo folder
pip install -r requirements.txt
```
**2. Register with Claude Code.** Set `SKILLS_DIR` to the folder you want skills
to live in, and enable the optional tools you want (`resolve_skill` is always
on). This example enables `doctor` and `migrate` — the relocate-and-resolve
workflow:
```bash
claude mcp add slikk --scope user \
-e SKILLS_DIR=~/.agents/skills \
-e ENABLE_DOCTOR=1 \
-e ENABLE_MIGRATE=1 \
-e ENABLE_LIST_SKILLS=0 \
-e ENABLE_REFRESH_INDEX=0 \
-e ENABLE_SYNC_COMMANDS=0 \
-- python3 /absolute/path/to/slikk/server.py
```
Every optional tool is listed so the full surface is visible — `1` enables a
tool, `0` (or omitting the line) disables it. This setup turns on `doctor` and
`migrate` for the initial relocate-and-resolve flow; flip the `0`s to `1` later
if you want listing, refresh, or `/`-autocomplete sync. (`resolve_skill` is
always on and has no flag.)
**`--scope user` registers slikk globally** (available in every project) — use it.
Without it, `claude mcp add` defaults to `local` (current project only), and since
relocating skills empties the machine-wide default folder, you want slikk active
everywhere, not just one project.
Start (or restart) Claude Code, then run `/mcp` — you should see **slikk**
connected with `resolve_skill`, `doctor`, and `migrate`.
> Prefer editing config by hand? The same registration as a `.mcp.json` entry is
> in [Register with Claude Code](#register-with-claude-code) below.
**3. Move your skills in:** with `SKILLS_DIR` pointed at your target, ask Claude
to plan a migration, review it, then apply. The prompt depends on **where your
skills currently are**:
- **From Claude Code's default folder** (`~/.claude/skills`) — the common case:
> "plan a slikk migration"
No source needed; migrate defaults to `~/.claude/skills`.
- **From a different folder** — a custom location, or another tool's skills dir.
Name the source explicitly:
> "plan a slikk migration with source `~/my-skills`"
After reviewing the plan, say *"apply it"*. You can run migrate more than once —
e.g. once for your default folder, then again with a different `source` to pull
in another — and each run is independently reversible. See
[`migrate`](#migrate--move-your-skills-into-skills_dir-without-breaking-references).
Other optional tools — `list_skills`, `refresh_index`, `sync_commands` — are
enabled with their own `ENABLE_*` flags; see [Configuration](#configuration).
## What it does
One real tool that matters: **`resolve_skill(name)`**
- Exact match on skill folder name first
- Falls back to fuzzy match (typos) and then substring match against
descriptions
- Returns on success: `found: true`, `id`, `skill_md_path` — minimal by design
- Returns on failure: `found: false`, `error`, `suggestions` (list of close IDs)
- Never reads/returns the full `SKILL.md` body, never executes anything
`skill_md_path` is all Claude needs — it reads that file to get the description,
allowed tools, model, argument hint, and full instructions. Returning those
fields in the tool result would just duplicate content a single `Read` away.
Five optional tools (each enabled by an env var — see [Configuration](#configuration)):
- **`list_skills()`** — cheap `{id, description}` listing for browsing (`ENABLE_LIST_SKILLS=1`)
- **`refresh_index()`** — force re-scan if you just added/edited a skill (`ENABLE_REFRESH_INDEX=1`)
- **`doctor(name=None, apply=False)`** — health-check skills for broken references (`ENABLE_DOCTOR=1`)
- **`sync_commands()`** — write `~/.claude/commands/` stubs so every skill appears in `/` autocomplete (`ENABLE_SYNC_COMMANDS=1`)
- **`migrate(source=None, apply=False, copy=False, link=False, rollback=False)`** — move (or copy/symlink) your skills **into** the configured `SKILLS_DIR`, rewriting stale references so nothing breaks (`ENABLE_MIGRATE=1`)
## `migrate` — move your skills into `SKILLS_DIR` without breaking references
This is the setup move (run it once for your main folder, or again later to pull
in others). The way you install slikk is to set `SKILLS_DIR` to the **new,
permanent home** you want your skills to live in — the same dir `resolve_skill`
reads from. But your skills aren't there yet; they're still in Claude Code's
default `~/.claude/skills` (or another folder). `migrate` pulls them into your
configured `SKILLS_DIR`, so the default dir ends up empty and Claude Code loads
nothing at startup (the whole point).
So the **destination is always `SKILLS_DIR`** (your configured target — not an
argument). The only thing you specify is the **source**: where your skills are
now. It defaults to `~/.claude/skills`, so most users don't pass it at all.
The typical move is therefore Claude Code's default `~/.claude/skills` →
a dedicated agents dir such as `~/.agents/skills` (any path works; slikk doesn't
impose a convention).
**Move is the normal setup.** Just `apply=true` — it relocates the dirs, rewrites
stale refs, and empties the source. Use it unless you have a specific reason not
to. `copy` and `link` are special cases, not alternatives to reach for by default:
| Mode | Flag | What happens | Use when |
|---|---|---|---|
| **Move** *(default, recommended)* | `apply=true` | Relocates the dirs; rewrites stale refs; **source ends up empty** | Your own skills — the standard relocate-and-resolve setup |
| Copy | `apply=true, copy=true` | Duplicates into `SKILLS_DIR`; rewrites the copies; **leaves a second copy** in the source | Only if you specifically want to keep the originals |
| Link | `apply=true, link=true` | **Symlinks** into `SKILLS_DIR`; real dir stays put; originals untouched, refs **not** rewritten | Only for skills owned by **another agent harness** you want visible without relocating — not for your own skills |
The dry-run plan lists these in `placement_options` with `recommended_mode: move`,
so the default is clear before you commit.
Moving is exactly where things break: a `SKILL.md` — **or a bundled
`scripts/*.py` / `config/*.json`** — that hardcodes `~/.claude/skills/<other>/...`
becomes a stale reference once it lives somewhere new. `migrate` couples the
move with the reference rewrite (reusing `doctor`'s stale-base detection) across
**every text file in the skill, not just SKILL.md**, and records a manifest so
the whole operation is reversible. Binary assets and undecodable files are left
untouched.
Three modes on one tool:
- **Dry-run (default, `apply=false`)** — reports every skill that would move into
`SKILLS_DIR` and every reference that would be rewritten. Touches nothing on
disk. Run this first and review it.
- **Apply (`apply=true`)** — places each skill from `source` into `SKILLS_DIR`,
rewrites the stale references in every bundled text file at the new location,
and appends a record to a `.slikk-migration.json` manifest. Reports whether the
source dir ends up empty (the payoff). Placement mode:
- default — **move** (source ends up empty)
- `copy=true` — duplicate, leaving the originals in place (a safer first pass)
- `link=true` — **symlink** each skill into `SKILLS_DIR`, leaving the real dir
where it is (see below); originals are untouched and **not** rewritten.
`copy` and `link` are mutually exclusive.
- **Rollback (`rollback=true`)** — undoes the **most recent run**: reverts the
rewrites and restores the placement (moves dirs back, deletes copies, or removes
symlinks). Run it again to step back through earlier runs.
For move/copy, references are rewritten across **every** skill, so a skill you're
*not* moving that points into one you *are* moving is fixed too.
### Multiple sources, and linking another harness's folder
`migrate` is **re-runnable**. Each call records its own run in the manifest, so
you can consolidate several folders into one `SKILLS_DIR` — run it once per
`source` — and roll them back independently, newest first.
`link=true` is for skills owned by **another agent harness**: you want them
*visible* in `SKILLS_DIR` (so slikk and Claude Code can resolve them) without
relocating or editing them. slikk symlinks each skill into `SKILLS_DIR`; the real
files stay exactly where the other harness keeps them, byte-for-byte, and their
internal references are deliberately left alone (rewriting them would edit another
tool's files). Rollback simply removes the symlinks.
A typical mixed setup:
1. "Migrate." → **move** your own skills from `~/.claude/skills` into `SKILLS_DIR`
2. "Migrate with source `~/.other-harness/skills` and link=true." → **symlink**
that harness's skills in, untouched
3. "Roll back." → removes the symlinks; "roll back" again → moves your own skills
back
> **First, set `SKILLS_DIR` to your target dir** (e.g. `~/Downloads/claude-code-skills`).
> If `SKILLS_DIR` is still `~/.claude/skills`, migrate has nothing to do and tells
> you to configure a destination first.
A natural session (skills currently in the default folder):
1. "Plan a migration." → review which skills move into `SKILLS_DIR` + the rewrites
2. "Looks right — apply it." → moves, rewrites, writes the manifest
3. (if needed) "Roll that migration back." → restores the original state
#### Migrating from a different source folder
"Plan a migration" defaults to `~/.claude/skills`. If your skills live somewhere
else — a custom location, or another tool's folder — **name the source** in the
prompt:
- "Plan a slikk migration **with source `~/my-skills`**."
- "Migrate **from `~/.other-harness/skills`** with `link=true`." (symlink, for a
folder you don't want to relocate)
The dry-run plan echoes which source it scanned (`source_note`); if it reports
zero skills, it reminds you to point `source` at the right folder.
### Updating CLAUDE.md after migrating
Once the default folder is empty, Claude Code needs to be told where skills went.
Every `migrate` result (plan and apply) includes a `claude_md_suggestion` — a
ready-to-paste block stating skills now live in your `SKILLS_DIR` and how to
resolve them (Read the path directly when the name is known; call
`resolve_skill` when it's ambiguous). slikk **does not write any file** — it only
suggests the text, and `claude_md_target` recommends the **global**
`~/.claude/CLAUDE.md` (the move is machine-wide, so the guidance belongs there).
A `claude_md_apply_hint` tells Claude Code to reconcile with any existing
skill-resolution section rather than appending a duplicate.
In practice: after migrating from Claude Code, ask "add the suggested skills note
to my global CLAUDE.md" — Claude reads the suggestion from the result, merges it
into your `~/.claude/CLAUDE.md`, and you confirm the change.
### After migrating: `next_steps`
A successful move/copy result also includes a `next_steps` list — structured
objects, each with a `title`, `detail`, and an `automatable` flag — covering:
applying the CLAUDE.md block, reconnecting so a fresh session loads the empty
default folder, optionally running `doctor` to verify nothing broke, enabling
`sync_commands` for `/` autocomplete (whitelisting the ones you use most), and —
once setup is done — optionally setting `ENABLE_MIGRATE=0` / `ENABLE_DOCTOR=0`
(left in place so they're easy to flip back on) to keep the surface minimal.
The steps marked `automatable` are config edits Claude Code can do **for you** —
when you run migrate from Claude Code, it can edit the slikk registration
(enable `sync_commands`, toggle the flags) on your confirmation, rather than you
hand-editing JSON. The catch is built into each step: any registration change
needs the slikk server to **reconnect** before it takes effect (`requires_reconnect`).
So a flow like "enable sync and run it" is really: Claude edits the registration
→ you reconnect → Claude runs `sync_commands`. Toggling those flags edits the registration and the
slikk server must reconnect to pick it up; Claude Code can make the edit, but
restart the session if the tool list doesn't update.
## `doctor` — find & fix broken references
`doctor` checks whether a skill points at things that don't exist, so you catch
breakage before invocation instead of mid-run.
Scope: `doctor()` checks **all** skills; `doctor(name="mythic")` checks **one**.
Results are grouped per skill, ordered worst-first.
What it detects, in "will break at runtime" order:
- **`unloadable`** — `SKILL.md` missing, no `---` frontmatter block, or invalid
YAML. The resolver silently drops these, so they can't be invoked at all.
- **`missing_skill_ref`** — a referenced skill that doesn't exist: in
`permissions.spawns`, in `~/.claude/skills/<other>/...` paths, or in the body.
- **`missing_local_file`** — a path the body instructs Claude to read/run that
should live in the skill's own directory but doesn't (e.g. `scripts/foo.py`,
`config/services.json`). Resolved against the skill dir **and** any
`extra_roots` (see below), so scripts kept outside `SKILLS_DIR` still count.
- **`stale_prefix`** — a skill-to-skill path reference whose base directory
doesn't match the configured `SKILLS_DIR`. `SKILLS_DIR` can be **any folder you
choose** (e.g. `~/.claude/skills`, `~/.agents/skills`, or something
entirely custom like `~/Downloads/claude-code-skills`). If a `SKILL.md`
references another skill using a different base — most commonly the legacy
`~/.claude/skills/<other>/...` convention when your skills actually live
elsewhere — that base is "stale." When the referenced skill **exists**, this is
auto-fixable: the base is rewritten to point at your `SKILLS_DIR`, preferring a
**portable home-relative form** (e.g. `~/Downloads/claude-code-skills/sentinel/**`)
when `SKILLS_DIR` is under your home directory, and falling back to an absolute
path only when it isn't. When the referenced skill does **not** exist (e.g.
`oracle`), it is reported but NOT auto-fixed — rewriting the base wouldn't help
while the target is still missing, so it stays a manual suggestion alongside the
`missing_skill_ref`. The rewrite is idempotent: a reference that already uses
the correct `SKILLS_DIR` base is never re-flagged.
- **`dangling_symlink`** — a symlink inside the skill directory whose target
doesn't resolve (e.g. `medic/scripts/utils.py → ../../oracle/scripts/utils.py`
when the `oracle` skill is missing). Suggestion-only — the doctor can't invent
the target, so it reports the broken link and what it points at.
Each body reference is classified **hard** vs **illustrative**: "hard" means it
sits in a code block or on a real read/run instruction line (these actually fail
during invocation); "illustrative" means it only appears in prose/tables (likely
a false positive for breakage) and is reported at low severity. Templated paths
(`{SERVICE}`, `${TS}`, `SPRINT_NAME`) and runtime output dirs (`memory/`,
`reports/`, ...) are ignored — those are written at runtime, not bundled.
Every issue carries a `suggestion`. A subset are `auto_fixable`:
- **`apply=False`** (default) — diagnose only, never touches files.
- **`apply=True`** — writes ONLY the safe fixes: repairing missing frontmatter,
renaming a spawn to its single unambiguous existing match (e.g.
`ticket-intake` → `ticket-intake-pipeline`), and rewriting a stale
`~/.claude/skills/` prefix to match `SKILLS_DIR` (portable `~/...` form when
possible) **when the target skill exists**. Risky changes (deleting refs, creating missing skills/files,
repointing/rewriting paths to skills that don't exist like `oracle`, fixing
broken YAML structure) are never auto-applied — they stay as suggestions.
Re-running with `apply=True` is idempotent.
### Triggering the doctor in Claude Code
`doctor` is an MCP tool, so you trigger it with natural language — Claude picks
the tool and fills in `name` / `apply`. The recommended flow is **diagnose
first, review, then apply** (apply only writes the safe fixes).
**Diagnose (no changes):**
- "Run the slikk doctor and show me all the broken references."
- "Run doctor on the `mythic` skill." (one skill instead of all)
**Apply fixes (after reviewing):**
- "Apply the safe fixes for `mythic`."
- "Run doctor across all skills and apply the auto-fixes."
If Claude doesn't reach for the tool, name it directly: "use the
**slikk** doctor tool." (The tool only triggers if the slikk
MCP is registered in that Claude Code instance.)
### Running the doctor directly (no MCP needed)
The same function runs straight from a terminal — `server.doctor(name=None, apply=False)`:
```bash
SKILLS_DIR=... python3 -c "import server, json; print(json.dumps(server.doctor(), indent=2))"
```
Pass `name='<id>'` for one skill and `apply=True` to write the safe fixes. You
can also call the logic module directly (`doctor.run_doctor`, needs only
`pyyaml`, no `mcp`) — note it does **not** expand `~`, so give it an absolute path.
### Resolving scripts kept outside `SKILLS_DIR` (`extra_roots`)
Some skills keep their scripts outside the skills dir — e.g. grimoire runs
`~/.claude/grimoire/scripts/db.py`. To stop those from being reported as
`missing_local_file`, the doctor resolves bundled-file references against the
skill dir **plus** a list of extra roots. A file counts as found if it exists at
`<root>/<skill>/<rel>` or `<root>/<rel>`.
Source order: the `extra_roots` argument > the `CLAUDE_EXTRA_ROOTS` env var
(`os.pathsep`-separated) > the default `~/.claude`. So out of the box, anything
under `~/.claude/<skill>/...` already resolves with no extra configuration.
```bash
# add more roots for this run
SKILLS_DIR=... python3 -c "import server, json; print(json.dumps(server.doctor(extra_roots=['~/.claude', '~/git_tree']), indent=2))"
# or via env
CLAUDE_EXTRA_ROOTS=~/.claude:~/git_tree SKILLS_DIR=... python3 -c "import server, json; print(json.dumps(server.doctor(), indent=2))"
```
> Note: `permissions` is **not** part of the standard Claude Code skill format
> and is not enforced by Claude Code, so permission-path findings are flagged as
> intent-only. The references that genuinely break invocation are the ones in the
> skill **body**.
## `sync_commands` — keep `/` autocomplete in sync
When `ENABLE_SYNC_COMMANDS=1` is set, the `sync_commands` tool writes one
`~/.claude/commands/<id>.md` stub per skill so every skill appears in Claude
Code's `/` autocomplete. It force-refreshes the index before writing, deletes
stubs for skills that no longer exist, and skips writes when content is
unchanged (idempotent).
Because a `/skillname` is an exact, known id, each stub instructs Claude to
**`Read` that skill's `SKILL.md` directly** and follow it — no `resolve_skill`
round-trip on the hot path. `resolve_skill` is named only as the fallback for
when the file is missing or has moved.
### Filtering
Whitelist and blacklist are mutually exclusive — set one or neither, not both.
If both are set the tool returns an error immediately and touches nothing.
| Env var | Effect |
|---|---|
| _(neither set)_ | sync all skills |
| `SYNC_COMMANDS_WHITELIST=id1,id2,...` | sync **only** the listed skill IDs |
| `SYNC_COMMANDS_BLACKLIST=id1,id2,...` | sync everything **except** the listed IDs |
Use whitelist when you want a small explicit opt-in set; use blacklist when you
want to exclude a handful of skills from an otherwise full sync.
### Response
```json
{
"synced": 42,
"added": 3,
"updated": 0,
"deleted": 1,
"unchanged": 38,
"deleted_ids": ["old-skill"],
"commands_dir": "/Users/you/.claude/commands"
}
```
## Configuration
All configuration is via environment variables set in your MCP config.
### Core
| Env var | Default | Description |
|---|---|---|
| `SKILLS_DIR` | _(required — no default)_ | Directory to scan for skill folders — set this to the **new home** you want skills to live in (e.g. `~/.agents/skills` or `~/Downloads/claude-code-skills`); any path works. The server refuses to start if it is unset, and it should **not** be `~/.claude/skills` (the folder Claude Code auto-loads and the migration source default) |
> **Windows:** Claude Code runs under **WSL**, so it's a Linux environment —
> use the WSL paths and run slikk inside WSL like any Linux setup. Native
> (non-WSL) Windows Python is not supported: the path handling assumes
> POSIX-style `/` paths.
### Optional tools (disabled by default)
| Env var | Enables |
|---|---|
| `ENABLE_LIST_SKILLS=1` | `list_skills()` tool |
| `ENABLE_REFRESH_INDEX=1` | `refresh_index()` tool |
| `ENABLE_DOCTOR=1` | `doctor()` tool |
| `ENABLE_SYNC_COMMANDS=1` | `sync_commands()` tool |
| `ENABLE_MIGRATE=1` | `migrate()` tool |
### `sync_commands` options
| Env var | Default | Description |
|---|---|---|
| `COMMANDS_DIR` | `~/.claude/commands` | Where to write slash-command stubs |
| `SYNC_COMMANDS_WHITELIST` | _(none)_ | Comma-separated skill IDs to sync (exclusive with blacklist) |
| `SYNC_COMMANDS_BLACKLIST` | _(none)_ | Comma-separated skill IDs to exclude (exclusive with whitelist) |
### `doctor` options
| Env var | Default | Description |
|---|---|---|
| `CLAUDE_EXTRA_ROOTS` | `~/.claude` | Colon-separated extra roots for resolving bundled-file references |
## What it deliberately does NOT do
- **No execution.** Claude Code already has bash/file access — resolution
and execution are kept separate so whatever confirmation gates already
exist in your skills (script-level checks, or Claude pausing to ask you)
are never silently bypassed by a new layer.
- **No auto-chaining.** If a skill needs another, that's expressed in its
**body** ("run X first", "read Y") and Claude resolves it at runtime —
calling `resolve_skill` as needed. The server never walks a dependency
graph, and it does not read structured dependency metadata (Claude Code
ignores such keys anyway).
- **No safety classification.** The server doesn't invent a "safe/unsafe"
flag. Use Claude Code's real `disable-model-invocation` / `user-invocable`
frontmatter if you want to control how a skill is invoked.
## Verify the install
Install is covered in [Install & register](#install--register). To smoke-test the
server outside Claude Code, run it directly:
```bash
# defaults to ~/.claude/skills; set SKILLS_DIR to override
SKILLS_DIR=~/.agents/skills python3 -c "
import server
print(server.list_skills()[:3])
"
```
## Register with Claude Code
The quickest way is the CLI (see [Install & register](#install--register)):
```bash
claude mcp add slikk --scope user \
-e SKILLS_DIR=~/.agents/skills \
-e ENABLE_DOCTOR=1 \
-e ENABLE_MIGRATE=1 \
-e ENABLE_LIST_SKILLS=0 \
-e ENABLE_REFRESH_INDEX=0 \
-e ENABLE_SYNC_COMMANDS=0 \
-- python3 /absolute/path/to/slikk/server.py
```
All optional flags are shown explicitly (`1` on, `0` off) so the full surface is
visible and easy to toggle. `--scope user` makes slikk **global** (every project);
the default is `local` (current project only). Or add it to your MCP config by
hand — for the global equivalent, put it in `~/.claude.json` rather than a project
`.mcp.json`:
```json
{
"mcpServers": {
"slikk": {
"command": "python3",
"args": ["/absolute/path/to/slikk/server.py"],
"env": {
"SKILLS_DIR": "~/.agents/skills",
"ENABLE_DOCTOR": "1",
"ENABLE_MIGRATE": "1",
"ENABLE_LIST_SKILLS": "0",
"ENABLE_REFRESH_INDEX": "0",
"ENABLE_SYNC_COMMANDS": "0",
"SYNC_COMMANDS_WHITELIST": "",
"SYNC_COMMANDS_BLACKLIST": ""
}
}
}
}
```
`SKILLS_DIR` defaults to `~/.claude/skills` if omitted. Point it at wherever
you keep your skills — any path works, and the `doctor` tool adapts its
reference-checking to whatever base you configure. Each optional tool
(`list_skills`, `refresh_index`, `doctor`, `sync_commands`, `migrate`) is off
until you set its `ENABLE_*` flag — see [Configuration](#configuration) for the
full list.
`SYNC_COMMANDS_WHITELIST` / `SYNC_COMMANDS_BLACKLIST` are shown empty as
placeholders: leaving both empty is fine — even with `ENABLE_SYNC_COMMANDS=1` it
just means "sync all skills." Fill in **one** (comma-separated IDs) to surface
only those (whitelist) or hide those (blacklist); setting **both** to non-empty
is an error.
## Frontmatter fields the resolver surfaces
The resolver only reads frontmatter keys that Claude Code itself recognizes.
All are optional; a skill needs only `name` + `description` to be useful.
```yaml
---
name: my-skill
description: When to use this skill (this is what Claude matches on).
allowed-tools: Read, Grep, Bash # optional: scope tool access
user-invocable: true # optional: who may invoke
argument-hint: <ticket-id> # optional: expected input
model: claude-sonnet-4-6 # optional: for subagent execution
---
```
> Older versions of this resolver invented extra keys (`depends_on`,
> `gated_by`, `calls_next`, `permissions`, `executable`, `entrypoint`,
> `requires_confirmation`). Claude Code does **not** read those, so they've
> been dropped. Express cross-skill dependencies in the skill **body** instead
> — Claude follows those instructions and resolves other skills at runtime.
## Notes
- The index is cached for 30 seconds (`cache_ttl_seconds` in `server.py`) —
call `refresh_index()` if you need it to pick up changes immediately,
e.g. right after creating a new skill with `writing-skills` or
`create-playbook`.
- Skill folders with malformed/missing frontmatter are excluded from
`list_skills()` and return a clear parse error from `resolve_skill()`
rather than crashing the server.
- Folder names with colons (e.g. `ape:create-jira`) work fine — tested.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues