Skip to main content

Overview

Skills are reusable prompt packages that live as directories — each containing a SKILL.md file with frontmatter and supporting files. There are two workflows:
  • Author & publish — write skills in your repo, push them to Runlayer with skills push (typically in CI)
  • Consume & install — add published skills to your project or global config with skills add

Authoring skills

Directory structure

skills/
  ticket-triage/
    SKILL.md          # required — must have `name` in frontmatter
    instructions.md
    examples.txt
  code-review/
    SKILL.md
    checklist.md

SKILL.md frontmatter

---
name: Ticket Triage
description: Classify and route incoming support tickets
---

Your skill instructions go here...
FieldRequiredNotes
nameYesHuman-readable label shown in the UI
descriptionNoShort summary, max 1024 characters
The directory path (e.g. skills/ticket-triage) is the stable sync key. Renaming the directory creates a new skill; changing name in frontmatter updates the display name. Supported file types: .md, .txt, .sh, .py, .js, .ts.

Publishing

Push skills from a local directory to the Runlayer API.
runlayer skills push [PATH] --namespace <namespace> [OPTIONS]
FlagDescription
--namespace, -NRequired. Groups skills by repo (e.g. myorg/my-repo)
--host, -HRunlayer host URL. Also reads RUNLAYER_HOST env var
--secret, -sAPI key. Also reads RUNLAYER_API_KEY env var
--dry-run, -nShow what would change without making API calls
--pruneDelete remote skills whose directories no longer exist locally
PATHRoot directory to scan. Defaults to .

Examples

# Preview changes
runlayer skills push --namespace myorg/repo -n

# Push skills
runlayer skills push --namespace myorg/repo

# Push and remove deleted skills
runlayer skills push --namespace myorg/repo --prune

# Delete all skills in a namespace (run from empty dir)
cd $(mktemp -d) && runlayer skills push --namespace myorg/repo --prune

How push works

  1. CLI walks the directory tree looking for SKILL.md files
  2. Each SKILL.md must have name in its YAML frontmatter (directories without it are skipped)
  3. The directory path relative to root becomes the skill’s path — this is the stable key used to match local and remote skills
  4. For each discovered skill:
    • New path — creates the skill and uploads all files
    • Existing path — compares name, description, and file contents; updates only what changed
    • Remote-only path (with --prune) — deletes the skill from Runlayer

GitHub Actions

name: Push Skills
on:
  push:
    branches: [main]
    paths:
      - 'skills/**'

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: astral-sh/setup-uv@v4

      - run: uvx runlayer skills push --namespace ${{ github.repository }} --prune
        env:
          RUNLAYER_HOST: ${{ secrets.RUNLAYER_HOST }}
          RUNLAYER_API_KEY: ${{ secrets.RUNLAYER_API_KEY }}
Set RUNLAYER_HOST and RUNLAYER_API_KEY as repository secrets. The paths filter ensures the workflow only runs when files under skills/ change. The --prune flag removes skills from Runlayer when their directory is deleted from the repo.

Installing

Add published skills from the Runlayer API to your local project or global config.
runlayer skills add [SOURCE] [OPTIONS]
FlagDescription
sourceOptional when --all is used. Skill UUID or namespace (e.g. Org/Repo)
--allInstall all accessible skills across namespaces
--skillFilter by skill name within a namespace
--client, -cTarget editor client (default: claude_code)
--global, -gInstall globally instead of project-level
--dry-run, -nShow what would be installed without writing files
--secret, -sAPI key. Also reads RUNLAYER_API_KEY env var
--host, -HRunlayer host URL. Also reads RUNLAYER_HOST env var

Examples

# Install all skills from a namespace
runlayer skills add myorg/my-repo

# Install all accessible skills across namespaces
runlayer skills add --all

# Install a single skill by name
runlayer skills add myorg/my-repo --skill ticket-triage

# Install globally
runlayer skills add myorg/my-repo --global

# Install for Cursor instead of Claude Code
runlayer skills add myorg/my-repo --client cursor
If --all sees the same skill name in multiple namespaces, install fails with an explicit error. Re-run with a namespace SOURCE (or UUID) to disambiguate. Typical output:
Done: 12 installed, 3 skipped
Validation errors:
Pass either SOURCE or --all, not both.
Missing argument 'SOURCE'. Use SOURCE or --all.

File layout

Skills are written to two locations — a canonical directory and an editor-specific directory:
ScopeCanonicalEditor (Claude Code)Editor (Cursor)
Project.agents/skills/.claude/skills/.cursor/skills/
Global~/.agents/skills/~/.claude/skills/~/.cursor/skills/
A lockfile at .runlayer/skill-lock.yml (or ~/.runlayer/skill-lock.yml for global) tracks installed skills and versions per client.
  • Skill files are stored in the canonical directory (.agents/skills/ or ~/.agents/skills/).
  • Editor directories (.claude/skills/, .cursor/skills/, and global variants) contain symlinks to canonical skill directories.
Example (project install):
.agents/skills/ticket-triage/          # real files
.claude/skills/ticket-triage -> ../../.agents/skills/ticket-triage
.cursor/skills/ticket-triage -> ../../.agents/skills/ticket-triage
Client-scoped lifecycle:
  • runlayer skills remove --client <client> removes only that client’s symlink + lockfile entry.
  • Canonical files are kept while any other client still references the same skill.
  • Canonical files are deleted only when the last client reference is removed.
If symlink creation is blocked by filesystem policy or permissions, install fails. Run in a writable path that supports symlinks.

Managing installed skills

List

runlayer skills list [OPTIONS]
FlagDescription
--client, -cTarget editor client (default: claude_code)
--global, -gList global skills
list, update, and remove are scoped to the selected --client.

Update

Pull the latest versions of installed skills from the API.
runlayer skills update [OPTIONS]
FlagDescription
--skillUpdate a specific skill only
--client, -cTarget editor client (default: claude_code)
--global, -gUpdate global skills
--dry-run, -nShow what would change without writing files
--secret, -sAPI key. Also reads RUNLAYER_API_KEY env var
--host, -HRunlayer host URL. Also reads RUNLAYER_HOST env var

Remove

runlayer skills remove [SKILL_NAME] [OPTIONS]
FlagDescription
nameOptional when --all is used. Skill name to remove
--allRemove all installed skills in the selected scope
--yesSkip confirmation prompt for --all
--client, -cTarget editor client (default: claude_code)
--global, -gRemove from global skills

Remove examples

# Remove one skill
runlayer skills remove ticket-triage

# Remove all project skills (prompts for confirmation)
runlayer skills remove --all

# Remove all global skills without prompt
runlayer skills remove --all --global --yes
Typical output (examples):
Remove 5 skill(s) from project install? [y/N]:
Aborted.
Done: 5 removed