Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

skillc is the development kit for Agent Skills — the open format for extending AI agent capabilities with specialized knowledge and workflows.

At a Glance

                        SKILL.md (source)
                              │
              ┌───────────────┴───────────────┐
              │                               │
              ▼                               ▼
   ┌─────────────────────┐         ┌─────────────────────┐
   │  skillc (optional)  │         │      git push       │
   │                     │         │         ↓           │
   │  lint · build       │         │  npx skills add     │
   │  stats · search     │         │         ↓           │
   │         ↓           │         │  Claude · Cursor    │
   │  local testing      │         │  Codex · Copilot    │
   └─────────────────────┘         └─────────────────────┘

skillc helps authors validate and test skills locally. Consumers just run npx skills add — no compilation needed.

Who is this for?

AudienceWhat skillc provides
Skill authorsCreate, validate, and test skills before publishing
Power usersTrack how agents use skills locally

Core Commands

CommandWhat it does
initCreate a new skill or project structure
lintValidate structure, frontmatter, and links
buildCompile for local testing and deploy to agents
listShow all managed skills
outlineList sections across all files
showRetrieve specific section content
openRead a file
searchFull-text search with FTS5
sourcesTree view of source files
statsUsage analytics
syncMerge local logs to global store
mcpStart MCP server for agent integration

Common Options

CommandOptionDescription
outline--level <n>Filter to headings ≤ level n (1-6)
show--max-linesTruncate output to first n lines
open--max-linesTruncate output to first n lines
stats--group-byAggregate by: sections, files, commands, projects, errors, search

Two Interfaces

InterfaceForExample
CLI (skc)Humans, scripts, CIskc lint my-skill
MCPAI agents directlyskc_lint tool

Both expose the same functionality. MCP provides structured output for agent integration.

Key Concepts

Source vs. Compiled

SourceCompiled
WhatYour SKILL.md with full contentStub directing agents to gateway commands
ForPublishing to GitHubLocal development/testing
Publish?YesNo

Always push source, never compiled output.

Skill Resolution

When you run skc <command> my-skill, skillc searches:

  1. Project: .skillc/skills/my-skill/ (from current directory upward)
  2. Global: ~/.skillc/skills/my-skill/

Project-local skills take precedence.

Project Detection

skillc walks upward from your current directory looking for .skillc/:

~/projects/myapp/src/          ← you are here
~/projects/myapp/.skillc/      ← project root found

Run commands from anywhere within a project.

Workflow Guides

Supported Agents

skillc deploys to these agent directories:

TargetDirectory
claude~/.claude/skills/
codex~/.codex/skills/
copilot~/.github/skills/
cursor~/.cursor/skills/
gemini~/.gemini/skills/
kiro~/.kiro/skills/
opencode~/.opencode/skills/
trae~/.trae/skills/

Use skc build my-skill --target cursor to deploy to a specific agent.

Authoring Skills

This guide covers creating and structuring skills with skillc.

Initialize a project

Before creating skills, initialize skillc in your project:

skc init

This creates .skillc/skills/ where your skill sources live.

Create a new skill

skc init my-skill

This creates .skillc/skills/my-skill/SKILL.md with minimal frontmatter:

---
name: my-skill
description: A brief description of what this skill does
---

# my-skill

Your skill content here...

Skill structure

A skill is a directory containing at least SKILL.md. You can add additional markdown files for organization:

.skillc/skills/my-skill/
├── SKILL.md              # Required: main entry point
├── examples/
│   └── usage.md          # Optional: examples
├── reference/
│   └── api.md            # Optional: reference docs
└── troubleshooting.md    # Optional: troubleshooting

Frontmatter

Every SKILL.md must have YAML frontmatter with at least:

---
name: my-skill
description: A brief description
---

Optional fields:

---
name: my-skill
description: A brief description
version: 1.0.0
author: Your Name
tags: [rust, development]
---

Writing effective content

Keep it scannable

Agents read skills to find relevant information quickly. Use:

  • Clear headings (H2 for major sections, H3 for subsections)
  • Bullet points for lists
  • Code blocks for examples

Use progressive disclosure

Put the most important information first. Detailed reference material can go in separate files.

Include activation triggers

Tell agents when to use this skill:

## When to use this skill

Use this skill when:

- Working with Rust projects
- Debugging lifetime errors
- Optimizing Rust performance

Global skills

To create a skill that’s available across all projects:

skc init my-skill --global

This creates the skill in ~/.skillc/skills/my-skill/.

Next steps

Validating Skills

This guide covers using skc lint to validate skill quality before publishing.

Basic usage

skc lint my-skill

This checks your skill against quality rules and reports any issues.

What lint checks

See RFC-0008:C-REGISTRY for the full rule specification.

Meta rules (SKL0xx)

  • SKL001: Skip compiled skills (internal)

Frontmatter rules (SKL1xx)

  • SKL100: Frontmatter must be valid YAML
  • SKL101: name field required
  • SKL102: name format (lowercase, hyphens, digits only)
  • SKL103: name length (1-64 chars)
  • SKL104: name should match directory name
  • SKL105: description field required
  • SKL106: description must be non-empty
  • SKL107: description length (10-200 chars recommended)
  • SKL108: Include activation triggers
  • SKL109: Only known frontmatter fields allowed

Structure rules (SKL2xx)

  • SKL201: SKILL.md size warning (>500 lines)
  • SKL202: Missing H1 heading
  • SKL203: H1 should match skill name
  • SKL204: First heading should be H1
  • SKL205: No skipped heading levels
  • SKL301: Internal links must resolve
  • SKL302: Anchor links must resolve
  • SKL303: Links must not escape skill root

File rules (SKL4xx)

  • SKL401: No orphan files (files not linked from SKILL.md)

Output formats

Text (default)

skc lint my-skill
my-skill: 2 errors, 1 warning

SKILL.md:1:1 error[SKL103]: missing required frontmatter field: description
SKILL.md:5:1 warning[SKL107]: skill should include activation triggers
examples/usage.md:12:1 error[SKL301]: broken link: ./nonexistent.md

JSON

skc lint my-skill --format json
{
  "skill": "my-skill",
  "diagnostics": [
    {
      "rule": "SKL103",
      "severity": "error",
      "file": "SKILL.md",
      "line": 1,
      "message": "missing required frontmatter field: description"
    }
  ]
}

Fixing issues

Missing frontmatter fields

Add required fields to your SKILL.md:

---
name: my-skill
description: Helps with X by providing Y
---

Missing activation triggers

Add a section explaining when agents should use the skill:

## When to use this skill

Use this skill when:

- Condition A
- Condition B

Or use frontmatter:

---
name: my-skill
description: ...
activate when: working with Rust projects
---

Check that all internal links point to existing files:

<!-- Bad -->

[See examples](./examples.md) <!-- file doesn't exist -->

<!-- Good -->

[See examples](./examples/usage.md) <!-- file exists -->

Lint all skills

To lint all skills in your project:

skc lint

Exit codes

  • 0 — No errors (warnings are OK)
  • 1 — One or more errors found

Use exit codes in CI to block publishing of invalid skills.

Next steps

Testing Skills Locally

This guide covers testing skills with gateway commands before publishing.

Why test locally?

Before publishing, you want to verify:

  1. Agents can navigate your skill’s structure
  2. Content is accessible via gateway commands
  3. Search returns relevant results

Build for local testing

skc build my-skill

This compiles your skill and deploys it to the agent directory (e.g., ~/.claude/skills/).

Note: The compiled output is a stub that references gateway commands. This is for local testing only — you publish the source, not the compiled output.

Gateway commands

View structure

skc outline my-skill

Shows all sections in your skill:

# my-skill
## Installation
## Usage
### Basic usage
### Advanced options
## Troubleshooting

Read a section

skc show my-skill --section "Installation"

Displays the content of that section. This simulates how an agent would request specific content.

Open a file

skc open my-skill examples/usage.md

Opens a specific file from the skill. Use this for non-markdown files or when you need the entire file.

List source files

skc sources my-skill

Lists all files in the skill as a tree:

my-skill/
├── SKILL.md
├── examples/
│   └── usage.md
└── reference/
    └── api.md

Use --format json for machine-readable output:

skc sources my-skill --format json

Search content

skc search my-skill "error handling"

Full-text search across all skill content:

examples/usage.md:45: ...proper error handling is crucial...
reference/api.md:112: ...the error handling middleware...

Test with an agent

After building, start a conversation with an agent that has access to ~/.claude/skills/ (or your target agent directory).

Ask the agent to use your skill and observe:

  1. Does it find the skill?
  2. Does it navigate to relevant sections?
  3. Does it understand the content?

Deploy to multiple agents

Test with different agents:

skc build my-skill --target claude,cursor,codex

Iterate

  1. Edit source files in .skillc/skills/my-skill/
  2. Rebuild: skc build my-skill
  3. Test with gateway commands or agent
  4. Repeat

No need to restart agents — they read fresh content on each request.

Next steps

Publishing Skills

This guide covers publishing skills for distribution via the skills ecosystem.

What you publish

You publish source files, not compiled output.

Published (source):           NOT published (compiled):
├── skills/                   ├── SKILL.md (stub)
│   └── my-skill/             └── .skillc-meta/
│       ├── SKILL.md              ├── manifest.json
│       └── examples/             └── index.tantivy/

The compilation step (skc build) is for local development and testing. Consumers download source directly and don’t need skillc.

Repository structure

The skills tool expects this structure:

your-repo/
└── skills/
    └── my-skill/
        ├── SKILL.md
        └── ...

Publishing workflow

Option 1: Dedicated skills repository

Make .skillc/ its own git repository:

cd .skillc
git init
git add skills/
git commit -m "Initial skill"
git remote add origin git@github.com:you/my-skills.git
git push -u origin main

The repo root becomes the published structure:

my-skills/           # repo root
└── skills/
    └── my-skill/

Option 2: Monorepo with skills

If your project already has a skills/ directory, you can author directly there:

# Initialize skillc to use skills/ instead of .skillc/skills/
# (configure via .skillc/config.toml if needed)

Or maintain both and sync:

# Your project structure
project/
├── .skillc/
│   └── skills/my-skill/    # author here
├── skills/
│   └── my-skill/           # publish here (copy or symlink)
└── src/

Before publishing

Run through this checklist:

  1. Lint passes: skc lint my-skill reports no errors
  2. Content complete: All sections filled in
  3. Examples work: Code examples are tested
  4. Links valid: No broken internal links

Consumer experience

After you publish, consumers install with:

npx skills add github:you/my-skills

This downloads skills/my-skill/ to their agent directory. They don’t need skillc — the agent reads source files directly.

Versioning

Use git tags or branches for versioning:

git tag v1.0.0
git push --tags

Consumers can install specific versions:

npx skills add github:you/my-skills@v1.0.0

Multiple skills

One repository can contain multiple skills:

my-skills/
└── skills/
    ├── rust/
    │   └── SKILL.md
    ├── cuda/
    │   └── SKILL.md
    └── typst/
        └── SKILL.md

Consumers choose which to install:

npx skills add github:you/my-skills --skill rust

Next steps

Usage Analytics

This guide covers tracking how agents use your skills locally.

Why analytics?

Understanding usage helps you:

  • Identify which sections agents read most
  • Find content that’s never accessed (candidates for removal)
  • Optimize skill structure based on real patterns

How it works

When you use gateway commands (skc show, skc open, skc search), skillc logs each access:

  • Timestamp
  • Command used
  • Skill and section accessed
  • Working directory context

Logs are stored locally in .skillc-meta/logs.db within each skill’s runtime directory.

View statistics

skc stats my-skill

Example output:

my-skill usage statistics (last 30 days)

Total accesses: 47
Unique sections: 12

Top sections:
  1. Installation (15 accesses)
  2. Troubleshooting (12 accesses)
  3. API Reference (8 accesses)

Unused sections:
  - Contributing
  - Changelog

Access by command:
  show: 35
  search: 8
  open: 4

Filter by time

skc stats my-skill --since 7d    # Last 7 days
skc stats my-skill --since 30d   # Last 30 days
skc stats my-skill --since 2024-01-01

JSON output

For programmatic analysis:

skc stats my-skill --format json
{
  "skill": "my-skill",
  "period": {
    "start": "2024-01-01T00:00:00Z",
    "end": "2024-01-30T23:59:59Z"
  },
  "total_accesses": 47,
  "sections": [
    { "name": "Installation", "count": 15 },
    { "name": "Troubleshooting", "count": 12 }
  ]
}

Sync local logs

If you work across multiple machines or projects, you may have fragmented logs. Sync them to a central location:

skc sync

This moves local fallback logs to the primary runtime location.

Privacy

  • All analytics are local only — nothing is sent externally
  • Logs contain access patterns, not content
  • You control what to track and what to delete

Acting on analytics

High-traffic sections

If a section gets many hits:

  • Ensure it’s well-written and complete
  • Consider expanding with more detail
  • Keep it near the top of your skill

Unused sections

If a section is never accessed:

  • Is the heading discoverable? (Check skc outline)
  • Is the content useful? Consider removing it
  • Should it be merged with another section?

Search patterns

If certain queries appear often:

  • Add a section that directly answers them
  • Improve headings to match search terms

Next steps

  • Use analytics to iterate on your skill structure
  • Publish updates based on usage patterns

RFC-0000: skillc — A Development Kit for Skill Writers

Version: 0.1.0 | Status: normative | Phase: stable


1. Summary

[RFC-0000:C-VISION] Vision (Informative)

skillc is a development kit for Agent Skills — the open format for extending AI agent capabilities with specialized knowledge and workflows.

Agent Skills define what a skill is: a folder with a SKILL.md file containing metadata and instructions. skillc provides the how: tooling to author, validate, optimize, and instrument skills throughout their lifecycle.

Where the Agent Skills specification ends, skillc begins.

Since: v0.1.0


2. Motivation

[RFC-0000:C-PROBLEM] Problem Statement (Informative)

The Agent Skills format solves the consumption problem: a simple, portable way for agents to discover and load specialized knowledge. But skill authoring remains ad-hoc.

Today, skill writers:

  • Write skills blind — No data on which sections agents actually read
  • Guess at structure — No tooling to validate or optimize content organization
  • Can’t iterate effectively — No feedback loop between publishing and agent usage
  • Manage skills manually — No registry, no build pipeline, no version tracking

The Agent Skills spec recommends keeping SKILL.md under 500 lines and using progressive disclosure, but provides no tooling to enforce or automate these practices.

Skill writers need a development kit.

Since: v0.1.0


3. Scope

[RFC-0000:C-SCOPE] Scope (Informative)

skillc complements the Agent Skills ecosystem by providing:

  • Scaffolding — Initialize properly-structured skill directories
  • Validation — Check skills conform to the spec (extends skills-ref validate)
  • Compilation — Generate optimized stubs that enforce size limits and progressive disclosure
  • Instrumentation — Trace agent access to skill content (sections read, files opened)
  • Analytics — Aggregate usage data to identify high-value vs. ignored content
  • Registry — Track skills across source and runtime locations

skillc is a local CLI tool. It works with the existing Agent Skills format — no proprietary extensions, no lock-in.

Since: v0.1.0

[RFC-0000:C-NONGOALS] Non-Goals (Informative)

skillc does not:

  • Define a new skill format — We build on Agent Skills, not compete with it
  • Replace skills-ref — We extend validation, not duplicate it
  • Host or distribute skills — Publishing is out of scope for v0
  • Modify agent behavior — Agents consume skills normally; instrumentation is transparent
  • Require infrastructure — No servers, no cloud, no accounts

Since: v0.1.0


4. Principles

[RFC-0000:C-PRINCIPLES] Design Principles (Informative)

1. Extend, don’t reinvent Agent Skills is an open standard with broad adoption. skillc adds tooling; it doesn’t fork the format.

2. Observability unlocks iteration You can’t improve what you can’t measure. Instrumented access is the foundation for data-driven skill refinement.

3. Progressive disclosure by default The spec recommends it; skillc enforces it. Compiled stubs expose structure without dumping content.

4. Local-first, zero infrastructure skillc runs on your machine. Skills are files. No accounts, no network, no vendor lock-in.

5. Minimal viable tooling Start with the smallest useful toolkit. Add capabilities only when clearly needed.

Since: v0.1.0


5. Compatibility Guarantees

[RFC-0000:C-COMPAT-FORMAT] Format Compatibility (Normative)

skillc MUST accept any directory that conforms to the Agent Skills specification.

skillc MUST NOT require proprietary extensions, additional metadata fields, or non-standard file structures to function.

Since: v0.1.0

[RFC-0000:C-COMPAT-OFFLINE] Offline Operation (Normative)

Core skillc functionality — authoring, validation, compilation, instrumentation, and analytics — MUST operate without network access.

Optional features MAY require network access, but MUST be explicitly opt-in and MUST NOT be required for basic skill development workflows.

skillc MUST NOT require accounts or authentication for core functionality.

Since: v0.1.0

[RFC-0000:C-COMPAT-PORTABLE] Portability (Normative)

Skill source directories managed by skillc MUST remain valid Agent Skills per the specification.

Compiled stubs MAY instruct agents to use skillc gateway commands for content access. Instrumented tracing is only available when agents access content through skillc.

skillc MAY provide options to include source references or mappings in compiled output, enabling fallback access when skillc is unavailable. The mechanism for source mapping is implementation-defined.

Since: v0.1.0


Changelog

v0.1.0 (2026-01-30)

Initial release

RFC-0001: Skill Compilation

Version: 0.2.1 | Status: normative | Phase: test


1. Summary

[RFC-0001:C-OVERVIEW] Overview (Informative)

Skill compilation transforms a skill source directory into a runtime-ready artifact.

The compiler reads an Agent Skills directory, extracts metadata and structure, and produces:

  1. A stub — a compact SKILL.md that instructs agents to use gateway commands
  2. A manifest — metadata for build tracking and change detection

Compilation enforces progressive disclosure: the stub exposes structure without content, directing agents to retrieve sections on-demand through skillc.

Since: v0.1.0


2. Specification

[RFC-0001:C-INPUT] Compilation Input (Normative)

The compiler MUST accept any directory that is a valid Agent Skill per RFC-0000:C-COMPAT-FORMAT.

The compiler MUST read the following from the source directory:

  • SKILL.md — extract name and description from YAML frontmatter
  • All .md files — extract heading structure for outline generation
  • Directory structure — enumerate files for source listing

The compiler MUST fail with a clear error if:

  • SKILL.md is missing
  • SKILL.md lacks required name or description frontmatter fields

Since: v0.1.0

[RFC-0001:C-OUTPUT] Compilation Output (Normative)

The compiler MUST produce the following outputs in the runtime directory:

  1. SKILL.md — the compiled stub (see RFC-0001:C-STUB)
  2. .skillc/manifest.json — build metadata (see RFC-0001:C-MANIFEST)

The compiler MUST create the runtime directory if it does not exist.

The compiler MUST NOT copy source content to the runtime directory. Only the stub, manifest, and log directories are permitted.

Since: v0.1.0

[RFC-0001:C-STUB] Stub Format (Normative)

The compiled stub MUST be a valid Agent Skills SKILL.md file.

The stub MUST include:

  • YAML frontmatter with name and description (preserved from source)
  • A notice that agents should use gateway commands, not read sources directly
  • A statement that agents SHOULD prefer MCP tools (skc_outline, skc_show, skc_search, etc.) if the skillc MCP server is available, for better performance and structured output
  • Gateway command examples as CLI fallback: skc outline, skc show --section, skc open, skc sources
  • A section listing per RFC-0001:C-SECTIONS

The stub MUST NOT include:

  • Source content beyond headings
  • Source file listings (use skc sources instead)
  • Implementation details or internal paths
  • References to absolute filesystem paths

The stub format is designed to fit within agent context limits while providing enough structure for agents to navigate the skill.*

Since: v0.1.0

[RFC-0001:C-MANIFEST] Manifest Format (Normative)

The manifest MUST be a JSON file located at .skillc/manifest.json in the runtime directory.

The manifest MUST include:

  • skill — the skill name
  • version — manifest schema version (integer)
  • built_at — ISO 8601 timestamp of compilation
  • source_hash — content hash for change detection

The source hash MUST be computed as SHA-256 over the sorted list of (relative_path, file_hash) pairs from the source directory. This enables the compiler to detect when sources have changed since the last build.

The manifest MAY include additional fields for future extensibility.

Since: v0.1.0

[RFC-0001:C-ERRORS] Error Handling (Normative)

All compilation errors MUST exit with status 1 and print an error message to stderr.

Error codes: See RFC-0005:C-CODES for canonical error messages. This RFC uses:

ConditionError Code
Skill resolution failedE001 or E010
Missing frontmatter fieldE011
Path escapes skill rootE012
Invalid CLI optionE100

Usage:

  • E001/E010: Skill resolution failed per RFC-0007:C-RESOLUTION. See RFC-0005:C-CODES for when to use each.
  • E011: SKILL.md exists but lacks required name or description frontmatter
  • E012: Symlink or path would escape the skill root directory
  • E100: Unknown flag, missing required value, or other CLI parsing failure

Since: v0.1.0

[RFC-0001:C-SECTIONS] Section Listing Rules (Normative)

The stub section listing (“Top Sections”) MUST be generated according to these rules:

SKILL.md Sections

For the main SKILL.md file, the compiler MUST:

  • Include all H1 headings at indent level 0
  • Include H2 headings at indent level 1 (as children of the preceding H1)
  • Exclude H3 and deeper headings (too detailed for stub)
  • Limit to 15 entries; if more exist, append “… (N more)” indicator

The first H1 is NOT treated specially — it is included like any other H1.

Other Markdown Files

For all other .md files in the skill directory:

  • Group all entries under a “References (query by title only)” label at indent level 0
  • The hint “(query by title only)” clarifies that descriptions are for context only
  • Use the first H1 heading from each file at indent level 1
  • If a file has no H1 heading, use the relative file path as the label
  • If the file has frontmatter with a description field, append it inline after an em-dash: - Title — description
  • Description MUST be truncated to 120 characters with if longer
  • Limit to 15 entries; if more exist, append “… (N more)” indicator
  • Files are listed in alphabetical order by path

The “References” section is only included if there are other .md files.

Reference File Frontmatter

Reference files MAY contain optional YAML frontmatter:

---
description: "Brief description of this reference document"
---

The description field:

  • Is optional (no warning if absent)
  • Should be concise (≤120 characters recommended)
  • Is displayed inline in the stub after the title
  • Is NOT part of the queryable section name

File Ordering

Files MUST be processed in this order:

  1. SKILL.md first (main document)
  2. Other .md files in alphabetical order by path

Example Output

## Top Sections

- Rust CLI
  - Default Flow
  - Decision Tree
- Advanced Topics
  - Performance
- References (query by title only)
  - Clap Patterns — Advanced argument parsing examples
  - Error Handling — anyhow vs thiserror patterns
  - TUI Guide

In this example:

  • “Rust CLI” and “Advanced Topics” are H1s from SKILL.md
  • “Default Flow”, “Decision Tree”, “Performance” are H2s from SKILL.md
  • “References (query by title only)” is the fixed grouping label with hint
  • “Clap Patterns” and “Error Handling” have descriptions from their frontmatter
  • “TUI Guide” has no description (frontmatter absent or no description field)
  • When querying, use skc show --section "Clap Patterns" (not the full line with description)

Since: v0.2.0

Since: v0.2.0


3. Constraints

[RFC-0001:C-CONSTRAINTS] Compilation Constraints (Normative)

The compiler MUST enforce the following constraints:

Stub size: The compiled stub MUST NOT exceed 100 lines. If the source skill is too large to summarize within this limit, the compiler MUST truncate sections and indicate truncation.

Section limit: The stub section listing MUST include at most 12 top-level headings. Additional headings MUST be omitted with an indication that more exist.

Command restrictions:

  • skc outline — Lists structure from .md files only
  • skc show — Retrieves sections from .md files only
  • skc open — Retrieves any file within the skill root (not restricted to .md)
  • skc sources — Lists all files within the skill root

Path safety: The compiler MUST reject source directories containing symlinks that escape the skill root.

Since: v0.1.0


4. Compilation Output

[RFC-0001:C-DEPLOYMENT] Deployment Strategy (Normative)

The compiler MUST compile to a Single Source of Truth (SSOT) location and deploy to agent directories.

SSOT Locations

Compiled skills MUST be stored in one of these SSOT locations:

  • Project-local SSOT: .skillc/runtime/<skill-name>/
  • Global SSOT: ~/.skillc/runtime/<skill-name>/

Agent Directories

Agent directories are where AI agents discover skills:

  • ~/.claude/skills/<skill-name>/
  • ~/.cursor/skills/<skill-name>/

Agent directories contain links (or copies) pointing to the SSOT location.

Default Behavior (Local-First)

When compiling a project-local source (.skillc/skills/), the compiler MUST:

  1. Output to project-local SSOT (.skillc/runtime/<skill-name>/)
  2. Deploy to agent directory (~/.claude/skills/<skill-name>/ by default)

When compiling a global source (~/.skillc/skills/), the compiler MUST:

  1. Output to global SSOT (~/.skillc/runtime/<skill-name>/)
  2. Deploy to agent directory (~/.claude/skills/<skill-name>/ by default)

CLI Flags

FlagDefaultEffect
--globalfalseForce SSOT to ~/.skillc/runtime/ regardless of source
--target <agents>claudeWhich agent directories to deploy to (comma-separated)
--copyfalseForce copy instead of symlink/junction
--forcefalseOverwrite existing skill during import

Deployment Methods

The compiler MUST deploy from SSOT to agent directories using these methods:

  1. Unix: Create symlink (default)
  2. Windows: Create directory junction (no admin required)
  3. Fallback: Copy directory contents with warning

The --copy flag forces copy mode on all platforms.

Deployment Behavior

When deploying, the compiler MUST:

  1. Ensure the parent directory exists
  2. Remove any existing symlink/junction at the target path
  3. Create a symlink/junction pointing to the SSOT directory (or copy if --copy)
  4. Report each deployment with method used

The compiler MUST NOT overwrite an existing directory (non-symlink) without --force.

Since: v0.1.0


Changelog

v0.2.1 (2026-01-31)

Add reference file description support

v0.2.0 (2026-01-31)

Add C-SECTIONS

v0.1.0 (2026-01-30)

Initial release

RFC-0002: Gateway Protocol

Version: 0.2.1 | Status: normative | Phase: test


1. Summary

[RFC-0002:C-OVERVIEW] Overview (Informative)

The gateway is how agents access skill content on-demand. Rather than loading entire skills into context, agents use gateway commands to retrieve specific sections as needed.

Gateway commands operate on the source directory, not the compiled stub. This ensures agents always see current content without requiring a rebuild.

Every gateway access is logged per RFC-0007:C-LOGGING, enabling skill authors to understand which content agents actually use.

Gateway commands:

  • outline — List all sections in a skill
  • show — Retrieve section content
  • open — Retrieve file content
  • sources — List source files (tree-style)

See RFC-0007:C-COMMANDS for the complete command registry with parameters and interface availability.

Since: v0.1.0


2. Specification

[RFC-0002:C-OUTLINE] Outline Command (Normative)

Syntax: skc outline <skill> [--level <n>]

The outline command MUST scan all .md files in the skill’s source directory and extract headings.

Options:

OptionDescription
--level <n>Maximum heading level to include (1-6, default: unlimited)

When --level is provided, the command MUST only output headings with level ≤ n. For example, --level 2 shows only # and ## headings.

Output format: The command MUST output a structured list of headings with:

  • Heading level (1-6)
  • Heading text
  • File path (relative to skill root)

Ordering: Headings MUST be listed in file order, with files sorted lexicographically by relative path (bytewise ASCII order). No special-case ordering is permitted.

Example output:

SKILL.md
  # Skill Name
  ## Getting Started
  ## API Reference
    ### Authentication
    ### Endpoints
references/advanced.md
  # Advanced Topics
  ## Performance

With --level 2:

SKILL.md
  # Skill Name
  ## Getting Started
  ## API Reference
references/advanced.md
  # Advanced Topics
  ## Performance

Since: v0.1.0

[RFC-0002:C-SHOW] Show Command (Normative)

Syntax: skc show <skill> --section "<heading>" [--file <path>] [--max-lines <n>]

The show command MUST locate the specified heading and return its content.

Options:

OptionDescription
--file <path>Limit search to specific file
--max-lines <n>Maximum lines to return (default: unlimited)

When --max-lines is provided, the command MUST truncate output to the first n lines. If content is truncated, the command MUST append a line: ... (N more lines)

Index-based lookup: The command MUST use the pre-built headings index from RFC-0004:C-INDEX instead of parsing files at runtime. If the index is missing or stale, the command MUST exit with error E002 per RFC-0005:C-CODES.

Query normalization: Before matching, the query MUST be normalized:

  1. Trim leading/trailing whitespace
  2. If the query contains (em-dash with spaces), extract only the part before it

This allows queries copied from compiled stubs (which may include descriptions) to work correctly.

Heading matching:

  • Matching MUST be case-insensitive
  • If --file is provided, search only that file; otherwise search all indexed headings

Content extraction: The command MUST read content from the source file using the start_line and end_line from the index. Lines are 1-based.

Multiple matches: If multiple headings match, the command MUST return the first match and write a warning to stderr in the form: warning: multiple matches for "<heading>"; showing first The command MUST exit with status 0 in this case.

No match with suggestions: If no heading matches, the command MUST:

  1. Search for similar headings (case-insensitive prefix match or substring match)
  2. If suggestions found, include them in the error message:
    error[E020]: section not found: '<query>'
    
    Did you mean one of these?
      - <suggestion1> (<file1>)
      - <suggestion2> (<file2>)
    
  3. Limit suggestions to 5 entries
  4. Exit with non-zero status

Updated in v0.2.0: Added index-based lookup, query normalization (em-dash stripping), and suggestions on no match.

Since: v0.1.0

[RFC-0002:C-OPEN] Open Command (Normative)

Syntax: skc open <skill> <path> [--max-lines <n>]

The open command MUST return the contents of the specified file.

Options:

OptionDescription
--max-lines <n>Maximum lines to return (default: unlimited)

When --max-lines is provided, the command MUST truncate output to the first n lines. If content is truncated, the command MUST append a line: ... (N more lines)

Path validation:

  • The path MUST be relative to the skill source root
  • The path MUST NOT contain .. sequences that escape the skill root
  • The path MUST refer to a file (not a directory)

Content: The command MUST return the file contents as-is without transformation (except for --max-lines truncation).

File type: The open command is NOT restricted to .md files. It can retrieve any file within the skill source directory. This enables retrieval of search results from non-.md files (e.g., .txt).

Path safety: The command MUST reject any path that would resolve outside the skill source directory after canonicalization. See RFC-0005:C-CODES for error E012.

No match: If the file does not exist, the command MUST exit with error E021 per RFC-0005:C-CODES.

Since: v0.1.0

[RFC-0002:C-ERRORS] Error Handling (Normative)

All gateway command errors MUST exit with status 1 and print an error message to stderr.

Error codes: See RFC-0005:C-CODES for canonical error messages. Gateway commands use:

ConditionError Code
Skill resolution failedE001 or E010
Path escapes skill rootE012
Section not foundE020
File not foundE021
Directory not foundE022
Invalid CLI optionE100

Usage:

  • E001/E010: Skill resolution failed per RFC-0007:C-RESOLUTION. See RFC-0005:C-CODES for when to use each.
  • E012: skc open path or skc sources --dir path would escape the skill root after canonicalization
  • E020: skc show --section finds no matching heading
  • E021: skc open target file does not exist
  • E022: skc sources --dir target directory does not exist
  • E100: Unknown flag, missing required value, or other CLI parsing failure

Since: v0.1.0

[RFC-0002:C-SOURCES] Sources Command (Normative)

Syntax: skc sources <skill> [options]

The sources command MUST list all files in the skill’s source directory in a tree-style format.

Options:

OptionDescription
--depth <n>Maximum tree depth to display (default: unlimited)
--dir <path>Scope listing to a subdirectory
--limit <n>Maximum entries to display (default: 100)
--pattern <glob>Filter files by glob pattern (e.g., *.md)
--format <fmt>Output format: text (default) or json

Output format:

The command MUST output a tree-style directory listing:

  • Files are listed with their relative paths
  • Directories that are not expanded MUST show a file count suffix: dirname/ (N files)
  • When --limit is exceeded, output MUST end with a truncation indicator: ... (N more)

Ordering: Entries MUST be sorted lexicographically by relative path (bytewise ASCII order), with directories listed before files at each level.

Example output:

$ skc sources cuda --depth 2
cuda/
├── SKILL.md
├── references/
│   ├── compilation.md
│   ├── cuda-driver-docs/ (156 files)
│   ├── cuda-runtime-docs/ (89 files)
│   ├── debugging-tools.md
│   └── ... (8 more)

Scoped listing:

When --dir is provided, the command MUST:

  • Validate that the path exists within the skill root
  • Display the subtree rooted at that directory
  • Apply --depth relative to the specified directory

Path safety: The command MUST reject any --dir path that would resolve outside the skill source directory after canonicalization. See RFC-0005:C-CODES for error E012.

Since: v0.1.0


Changelog

v0.2.1 (2026-01-31)

Add missing –format support for skc sources

v0.2.0 (2026-01-31)

C-SHOW updated with em-dash stripping and suggestions

v0.1.0 (2026-01-30)

Initial release

RFC-0003: Usage Analytics

Version: 0.1.0 | Status: normative | Phase: test


1. Summary

[RFC-0003:C-OVERVIEW] Overview (Informative)

Usage analytics enables skill authors to understand how agents interact with their skills.

The analytics system is designed as a data layer with multiple front-end consumers:

  • CLI commands for quick insights
  • JSON output for scripts and automation
  • Future: web API and dashboard

Analytics queries the access logs created by RFC-0007:C-LOGGING and aggregates usage data.

Commands:

  • skc stats <skill> — Show usage summary
  • skc stats <skill> --group-by <type> — Run specific aggregation
  • skc stats <skill> --format json — Machine-readable output

Since: v0.1.0


2. Specification

[RFC-0003:C-QUERIES] Query Types (Normative)

The analytics system MUST support the following query types:

summary — Overview statistics Returns total access count, unique sections accessed, unique files accessed, error count, and date range of data.

sections — Section access breakdown Returns a list of sections ordered by access count (descending). Ties MUST be ordered by file path, then section heading, both ascending. Each entry includes the section heading text, file path, and access count.

files — File access breakdown Returns a list of files ordered by access count (descending). Ties MUST be ordered by file path ascending. Each entry includes the file path and access count.

commands — Command type breakdown Returns access counts grouped by command type. All logged commands appear as keys. Known command types include: outline, show, open, search, build, stats. Additional command types (from future versions) MUST be included as extra keys.

projects — Project/CWD breakdown Returns access counts grouped by calling directory (CWD). Each entry includes the directory path and access count.

errors — Failed lookups Returns a list of failed access attempts. Each entry includes the requested target, command type, error message, and count.

search — Search query breakdown Returns a list of search queries ordered by frequency (descending). Ties MUST be ordered by query text ascending. Each entry includes the query string and count. This enables understanding which search terms agents use most frequently.

The default query type MUST be summary.

Since: v0.1.0

[RFC-0003:C-FILTERS] Query Filters (Normative)

All queries MUST support the following filters:

Time range filters:

  • --since <datetime> — Include only accesses on or after this timestamp
  • --until <datetime> — Include only accesses on or before this timestamp

Timestamps MUST be parsed as RFC 3339 format (YYYY-MM-DDTHH:MM:SSZ) or date-only format (YYYY-MM-DD, interpreted as start of day UTC). Logged access timestamps MUST be stored in UTC.

If no time filters are provided, all available data MUST be included.

Project filter:

  • --project <path> — Include only accesses where CWD matches or is a subdirectory of the given path

The path MUST be matched as a prefix after canonicalization. Canonicalization MUST resolve . and .. path segments and MUST resolve symlinks to their real paths. Matching MUST use the canonicalized absolute paths for both the filter and the logged CWD. For example, --project /Users/me/webapp matches CWDs like /Users/me/webapp, /Users/me/webapp/src, etc.

Multiple --project flags MAY be provided; accesses matching ANY of the paths MUST be included (OR logic).

Filter application: Filters MUST be applied before aggregation. The response schema MUST include the applied filters in the filters field.

Since: v0.1.0

[RFC-0003:C-SCHEMA] Response Schema (Normative)

All analytics responses MUST conform to a JSON schema for interoperability with multiple front-ends.

Root response structure:

{
  "skill": "<skill-name>",
  "skill_path": "<absolute-source-path>",
  "query": "<query-type>",
  "filters": {
    "since": "<datetime-or-null>",
    "until": "<datetime-or-null>",
    "projects": ["<path>", ...]
  },
  "period": {
    "start": "<earliest-access-timestamp>",
    "end": "<latest-access-timestamp>"
  },
  "data": { ... }
}

Query-specific data structures:

summary:

{
  "total_accesses": 150,
  "unique_sections": 8,
  "unique_files": 3,
  "error_count": 5
}

sections:

[
  {"section": "Getting Started", "file": "SKILL.md", "count": 42},
  {"section": "API Reference", "file": "SKILL.md", "count": 35}
]

files:

[
  {"file": "SKILL.md", "count": 100},
  {"file": "docs/advanced.md", "count": 25}
]

commands:

{
  "outline": 50,
  "show": 80,
  "open": 20,
  "search": 45,
  "build": 10
}

projects:

[
  {"project": "/Users/me/webapp", "count": 75},
  {"project": "/Users/me/cli-tool", "count": 25}
]

errors:

[
  {"target": "NonExistentSection", "command": "show", "error": "Section not found", "count": 5}
]

search:

[
  {"query": "authentication", "count": 25},
  {"query": "error handling", "count": 18},
  {"query": "api", "count": 12}
]

The JSON output MUST be valid JSON. Field order is not significant.

Since: v0.1.0

[RFC-0003:C-CLI] CLI Commands (Normative)

Syntax: skc stats <skill> [options]

The stats command MUST query the access log for the specified skill and display usage analytics.

Options:

--group-by <type> — Aggregation dimension (default: summary) Valid values: summary, sections, files, commands, projects, errors

--format <format> — Output format (default: text) Valid values: text, json

--since <datetime> — Filter: include accesses on or after this time

--until <datetime> — Filter: include accesses on or before this time

--project <path> — Filter: include accesses from this project directory (may be repeated)

Skill resolution: The <skill> argument MUST be resolved using the same logic as RFC-0007:C-RESOLUTION.

Log database location: The command MUST read from .skillc-meta/logs.db in the resolved runtime directory (per RFC-0007:C-LOGGING).

No data: If the log database does not exist or contains no matching records, the command MUST return an empty result (not an error). For summary, this means all counts are zero.

Text output: When --format text (default), the command MUST produce human-readable output suitable for terminal display. The exact format is implementation-defined but MUST convey the same information as the JSON schema.

Exit codes:

  • 0: Success (including empty results)
  • 1: Error. See RFC-0003:C-ERRORS for error codes (E001/E010 for skill resolution, E030/E031 for invalid query/filter, E100 for invalid options).

Since: v0.1.0

[RFC-0003:C-ERRORS] Error Handling (Normative)

All analytics command errors MUST exit with status 1 and print an error message to stderr.

Error codes: See RFC-0005:C-CODES for canonical error messages. This RFC uses:

ConditionError Code
Skill resolution failedE001 or E010
Invalid query typeE030
Invalid filterE031
Invalid CLI optionE100

Usage:

  • E001/E010: Skill resolution failed per RFC-0007:C-RESOLUTION. See RFC-0005:C-CODES for when to use each.
  • E030: --query value is not one of: summary, sections, files, commands, projects, errors
  • E031: --since, --until, or --project value is malformed
  • E100: Unknown flag, missing required value, or other CLI parsing failure

Note: Empty results (no matching log entries) are NOT errors. The command MUST return an empty result set with exit code 0.

Since: v0.1.0


Changelog

v0.1.0 (2026-01-30)

Initial release

RFC-0004: Search Protocol

Version: 0.2.0 | Status: normative | Phase: test


1. Summary

[RFC-0004:C-OVERVIEW] Overview (Informative)

Search enables agents to find content within skills using full-text queries.

The search system builds an index during compilation and supports BM25-ranked queries with snippet extraction. Rather than requiring agents to know exact section headings, search allows natural language queries like “how to configure authentication” to find relevant content.

Design principles:

  1. Progressive disclosure — Search returns section references; agents use show to retrieve content
  2. Offline-first — Uses SQLite FTS5, no external dependencies
  3. Extensible formats — File format support is added incrementally
  4. Observable — All searches are logged for analytics

Commands:

  • skc search <skill> <query> — Find matching sections

Since: v0.1.0


2. Specification

[RFC-0004:C-FORMATS] Supported Formats (Normative)

The search index MUST support the following file formats:

v0.1.0:

  • .md — Markdown files, segmented by headings. Each section (heading + content until next heading of equal or higher level) becomes a searchable document. The section field contains the heading text.
  • .txt — Plain text files, indexed as a single document. The section field MUST be an empty string ("").

Retrieval: Search results from any indexed format can be retrieved using skc open <skill> <path>. The open command is not restricted to .md files (see RFC-0002:C-OPEN).

Additional formats MAY be added in future versions. The implementation MUST silently skip unsupported file types without error.

Planned (future versions):

  • .csv — Each row as a searchable document
  • .json, .yaml, .toml — Flattened key-value pairs
  • Code files (.py, .js, .ts, .rs) — Plain text with comment weighting

Since: v0.1.0

[RFC-0004:C-INDEX] Index Storage (Normative)

The search index MUST be stored as a SQLite FTS5 database in the skill’s runtime directory.

Index file naming: To avoid collisions when multiple source directories share a runtime store, the index file MUST be named using a hash of the source path:

.skillc-meta/search-<hash16>.db

Where <hash16> is the first 16 characters (64 bits) of the SHA-256 hash of the canonicalized source directory path.

Tokenizer preference: The current tokenizer preference is determined at runtime:

  1. Attempt porter unicode61
  2. If unavailable, fall back to unicode61

This preference is used for both index creation (build) and checking (search).

Corrupt index definition: An index is corrupt if any of:

  • The database file cannot be opened as a SQLite database
  • The index_meta table does not exist
  • Any required key is missing (skill_path, source_hash, schema_version, tokenizer)
  • Any required key value cannot be parsed (e.g., non-integer schema_version)

Any read or parse failure during index access MUST be treated as corruption. Implementations MUST NOT attempt to distinguish transient errors from permanent corruption; all failures map to the same handling (E002 for search, delete+rebuild for build).

Index file selection (search): When searching, the implementation MUST follow these steps in order:

  1. Compute the expected filename search-<hash16>.db
  2. If file does not exist: exit with error E002 (missing)
  3. Open the database and read required keys from index_meta; if corrupt (per definition above): exit with error E002
  4. If skill_path does not match current source path: exit with error E003 (collision)
  5. Check staleness conditions (see below): if stale, exit with error E002
  6. Proceed with search

E002 conditions (search): E002 (“unusable”) is the umbrella error covering three distinct failure modes:

  • Missing: file does not exist (step 2)
  • Corrupt: any read/parse failure (step 3)
  • Stale: metadata mismatch (step 5) — a subset of “unusable”

All three require skc build to fix.

See RFC-0005:C-CODES for canonical error messages.

Staleness conditions (search-only): “Stale” is a subset of “unusable” that applies when the index can be read but its metadata does not match the current skill state.

After confirming no collision (step 4), the index is stale if any of:

  • source_hash does not match current manifest hash
  • schema_version < current schema version (currently 2)
  • tokenizer does not match current tokenizer preference

These three fields are the only staleness conditions. Missing file and corrupt index are handled earlier (steps 2-3). The skill_path field is used for collision detection (step 4), not staleness.

If stale, skc search MUST exit with error E002.

Index lifecycle (build): When skc build runs:

  1. Compute the expected filename search-<hash16>.db
  2. If file does not exist: proceed to step 6 to create new index
  3. Open the database and read required keys from index_meta; if any read/parse failure: delete file, proceed to step 6 to create new index
  4. If skill_path does NOT match current source path: exit with error E003 (collision). Stop.
  5. Compare source_hash, schema_version, and tokenizer:
    • If all match: skip rebuild. Done.
    • Else: delete existing file, proceed to step 6 to create new index.
  6. Create new index with current tokenizer preference

Build does not error on unusable indexes; it rebuilds them. Corrupt indexes are deleted without collision detection since skill_path cannot be reliably read.

Build behavior summary:

  • Missing: create new index (step 2 → 6)
  • Corrupt: delete and rebuild without collision check (step 3 → 6)
  • Collision (skill_path mismatch): error E003 (step 4)
  • Up-to-date (all metadata matches): skip rebuild (step 5)
  • Stale (metadata differs): rebuild (step 5 → 6)

No automatic cleanup: The implementation MUST NOT delete other search-*.db files. Multiple skills may share a runtime directory.

Runtime directory resolution: The runtime directory MUST be resolved using the same logic as RFC-0007:C-RESOLUTION.

Index schema: The database MUST contain a virtual table using FTS5 for full-text search:

CREATE VIRTUAL TABLE sections USING fts5(
    file,
    section,
    content,
    tokenize='porter unicode61'
);

The database MUST contain a headings table for section lookup by RFC-0002:C-SHOW:

CREATE TABLE headings (
    id INTEGER PRIMARY KEY,
    file TEXT NOT NULL,
    text TEXT NOT NULL,
    level INTEGER NOT NULL,
    start_line INTEGER NOT NULL,
    end_line INTEGER NOT NULL
);

CREATE INDEX idx_headings_text ON headings(text COLLATE NOCASE);

Fields:

  • file — relative path from skill root
  • text — heading text (without # prefix)
  • level — heading level (1-6)
  • start_line — 1-based line number of heading
  • end_line — 1-based line number of next heading (or EOF+1)

The database MUST also contain a metadata table:

CREATE TABLE index_meta (
    key TEXT PRIMARY KEY,
    value TEXT
);

Required metadata keys:

  • source_hash — Hash from RFC-0001:C-MANIFEST
  • skill_path — Canonicalized absolute path to source directory
  • schema_version — Integer (currently 2)
  • indexed_at — RFC 3339 UTC timestamp
  • tokenizerporter or unicode61

Schema migration: No in-place migration. User must run skc build.

Updated in v0.2.0: Added headings table for index-based section lookup. Bumped schema_version to 2.

Since: v0.1.0

[RFC-0004:C-SEARCH] Search Command (Normative)

Syntax: skc search <skill> <query> [options]

The search command MUST query the FTS5 index and return ranked results.

Options:

  • --limit N — Maximum results (default: 10)
  • --format <text|json> — Output format (default: text)

Ranking: Results MUST be ranked using BM25. Scores MUST be negated for display (FTS5 returns negative).

Snippet extraction: Snippet parameters (FTS5 snippet() function):

  • Column: content (index 2)
  • Start marker: [MATCH]
  • End marker: [/MATCH]
  • Ellipsis: ...
  • Token limit: 32

Output format guarantees:

JSON is canonical (Normative). Use JSON for machine parsing.

JSON output (--format json):

{
  "query": "<original-query>",
  "results": [
    {
      "file": "<relative-path>",
      "section": "<heading-or-identifier>",
      "snippet": "...text with [MATCH]term[/MATCH]...",
      "score": <float>
    }
  ]
}

Text output (--format text) — Informative only: Human-readable, NOT a stable contract. Do NOT parse.

<file>#<section> (score: <score>)
  <snippet>

No results: Return empty result set, exit 0. JSON: {"query": "...", "results": []}.

Skill resolution: Per RFC-0007:C-RESOLUTION.

Error handling: All errors exit with status 1. See RFC-0005:C-CODES for canonical error messages.

ConditionError Code
Skill resolution failedE001 or E010
Index unusableE002
Index hash collisionE003
Empty queryE004
Invalid CLI optionE100

Note: “Index unusable” (E002) covers three cases: missing file, corrupt index, or stale metadata. See RFC-0004:C-INDEX for details.

Since: v0.1.0

[RFC-0004:C-LOGGING] Search Logging (Normative)

Search commands MUST be logged per RFC-0007:C-LOGGING.

Command name: search

Args format:

{
  "query": "<search-query>",
  "result_count": <number-of-results-returned>
}

Error field: If the search fails (e.g., stale index), the error message MUST be recorded in the error field.

Analytics extension (future): The stats command (per RFC-0003) SHOULD be extended to support a searches query type that aggregates:

  • Query strings and their frequency
  • Average result counts
  • Zero-result query patterns

This extension is NOT part of v0.1.0. Until implemented, --query searches is not a valid query type and will result in error E030 per RFC-0005:C-CODES.

Since: v0.1.0

[RFC-0004:C-QUERY-SYNTAX] Query Syntax (Normative)

Query semantics: The <query> argument is treated as a bag-of-words query with implicit AND. Each word in the query must appear somewhere in the document for a match; word order and adjacency are NOT required.

Example: Query configure authentication matches documents containing both words anywhere in the content, regardless of order or proximity.

Tokenizer-dependent matching: Query matching behavior depends on the tokenizer used to build the index (recorded in index_meta.tokenizer):

  • porter: Terms are stemmed. Query configuring matches indexed configure.
  • unicode61: No stemming. Query configuring does NOT match configure.

FTS5 handles tokenizer selection internally based on how the index was created. The implementation does not need to branch on tokenizer type; FTS5 applies the correct tokenizer automatically. However, the recorded tokenizer value is useful for debugging, diagnostics, and user understanding of matching behavior.

Query tokenization: To construct a bag-of-words AND query, the implementation MUST:

  1. Split the query on ASCII whitespace only (space U+0020, tab U+0009, newline U+000A, carriage return U+000D)
  2. Remove empty tokens
  3. For each non-empty token: a. Escape internal " by doubling (""") b. Wrap in double quotes to make it a literal FTS5 term
  4. Join all quoted tokens with spaces (implicit AND in FTS5)

Unicode whitespace limitation: Non-ASCII whitespace characters (e.g., non-breaking space U+00A0, ideographic space U+3000) are NOT treated as token separators. They are included as part of the token. This is a known limitation. Users should use ASCII spaces in queries.

Example: User input configure authentication becomes FTS5 query "configure" "authentication".

Example with quotes: User input my "special" app becomes FTS5 query "my" """special""" "app".

Why this works: Each quoted token is passed to FTS5 as a single-term phrase. FTS5 applies its internal tokenizer (matching the index) to each term, handling Unicode normalization and stemming as appropriate. Multiple quoted terms joined by spaces create an implicit AND query.

Note on punctuation: Punctuation attached to words (e.g., hello, or (world)) is passed to FTS5 as-is. FTS5’s tokenizer will strip it during matching.

Shell quoting: The query is passed as a single shell argument. Users MUST quote multi-word queries:

skc search my-skill "configure authentication"  # Correct
skc search my-skill configure authentication    # Wrong: two positional args

Empty query: If the query is empty or contains only ASCII whitespace, the command MUST exit with error E004. See RFC-0005:C-CODES for the canonical message.

Future extension:

  • --raw — Pass raw FTS5 syntax for advanced users
  • --phrase — Require adjacency (true phrase matching)

These flags are NOT part of v0.1.0.

Since: v0.1.0

[RFC-0004:C-ERRORS] Error Messages (Normative)

All search-related errors MUST exit with status 1 and print an error message to stderr.

Error codes: See RFC-0005:C-CODES for canonical error messages. This RFC uses:

ConditionError Code
Skill resolution failedE001 or E010
Index unusableE002
Index hash collisionE003
Empty queryE004
Invalid CLI optionE100

Usage:

  • E001/E010: Skill resolution failed per RFC-0007:C-RESOLUTION. See RFC-0005:C-CODES for when to use each.
  • E002: Index unusable (missing, corrupt, or stale). See RFC-0004:C-INDEX for details.
  • E003: Index filename exists but skill_path does not match (hash collision)
  • E004: Query is empty or contains only whitespace
  • E100: Unknown flag, missing required value, or other CLI parsing failure

Collision handling: Hash collisions are rare but possible. When detected, the user MUST manually delete the conflicting index file. The error message includes the filename pattern to delete. Automatic deletion is not performed because it could destroy another skill’s valid index.

Corrupt index handling: An index is corrupt if the database cannot be opened, index_meta table is missing, required keys are missing, or key values cannot be parsed. See RFC-0004:C-INDEX for the full definition. During search, corruption maps to E002. During build, corrupt files are deleted and rebuilt without collision detection (since skill_path cannot be verified).

Since: v0.1.0


Changelog

v0.2.0 (2026-01-31)

C-INDEX updated with headings table, schema version bumped to 2

v0.1.0 (2026-01-30)

Initial release

RFC-0005: Error Code Registry

Version: 0.1.0 | Status: normative | Phase: test


1. Summary


2. Specification

[RFC-0005:C-CODES] Error Code Table (Normative)

Error Codes

Canonical error code table:

CodeMessage TemplateSemantics
E001error[E001]: skill '<skill>' not foundSkill resolution failed (no matching directory in any store)
E002error[E002]: search index unusable; run 'skc build <skill>' to rebuildIndex is missing, corrupt, or stale
E003error[E003]: index hash collision; delete .skillc-meta/search-<hash16>.db and rebuildIndex filename exists but belongs to different skill
E004error[E004]: empty querySearch query is empty or whitespace-only
E010error[E010]: not a valid skill: '<path>' (missing SKILL.md)Directory exists but lacks SKILL.md
E011error[E011]: missing frontmatter field '<field>' in SKILL.mdSKILL.md lacks required name or description field entirely
E012error[E012]: path escapes skill root: '<path>'Symlink or path traversal would escape skill directory
E020error[E020]: section not found: '<section>'Gateway show command found no matching heading
E021error[E021]: file not found: '<path>'Gateway open command target does not exist
E022error[E022]: directory not found: '<path>'Gateway sources –dir target does not exist
E030error[E030]: invalid query type: '<type>'Stats command received unknown query type
E031error[E031]: invalid filter: '<message>'Stats command received malformed filter value
E040error[E040]: no local logs foundSync command found no fallback logs to sync
E041error[E041]: sync destination not writable: '<path>'Sync command cannot write to primary runtime directory
E042error[E042]: sync source not readable: '<path>'Sync command cannot read from fallback log database
E050error[E050]: skill '<skill>' already existsInit command target already has SKILL.md
E100error[E100]: invalid option: '<message>'CLI parsing failed (unknown flag, missing value, etc.)
E300error[E300]: <rule-id> <rule-name>: <message>Lint rule violation with error severity (see RFC-0008)
E999error[E999]: <message>Internal error (IO, database, parsing, or other unexpected failures)

Warning Codes

Canonical warning code table:

CodeMessage TemplateSemantics
W001warning[W001]: multiple matches for '<section>'; showing firstGateway show found multiple headings matching query
W002warning[W002]: logging disabled; run 'skc sync' after session to merge logsAccess logging failed, using fallback or disabled
W003warning[W003]: stale local logs for '<skill>'; run 'skc sync' to uploadLocal fallback logs exist and are older than threshold
W300warning[W300]: <rule-id> <rule-name>: <message>Lint rule violation with warning severity (see RFC-0008)

Warning behavior:

  • Warnings are printed to stderr but do NOT cause command failure
  • Commands that emit warnings still exit with code 0
  • Multiple warnings may be emitted per command invocation

Resolution error hierarchy

When resolving a skill per RFC-0007:C-RESOLUTION:

  • E010: A directory was found (at the given path OR in project/global stores) but it lacks SKILL.md
  • E001: No directory was found at the path AND no match in project/global stores

E010 is a more specific form of resolution failure. Use E010 when a directory exists but isn’t a valid skill; use E001 when no directory is found at all.

Lint diagnostics

Lint diagnostics (E300, W300) use a structured format that includes the rule ID from RFC-0008:C-REGISTRY:

<severity>[<code>]: <rule-id> <rule-name>: <message>

Examples:

  • error[E300]: SKL102 name-format: name contains invalid characters
  • warning[W300]: SKL108 description-triggers: missing activation trigger
  • warning[W300]: SKL401 no-orphans: orphaned file 'old-draft.md'

The rule ID (SKLxxx) provides semantic detail; the diagnostic code (E300/W300) indicates severity. This separation allows adding new lint rules without modifying this RFC.

Unified codes

The following codes are used across multiple RFCs:

  • E001/E010 (Skill resolution): All commands that resolve skills via RFC-0007:C-RESOLUTION MUST use E001 or E010 when resolution fails.
  • E002–E004 (Index/query): Errors for index state and query validation. Currently used by search; future commands with similar semantics should reuse these.
  • E012 (Path escape): Any command that validates paths MUST use E012 when a path would escape the skill root.
  • E040–E042 (Sync): Errors specific to the sync command for log synchronization.
  • E050 (Skill exists): Init command cannot overwrite existing skill.
  • E100 (Invalid option): All commands MUST use E100 for flag/option parsing failures.
  • E300/W300 (Lint): Skill authoring validation per RFC-0008. Rule IDs (SKLxxx) provide specifics.
  • E999 (Internal): Unexpected failures (IO errors, database errors, parsing errors). These indicate bugs or environmental issues, not user errors.
  • W001 (Multiple matches): Gateway commands that find multiple matches.
  • W002 (Logging disabled): Access logging encountered errors.
  • W003 (Stale logs): Local fallback logs need syncing.

Message format

All diagnostic messages MUST include the code in brackets:

  • Errors: error[EXXX]: <message>
  • Warnings: warning[WXXX]: <message>

This format enables:

  • Machine parsing of diagnostic codes
  • Easy searching in documentation
  • Consistent user experience across commands

Placeholder substitution:

  • <skill> — The skill name/path provided by the user
  • <path> — File or directory path
  • <hash16> — First 16 characters of SHA-256 hash
  • <field> — Frontmatter field name
  • <section> — Section heading text
  • <type> — Query type string
  • <message> — Contextual error details
  • <rule-id> — Lint rule identifier (e.g., SKL102)
  • <rule-name> — Lint rule name (e.g., name-format)

Exit behavior

  • Errors: Exit with status 1
  • Warnings: Do not affect exit status (exit 0 if no errors)

Implementations MUST NOT use different exit codes for different error types.

Adding new codes

New diagnostic codes MUST be added to this table via RFC amendment. Feature RFCs MUST NOT define new codes inline; they MUST reference this RFC and propose additions here.

Exception: Lint rules (SKLxxx) are defined in RFC-0008 and use E300/W300 as their diagnostic codes. Adding new lint rules does not require amending this RFC.

Reserved ranges:

Error codes:

  • E001–E010: Unified errors (skill resolution, index state, query validation, path safety)
  • E011–E019: Compilation errors (RFC-0001)
  • E020–E029: Gateway errors (RFC-0002)
  • E030–E039: Analytics errors (RFC-0003)
  • E040–E049: Sync errors (RFC-0007)
  • E050–E059: Scaffolding errors (RFC-0006)
  • E100–E199: CLI parsing errors (all commands)
  • E200–E299: Reserved for network/remote errors
  • E300: Lint errors (RFC-0008) — rule IDs provide specifics
  • E999: Internal/unexpected errors

Warning codes:

  • W001–W009: Gateway warnings
  • W010–W019: Logging warnings
  • W020–W029: Reserved for future use
  • W300: Lint warnings (RFC-0008) — rule IDs provide specifics

Since: v0.1.0

[RFC-0005:C-USAGE] Usage by Feature RFCs (Normative)

Feature RFC requirements:

Feature RFCs that define error behavior MUST:

  1. Reference this RFC — Use [RFC-0005](../rfc/RFC-0005.md) or [RFC-0005:C-CODES](../rfc/RFC-0005.md#rfc-0005c-codes) when discussing error codes
  2. Use canonical codes — Only use error codes defined in RFC-0005:C-CODES
  3. Document applicability — Specify which codes apply to which commands/conditions
  4. Not redefine messages — Use the exact message templates from this RFC

Example usage in feature RFCs:

**Error handling:**
See [RFC-0005:C-CODES](../rfc/RFC-0005.md#rfc-0005c-codes) for canonical error messages.

| Condition | Error Code |
|-----------|------------|
| Skill not found | E001 |
| Index unusable | E002 |

Proposing new codes:

To add a new error code:

  1. Submit an amendment to this RFC
  2. Include: code, message template, semantics, and reserved range justification
  3. Update the canonical table in RFC-0005:C-CODES

Deprecating codes:

Deprecated codes MUST remain in the table with a (deprecated) suffix in the Semantics column. They MUST NOT be removed to maintain backward compatibility.

Since: v0.1.0


3. Motivation

[RFC-0005:C-OVERVIEW] Overview (Normative)

This RFC defines the canonical diagnostic code registry for skillc. All error and warning codes used across the CLI are defined here.

Purpose:

  • Single source of truth for diagnostic semantics
  • Consistent messages across commands
  • Feature RFCs reference this registry instead of defining their own codes

Scope: This RFC defines diagnostic codes and message templates. Per-command handling (which codes apply, when they’re raised) remains in feature RFCs.

Diagnostic levels:

  • Errors (error[EXXX]): Fatal conditions that prevent command completion. Exit code 1.
  • Warnings (warning[WXXX]): Non-fatal conditions where command succeeds but with degraded behavior. Exit code 0.

Design principles:

  • Exit code 1 for errors, 0 for warnings
  • All diagnostics printed to stderr
  • Human-readable messages with codes for documentation/search

Since: v0.1.0


Changelog

v0.1.0 (2026-01-30)

Initial release

RFC-0006: Scaffolding

Version: 0.1.0 | Status: normative | Phase: test


1. Summary

[RFC-0006:C-OVERVIEW] Overview (Informative)

Scaffolding provides commands to initialize skillc projects and create new skills.

The init command creates the necessary directory structure for skillc to manage skills locally within a project, or creates new skill templates.

Design principles:

  1. Project-local first — Skills are created within the current project by default
  2. Minimal templates — Generated files contain only required structure
  3. Idempotent initialization — Running init multiple times is safe

Since: v0.1.0


2. Specification

[RFC-0006:C-INIT] Initialization Command (Normative)

The skc init command scaffolds skillc project and skill structures.

Project Initialization

skc init

When invoked without arguments, skillc MUST:

  1. Create .skillc/ directory in the current working directory if it does not exist
  2. Create .skillc/skills/ subdirectory for project-local skill sources
  3. Print confirmation message to stdout

If .skillc/ already exists, the command MUST succeed without error (idempotent).

Skill Creation

skc init <name>
skc init <name> --global

When invoked with a skill name, skillc MUST:

  1. Determine the target directory:
    • Without --global: .skillc/skills/<name>/ (project-local)
    • With --global: ~/.skillc/skills/<name>/ (global source store)
  2. Create the target directory if it does not exist
  3. Create SKILL.md with minimal frontmatter:
---
name: <name>
description: "TODO: Add skill description"
---

# <Name>

Where <name> is the skill name as provided (lowercase), and <Name> is title-cased.

The description MUST be non-empty to satisfy RFC-0001:C-INPUT requirements. Users should replace the placeholder with a meaningful description.

Error Conditions

The command MUST fail with an error if:

  • SKILL.md already exists in the target directory (prevents accidental overwrite)
  • The target directory cannot be created (permissions, disk full, etc.)

Rationale:

Scaffolding eliminates the need to manually create skill directories and remember frontmatter format. The minimal template ensures valid Agent Skills format from the start. Project-local skills support the common workflow of developing skills alongside application code.

Since: v0.1.0


Changelog

v0.1.0 (2026-01-30)

Initial release

RFC-0007: CLI Reference

Version: 0.1.0 | Status: normative | Phase: test


1. Summary

[RFC-0007:C-OVERVIEW] Overview (Informative)

RFC-0007 is the single source of truth for skillc’s command-line interface.

This RFC specifies:

  1. Command Registry — All commands, their parameters, and interface availability (CLI vs MCP)
  2. Skill Resolution — How skill names/paths are resolved to source directories
  3. Access Logging — How command invocations are logged for analytics
  4. Sync Command — How fallback logs are merged to primary locations
  5. MCP Interface — The Model Context Protocol server for agent integration

Relationship to other RFCs:

  • RFC-0001 — Skill Compilation (build command behavioral spec)
  • RFC-0002 — Gateway Protocol (outline, show, open, sources behavioral specs)
  • RFC-0003 — Usage Analytics (stats command behavioral spec)
  • RFC-0004 — Search Protocol (search command behavioral spec)
  • RFC-0005 — Error Code Registry (canonical error codes)
  • RFC-0006 — Scaffolding (init command behavioral spec)

Each feature RFC owns the behavioral specification for its commands. RFC-0007 provides the cross-cutting infrastructure that all commands share.

Since: v0.1.0


2. Specification

[RFC-0007:C-COMMANDS] Command Registry (Normative)

This clause defines all skillc commands, their parameters, and interface availability.

Interface Legend:

  • CLI: Command-line interface (skc <command>)
  • MCP: Model Context Protocol tool (skc_<command>)

Command Registry

CommandCLIMCPDescription
initInitialize project or create skill
listList all skillc-managed skills
buildCompile skill to runtime format
lintValidate skill authoring quality
outlineList all sections in a skill
showRetrieve section content
openRetrieve file content
sourcesList source files (tree-style)
searchSearch skill content
statsUsage analytics
syncMerge fallback logs to primary (CLI-only)
mcpStart MCP server (CLI-only)

Parameter Definitions

init

ParameterTypeRequiredDefaultDescription
namestringnoSkill name to create
--globalbooleannofalseCreate in global source store

list

ParameterTypeRequiredDefaultDescription
--scopestringnoallFilter: project, global, or all
--statusstringnoallFilter: normal, not-built, obsolete, or all
--limitnumbernounlimitedMaximum skills to return
--patternstringnoFilter by skill name (glob pattern)
--check-obsoletebooleannofalseEnable obsolete runtime detection

See RFC-0007:C-LIST for full specification.

build

ParameterTypeRequiredDefaultDescription
skillstringyesSkill name or path
--globalbooleannofalseForce SSOT to global (~/.skillc/runtime/)
--targetstring[]noclaudeTarget agents to deploy to (comma-separated)
--copybooleannofalseForce copy instead of symlink/junction
--forcebooleannofalseOverwrite existing skill during import

Behavior:

  • Skill name: Looks up skill in project source store (.skillc/skills/) then global (~/.skillc/skills/)
  • Path: Imports skill to source store first, then builds (requires --force to overwrite existing)

Compiles to SSOT location (.skillc/runtime/ for local sources, ~/.skillc/runtime/ for global) and deploys to agent directories via symlink. See RFC-0001:C-DEPLOYMENT.

lint

ParameterTypeRequiredDefaultDescription
skillstringyesSkill name or path
--forcebooleannofalseLint even if skill is compiled

outline

ParameterTypeRequiredDefaultDescription
skillstringyesSkill name or path
levelnumbernounlimitedMaximum heading level (1-6)

show

ParameterTypeRequiredDefaultDescription
skillstringyesSkill name or path
sectionstringyesSection heading to retrieve
filestringnoLimit search to specific file
max_linesnumbernounlimitedMaximum lines to return

open

ParameterTypeRequiredDefaultDescription
skillstringyesSkill name or path
pathstringyesRelative path within skill
max_linesnumbernounlimitedMaximum lines to return

sources

ParameterTypeRequiredDefaultDescription
skillstringyesSkill name or path
depthnumbernounlimitedMaximum tree depth
dirstringnoScope to subdirectory
limitnumberno100Maximum entries
patternstringnoGlob pattern filter
ParameterTypeRequiredDefaultDescription
skillstringyesSkill name or path
querystringyesSearch query
limitnumberno10Maximum results

stats

ParameterTypeRequiredDefaultDescription
skillstringyesSkill name or path
group_bystringnosummaryAggregation dimension: summary, files, sections, commands, projects, errors, search
sincestringnoInclude accesses on or after (ISO 8601)
untilstringnoInclude accesses on or before (ISO 8601)
projectstring[]noFilter by project directory

sync (CLI-only)

ParameterTypeRequiredDefaultDescription
skillstringnoSpecific skill to sync
projectstringnoCWDProject directory
dry_runbooleannofalsePreview without writing

Rationale for CLI-only commands:

  • sync: MCP servers run outside the sandbox and write directly to primary runtime locations. No fallback logs are created, so there is nothing to sync. See RFC-0007:C-LOGGING for fallback mechanism.
  • mcp: Starts the MCP server itself; not callable from within MCP.

MCP Tool Naming

MCP tools use snake_case with skc_ prefix:

CLI CommandMCP Tool
skc initskc_init
skc listskc_list
skc buildskc_build
skc lintskc_lint
skc outlineskc_outline
skc showskc_show
skc openskc_open
skc sourcesskc_sources
skc searchskc_search
skc statsskc_stats

Since: v0.1.0

[RFC-0007:C-RESOLUTION] Skill Resolution (Normative)

All commands that operate on skills accept a <skill> argument that identifies the target skill.

Source directory resolution (first match wins):

  1. If <skill> resolves to a valid directory path containing SKILL.md, use it directly (CWD-relative or absolute). This means a local path takes precedence over a global skill with the same name.
  2. If project config exists (.skillc/config.toml relative to CWD), check project source store using <skill> as a name
  3. Check global source store (~/.skillc/skills/<skill>/) using <skill> as a name
  4. Resolution failed. Exit with error per RFC-0005:C-CODES:
    • If a directory was found at any step but it lacks SKILL.md: emit E010
    • Otherwise (no directory found at all): emit E001

Runtime directory resolution (for logging):

Derive <skill-name> from the resolved source directory’s basename. Resolve the runtime store using the same config precedence as storage layout (project config, then global config, then defaults). The runtime directory is <runtime-store>/<skill-name>/. If multiple source directories share the same basename within the same runtime store, they will share a log database; skill_path in the log distinguishes entries.

Since: v0.1.0

[RFC-0007:C-LOGGING] Access Logging (Normative)

All commands that resolve skills MUST log access events for usage analytics.

Log storage: Logs MUST be stored in a SQLite database at .skillc-meta/logs.db in the resolved runtime directory.

Schema: The database MUST contain an access_log table with at minimum:

  • id — Auto-incrementing primary key
  • timestamp — RFC 3339 UTC timestamp (YYYY-MM-DDTHH:MM:SSZ)
  • run_id — Session identifier
  • command — Command name (the skc subcommand, e.g., outline, show, open, search, build, stats)
  • skill — Skill name (directory basename)
  • skill_path — Canonicalized absolute path to the resolved skill source directory
  • cwd — Canonicalized absolute path of the current working directory when command was invoked
  • args — JSON-encoded command arguments
  • error — Error message if command failed (NULL on success)

Canonicalization MUST resolve . and .. path segments and MUST resolve symlinks to their real paths.

Run ID generation: If SKC_RUN_ID environment variable is set, use its value. Otherwise, generate a run ID in the format YYYYMMDDTHHMMSSZ-<rand4> where <rand4> is 4 random hex characters.

Initialization: The command MUST attempt to create the runtime directory, .skillc-meta/ subdirectory, database, and schema if they do not exist.

Fallback logging (EAFP): The command MUST first attempt to write to the primary runtime directory. If the INSERT fails with a read-only error (e.g., sandboxed filesystem), the command MUST fall back to <cwd>/.skillc/logs/<skill-name>/.skillc-meta/logs.db. The fallback directory and database MUST be created if they do not exist.

If both primary and fallback locations fail, the command MUST emit a warning to stderr: warning: logging disabled; run 'skc sync' after session to merge logs

Stale fallback warning: If fallback logs exist for the current skill and the database file’s mtime is older than 1 hour, the command SHOULD emit a warning to stderr: warning: stale local logs for '<skill>'; run 'skc sync' to upload

This warning SHOULD be emitted at most once per command invocation (not per skill if multiple skills are accessed).

The command MUST continue execution regardless of logging success.

Since: v0.1.0

[RFC-0007:C-SYNC] Sync Command (Normative)

Syntax: skc sync [<skill>] [options]

The sync command MUST move log entries from project-local fallback databases to the primary runtime log, then delete the local fallback.

Source discovery: Scan <cwd>/.skillc/logs/ for skill subdirectories containing .skillc-meta/logs.db. If <skill> is provided, sync only that skill’s logs.

Destination: The primary runtime directory per RFC-0007:C-RESOLUTION. For global skills, this is typically ~/.skillc/runtime/<skill>/.skillc-meta/logs.db.

Behavior:

  1. For each discovered skill, copy all entries to the destination database
  2. Skip entries that already exist (idempotent safety check)
  3. After successful copy, delete the local fallback database directory
  4. If destination is not writable (e.g., sandbox still active), emit error E041 and skip that skill

Partial failure: If sync succeeds for skill A but fails for skill B, delete A’s local logs and report B’s error. Each skill is independent.

Options:

OptionDescription
--project <path>Sync from specified project directory instead of CWD
--dry-runShow what would be synced without writing or deleting

Output:

Synced 47 entries for 'rust' (local logs removed)
Synced 12 entries for 'cuda' (local logs removed)

With --dry-run:

Would sync 47 entries for 'rust'
Would sync 12 entries for 'cuda'

If no local logs exist:

No local logs to sync

Exit codes:

  • 0: Success (including “nothing to sync”)
  • 1: Error (partial or complete failure). See RFC-0005:C-CODES for error codes E040–E042.

Since: v0.1.0

[RFC-0007:C-LIST] List Command (Normative)

Syntax: skc list [options]

The list command MUST enumerate all skillc-managed skills from source stores.

Discovery

The command MUST discover skills from these locations in order:

  1. Project-local source store: Recursive-up search for .skillc/skills/ directories
  2. Global source store: ~/.skillc/skills/

A valid skill is a directory containing a SKILL.md file with valid frontmatter.

Status Detection

Default (Fast Mode)

Without --check-obsolete, status detection is fast:

StatusCondition
normalRuntime directory exists with valid manifest.json
not-builtNo runtime directory or no manifest.json

With –check-obsolete (Hash Comparison)

When --check-obsolete is provided, the command performs expensive source hash comparison:

StatusCondition
normalRuntime exists and source hash matches manifest
not-builtNo runtime directory or no manifest.json
obsoleteRuntime exists but source hash differs from manifest

Output Format

Text Output (CLI default)

$ skc list
SKILL           SCOPE    STATUS
my-skill        project  normal
cuda            global   not-built

When --verbose is provided, include paths:

$ skc list --verbose
SKILL           SCOPE    STATUS     SOURCE
my-skill        project  normal     .skillc/skills/my-skill
cuda            global   not-built  ~/.skillc/skills/cuda

JSON Output (MCP default)

{
  "skills": [
    {
      "name": "my-skill",
      "scope": "project",
      "status": "normal",
      "source_path": "/path/to/.skillc/skills/my-skill",
      "runtime_path": "/path/to/.skillc/runtime/my-skill"
    }
  ],
  "total": 1,
  "filtered": 1
}

Filtering

OptionTypeDefaultDescription
--scopeproject|global|allallFilter by skill scope
--statusnormal|not-built|obsolete|allallFilter by build status
--limitnumberunlimitedMaximum skills to return
--patternstringFilter by skill name (glob pattern)
--check-obsoletebooleanfalseEnable hash comparison for obsolete detection

Ordering

Skills MUST be ordered by:

  1. Scope: project before global
  2. Name: alphabetical within scope

Error Handling

  • If no skills are found, output an empty list (not an error)
  • If a skill directory exists but SKILL.md is invalid, skip with warning

Since: v0.1.0


3. MCP Interface

[RFC-0007:C-MCP-OVERVIEW] MCP Interface Overview (Informative)

The MCP (Model Context Protocol) interface provides structured access to skillc functionality for AI agents. Per ADR-0003, MCP is the recommended interface for agents because:

  1. No sandbox restrictions: MCP servers run outside the IDE sandbox, enabling writes to global directories
  2. Structured I/O: JSON input/output eliminates text parsing errors
  3. Native integration: MCP is the designed protocol for agent tools
  4. Reduced latency: No shell process spawn per command

The MCP interface mirrors CLI functionality. Each CLI command has a corresponding MCP tool with equivalent behavior but structured data exchange.

Architecture:

Human users:  Terminal → skc CLI → skillc core
AI agents:    MCP client → skillc MCP server → skillc core

Since: v0.1.0

[RFC-0007:C-MCP-SERVER] MCP Server (Normative)

Syntax: skc mcp

The MCP server command MUST start a long-running process that speaks the MCP protocol over stdio.

Protocol:

The server MUST implement the MCP stdio transport:

  • Read JSON-RPC messages from stdin
  • Write JSON-RPC messages to stdout
  • Diagnostic output (if any) MUST go to stderr

Server info:

The server MUST respond to initialize with:

  • name: "skillc"
  • version: The skillc version string

Tool discovery:

The server MUST respond to tools/list with the MCP-enabled tools defined in RFC-0007:C-COMMANDS.

Configuration:

The MCP server is configured in the agent’s MCP settings:

{
  "mcpServers": {
    "skillc": {
      "command": "skc",
      "args": ["mcp"]
    }
  }
}

Logging:

All tool invocations MUST be logged per RFC-0007:C-LOGGING. Since the MCP server runs outside the sandbox, logging SHOULD write directly to the primary runtime location (no fallback needed).

Since: v0.1.0


Changelog

v0.1.0 (2026-01-30)

Initial release

RFC-0008: Skill Authoring Standard

Version: 0.2.1 | Status: normative | Phase: test


1. Summary

[RFC-0008:C-OVERVIEW] Overview (Informative)

This RFC defines the skill authoring standard as a set of configurable lint rules that skc lint applies to skill directories.

Design:

  • Each rule has a unique identifier (SKLxxx)
  • Rules are grouped by category (frontmatter, structure, links, files)
  • Rules produce diagnostic output per RFC-0005
  • Rules will be configurable in a future version (see RFC-0008:C-EXTENSIONS)

Rule categories:

  • SKL1xx: Frontmatter validation rules
  • SKL2xx: Structure and content rules
  • SKL3xx: Link validation rules
  • SKL4xx: File organization rules

Relationship to other RFCs:

  • RFC-0001 defines compilation requirements; this RFC extends with quality validation
  • RFC-0005 defines diagnostic output format; rules map to diagnostic codes

Since: v0.1.0


2. Specification

[RFC-0008:C-REGISTRY] Rule Registry (Normative)

This clause defines all lint rules. Each rule has an ID, name, default severity, and description.

Frontmatter Definition

SKILL.md frontmatter is a YAML block delimited by --- lines:

  • The file MUST begin with a line containing exactly ---
  • The frontmatter ends at the next line containing exactly ---
  • Content between the delimiters is parsed as YAML

Frontmatter validation is handled by rule SKL100.

Rule Summary

Rule IDNameDefaultCategory
SKL001skip-compiledn/aMeta
SKL100frontmatter-validerrorFrontmatter
SKL101name-requirederrorFrontmatter
SKL102name-formaterrorFrontmatter
SKL103name-lengtherrorFrontmatter
SKL104name-match-dirwarningFrontmatter
SKL105description-requirederrorFrontmatter
SKL106description-nonemptyerrorFrontmatter
SKL107description-lengthwarningFrontmatter
SKL108description-triggerswarningFrontmatter
SKL109frontmatter-knownwarningFrontmatter
SKL201skill-sizewarningStructure
SKL202heading-h1warningStructure
SKL203heading-match-namewarningStructure
SKL204heading-first-h1warningStructure
SKL205heading-hierarchywarningStructure
SKL301link-file-existserrorLinks
SKL302link-anchor-existswarningLinks
SKL303link-no-escapeerrorLinks
SKL401no-orphanswarningFiles

Meta Rules (SKL0xx)

SKL001: skip-compiled

Skip linting for compiled skills (detected by .skillc-meta/manifest.json).

Default behavior: enabled (compiled skills are skipped)

When a compiled skill is detected and this rule is enabled:

  1. The linter prints: info: skipping compiled skill '<name>'
  2. Exits with code 0 (success)

When --force is used, this rule is disabled and:

  1. The linter emits: warning[W300]: SKL001 skip-compiled: linting compiled skill; results may not be meaningful
  2. Applies all other rules normally

Configurability: Unlike other rules, SKL001 is controlled by --force, not by rule configuration. Future versions MAY allow disabling it via config.

Rationale: Compiled skills are derived artifacts. Their generated stub differs from source content.


Frontmatter Rules (SKL1xx)

SKL100: frontmatter-valid

SKILL.md MUST have valid frontmatter delimiters and parseable YAML.

Default severity: error

Requirements:

  • File MUST begin with a line containing exactly ---
  • A second --- line MUST appear to close the frontmatter
  • Content between delimiters MUST be valid YAML

Error messages:

  • Missing opening delimiter: missing frontmatter: file does not start with ---
  • Missing closing delimiter: missing frontmatter: no closing --- found
  • YAML parse error: invalid frontmatter YAML: <parse-error>

SKL101: name-required

The name field MUST be present in SKILL.md frontmatter.

Default severity: error

SKL102: name-format

The name field MUST contain only lowercase ASCII letters (a-z), digits (0-9), and hyphens (-). It MUST NOT start or end with a hyphen.

Default severity: error

Valid: my-skill, skill123, a Invalid: My-Skill (uppercase), -skill (leading hyphen), skill_name (underscore)

SKL103: name-length

The name field MUST be 1-64 characters in length.

Default severity: error

SKL104: name-match-dir

The name field SHOULD match the skill directory name.

Default severity: warning

SKL105: description-required

The description field MUST be present in SKILL.md frontmatter.

Default severity: error

SKL106: description-nonempty

The description field MUST NOT be empty or whitespace-only.

Default severity: error

SKL107: description-length

The description field SHOULD be at most 1024 characters.

Default severity: warning

SKL108: description-triggers

The description field SHOULD include activation triggers.

Default severity: warning

Detection: The rule checks for presence of any of these English patterns (case-insensitive):

  • use when
  • when to use
  • use for
  • triggers on
  • triggers:
  • activate when

Note: This rule is designed for English-language skills. Non-English skills may disable this rule via configuration (future).

SKL109: frontmatter-known

Frontmatter fields SHOULD be from the known set.

Default severity: warning

Known fields:

  • name (required)
  • description (required)
  • allowed-tools (optional, implementation-defined behavior)

Unknown fields trigger a warning. This helps catch typos and misunderstandings of the schema.

Note on allowed-tools: This field is recognized by some agent implementations to restrict available tools. Its format and semantics are implementation-defined. Future versions MAY add validation rules for this field.


Structure Rules (SKL2xx)

SKL201: skill-size

SKILL.md SHOULD be at most 500 lines.

Default severity: warning

SKL202: heading-h1

SKILL.md SHOULD contain at least one H1 (#) heading.

Default severity: warning

SKL203: heading-match-name

The first H1 heading in SKILL.md SHOULD match or contain the skill name.

Default severity: warning

Matching: Case-insensitive comparison. The heading may contain additional text (e.g., heading “My Skill Guide” matches name “my-skill” if “my-skill” appears as a substring after normalizing hyphens to spaces).

SKL204: heading-first-h1

The first heading in each markdown file SHOULD be an H1 (#).

Default severity: warning

Scope: Applies to all .md files in the skill directory.

Rationale: The first heading establishes the document title. Starting with H2 or lower suggests missing context.

Since: v0.2.0

SKL205: heading-hierarchy

Headings SHOULD NOT skip levels when going deeper.

Default severity: warning

Scope: Applies to all .md files in the skill directory.

Requirements:

  • When increasing heading depth, levels MUST NOT be skipped (H2→H4 is invalid; H2→H3 is valid)
  • Decreasing depth is always allowed (H3→H2, H4→H1 are valid)

Examples:

  • Valid: # Title## Section### Subsection## Another Section
  • Invalid: # Title### Subsection (skipped H2)
  • Invalid: ## Section#### Deep (skipped H3)

Rationale: Skipped heading levels break document outline semantics and can cause accessibility issues.

Since: v0.2.0


Internal markdown file links MUST resolve to existing files within the skill directory.

Default severity: error

Scope: Relative links like [text](path/to/file.md). Absolute paths and external URLs are not checked.

Internal markdown anchor links SHOULD resolve to existing headings.

Default severity: warning

Anchor normalization: GitHub-style slugging for ASCII:

  1. Convert to lowercase
  2. Remove characters except a-z, 0-9, spaces, hyphens
  3. Replace spaces with hyphens
  4. Collapse consecutive hyphens

Non-ASCII characters are removed. For duplicate headings, anchors are suffixed: #heading, #heading-1.

Links MUST NOT escape the skill root directory via .. traversal.

Default severity: error


File Rules (SKL4xx)

SKL401: no-orphans

Markdown files in the skill directory SHOULD be reachable from SKILL.md via link traversal.

Default severity: warning

Definition: A file is orphaned if it is not SKILL.md and is not reachable via links starting from SKILL.md (transitive closure).

Exceptions: Not considered orphaned:

  • Files in hidden directories (starting with .)
  • Common non-content files: LICENSE.md, CHANGELOG.md, CONTRIBUTING.md, README.md

Since: v0.1.0

[RFC-0008:C-SCOPE] Lint Scope (Normative)

This clause defines what files the linter scans.

File Scanning

The linter scans all .md files in the skill directory, excluding:

  • Files in directories starting with . (e.g., .git/, .skillc-meta/, .github/)
  • Files whose names start with .

This is consistent with RFC-0001 compilation behavior.

Compiled Skill Detection

Compiled skill handling is defined by rule SKL001 in RFC-0008:C-REGISTRY.

Detection: A skill is compiled if .skillc-meta/manifest.json exists.

SKILL.md Requirement

The linter requires SKILL.md to exist. If missing, the linter exits with E010 per RFC-0005:C-CODES.

Frontmatter Requirement

Frontmatter validation is handled by rule SKL100 in RFC-0008:C-REGISTRY. Invalid frontmatter produces E300 (lint error), not E010.

Since: v0.1.0

[RFC-0008:C-DIAGNOSTICS] Diagnostic Output (Normative)

This clause defines how lint rules produce diagnostic output.

Output Format

All lint diagnostics use the format defined in RFC-0005:C-CODES:

<severity>[<code>]: <rule-id> <rule-name>: <message>

Components:

  • <severity>: error or warning
  • <code>: E300 for errors, W300 for warnings
  • <rule-id>: The rule identifier (e.g., SKL102)
  • <rule-name>: The rule name (e.g., name-format)
  • <message>: Human-readable description of the violation

Examples:

error[E300]: SKL102 name-format: name 'My-Skill' contains uppercase characters
error[E300]: SKL301 link-file-exists: link target not found: 'references/missing.md'
warning[W300]: SKL104 name-match-dir: name 'foo' does not match directory 'bar'
warning[W300]: SKL401 no-orphans: orphaned file: 'old-notes.md'

Rule Severity Mapping

Each rule has a default severity (error or warning) defined in RFC-0008:C-REGISTRY.

Default SeverityDiagnostic Code
errorE300
warningW300

Exit Behavior

  • If any rule with error severity is violated: exit with status 1
  • If only warning-severity rules are violated: exit with status 0
  • If no violations: exit with status 0

Machine-Readable Output

Future versions MAY support structured output formats (JSON, SARIF) for tooling integration. See RFC-0008:C-EXTENSIONS.

Since: v0.1.0

[RFC-0008:C-REFERENCE-FRONTMATTER] Reference File Frontmatter (Informative)

Non-SKILL.md markdown files (reference documents) MAY contain optional YAML frontmatter.

Frontmatter Format

Reference files MAY begin with a YAML frontmatter block:

---
description: "Brief description of this reference document"
---

# Reference Title

Content here...

Supported Fields

FieldRequiredDescription
descriptionNoBrief description displayed in compiled stub

Field Constraints

description:

  • Optional (no lint warning if absent)
  • Should be ≤120 characters for optimal display
  • Longer descriptions are truncated with in the stub
  • Used by the compiler per RFC-0001:C-SECTIONS

Differences from SKILL.md Frontmatter

Reference file frontmatter differs from SKILL.md frontmatter:

AspectSKILL.mdReference files
RequiredYesNo
name fieldRequiredNot used
description fieldRequiredOptional
LintingFull validationNo validation

Example

A reference file references/clap-patterns.md:

---
description: "Advanced clap argument parsing patterns"
---

# Clap Patterns

## Value Enums
...

This description appears in the compiled stub:

- References
  - Clap Patterns — Advanced clap argument parsing patterns

Since: v0.2.0


3. Extensions

[RFC-0008:C-EXTENSIONS] Future Extensions (Informative)

This clause describes planned future extensions. These are NOT part of v0.2.0.

Configurable Rules (Future)

A future version MAY support rule configuration via .skilllint.toml:

# Example future configuration (not implemented)
[rules]
SKL107 = "off"                    # Disable description length check
SKL201 = { max-lines = 300 }      # Custom threshold
SKL108 = "error"                  # Upgrade warning to error

Design considerations:

  • Configuration file location: skill root or global ~/.config/skillc/
  • Per-rule enable/disable
  • Severity override (error ↔ warning ↔ off)
  • Rule-specific parameters (thresholds, patterns)

Inline Directives (Future)

A future version MAY support inline directives to suppress warnings:

<!-- skilllint-disable SKL201 -->
[large content here]
<!-- skilllint-enable SKL201 -->

Or single-line suppression:

[very long line] <!-- skilllint-disable-line SKL... -->

Structured Output (Future)

A future version MAY support machine-readable output:

  • --format=json — JSON array of violations
  • --format=sarif — SARIF format for IDE integration

Additional Rules (Future)

Potential future rules:

  • SKL110: allowed-tools-known — warn on unrecognized tool names
  • SKL206: code-block-language — code blocks should have language tags
  • SKL207: line-length — lines should not exceed threshold

Note: These extensions are documented for planning. They are out of scope for v0.2.0.

Since: v0.1.0


Changelog

v0.2.1 (2026-01-31)

Add C-REFERENCE-FRONTMATTER for optional description in reference files

v0.2.0 (2026-01-31)

Normalize SKL204, SKL205

v0.1.0 (2026-01-30)

Initial release

RFC-0009: Configuration

Version: 0.2.0 | Status: normative | Phase: test


1. Summary

[RFC-0009:C-OVERVIEW] Overview (Informative)

skillc supports optional configuration files at two levels:

  • Global: ~/.skillc/config.toml — user-wide preferences
  • Project: .skillc/config.toml — project-specific overrides

Configuration is minimal by design. Most behavior is convention-based with CLI overrides for per-invocation choices. Config files are reserved for true preferences that rarely change but need project-level control.

v0.1.0 Scope:

  • Tokenizer preference for search indexing (ASCII vs CJK)

Future Extensions (planned):

Since: v0.1.0


2. Specification

[RFC-0009:C-FILES] Configuration Files (Normative)

File Locations

skillc MUST check for configuration files in these locations:

ScopePathPurpose
Global~/.skillc/config.tomlUser-wide preferences
Project.skillc/config.tomlProject-specific overrides

File Format

Configuration files MUST use TOML format.

Configuration files MAY be empty or omit any section. Missing values use defaults per RFC-0009:C-RESOLUTION.

Schema

# Schema version (optional, default: 1)
version = 1

[search]
# Tokenizer for search indexing: "ascii" (default) or "cjk"
tokenizer = "ascii"

# Reserved for future use
# [lint]
# rules = { ... }

Version Handling

The version field is OPTIONAL. If omitted, version 1 is assumed.

Compatibility rules:

  • Version 1 is the only supported version in v0.1.0
  • If version is present and greater than the supported version, skillc MUST emit a warning and proceed using only recognized fields
  • If version is present and not a positive integer, skillc MUST emit an error and ignore the entire config file (proceed as if it does not exist)

Unknown Keys

Unknown keys and sections MUST be ignored with a warning. This enables forward compatibility when older skillc versions read configs written for newer versions.

Since: v0.1.0

[RFC-0009:C-RESOLUTION] Resolution Order (Normative)

When resolving a configuration value, skillc MUST apply this precedence order (highest first):

  1. CLI flags — explicit per-invocation override
  2. Environment variables — process-level override (see below)
  3. Project config.skillc/config.toml in current directory or ancestors
  4. Global config~/.skillc/config.toml
  5. Built-in defaults — hardcoded fallback values

Project Config Discovery

skillc MUST search for .skillc/config.toml starting from the current working directory and walking up to filesystem root. The first config file found is used.

If no project config is found, only global config and defaults apply.

Merging Behavior

Resolution is per-key, not per-file. For each setting:

  • If project config specifies a value, use it
  • Otherwise, if global config specifies a value, use it
  • Otherwise, use the built-in default

Settings not specified in a config file do not override lower-precedence values.

Environment Variables (v0.1.0)

Only the following environment variables are defined in v0.1.0:

VariableOverridesValid Values
SKILLC_TOKENIZER[search].tokenizerascii, cjk

If an environment variable is set to an invalid value, skillc MUST emit a warning and ignore the variable (fall through to next precedence level).

Additional environment variables MAY be added in future versions.

Since: v0.1.0

[RFC-0009:C-TOKENIZER] Tokenizer Setting (Normative)

The [search].tokenizer setting controls how text is tokenized for the search index per RFC-0004:C-INDEX.

Values

ValueBehaviorUse Case
asciiSplit on whitespace and punctuationEnglish and space-delimited languages (default)
cjkCharacter-level tokenization with ASCII fallbackChinese, Japanese, Korean content

Default

If not specified, the tokenizer MUST default to ascii.

Effect on Index

Changing the tokenizer setting invalidates existing search indexes. The search command MUST detect tokenizer mismatch and prompt for rebuild per RFC-0004:C-INDEX.

Since: v0.1.0

[RFC-0009:C-ENV-OVERRIDE] Environment Variable Override (Normative)

The SKILLC_HOME environment variable, if set, MUST override the default home directory detection for all global paths.

When SKILLC_HOME is set to a path (e.g., /custom/home):

  • global_skillc_dir() MUST return $SKILLC_HOME/.skillc/ (e.g., /custom/home/.skillc/)
  • All derived paths (global source store, global runtime, etc.) MUST use this base
  • find_project_root() MUST exclude $SKILLC_HOME from project root detection

When SKILLC_HOME is not set:

  • The implementation MUST fall back to dirs::home_dir() behavior

Rationale: This enables:

  1. Cross-platform test isolation (HOME env var only works on Unix)
  2. Custom installation locations
  3. Portable/relocatable installations

Since: v0.2.0


Changelog

v0.2.0 (2026-01-31)

Add SKILLC_HOME override

v0.1.0 (2026-01-30)

Initial release

ADR-0001: Storage Layout

Status: accepted | Date: 2026-01-26

References: RFC-0001

Context

skillc needs to store skill-related files in two locations:

  1. Source files — where skill authors write and edit content
  2. Runtime files — where agents discover and consume compiled skills

These locations must be:

  • Predictable (so skillc can find them without configuration)
  • Non-conflicting (source and runtime are separate concerns)
  • Compatible with existing Agent Skills tooling (Claude Code, Cursor, etc.)

The runtime location is particularly constrained: agents look for skills in specific directories based on their host environment.

Decision

We adopt a two-tier configuration system:

Global configuration: ~/.skillc/config.toml

  • Default source store: ~/.skillc/src/
  • Default runtime store: ~/.claude/skills/
  • Registry: ~/.skillc/registry.json

Project configuration: ./.skillc/config.toml (in project root)

  • Overrides global defaults when present
  • Typical runtime store: ./.claude/skills/ or ./.skills/
  • Enables project-local skills versioned with the repository

Resolution order (highest priority first):

  1. Project source store (./.skillc/skills/)
  2. Global source store (~/.skillc/skills/)

Note: CLI flags and environment variables for overriding source/runtime directories were removed in v0.1.0 to simplify the design. Direct paths can be imported via skc build <path> which copies to the appropriate source store.

Registry scope:

  • Global registry tracks globally-installed skills
  • Project skills are discovered by scanning project config, not stored in global registry

This mirrors Claude Code’s model of global vs project-local skills.

Consequences

Positive:

  • Matches mental model of global vs project-local (like Claude Code)
  • Project skills can be version-controlled with the repository
  • Flexible for different agent environments via config
  • Clear precedence rules prevent confusion

Negative:

  • Two config files to potentially manage
  • Project detection logic needed (find .skillc/config.toml upward)
  • Registry now only covers global skills; project skills discovered differently

Trade-offs accepted:

  • Complexity of layered config is justified by flexibility gained
  • Project skills not in global registry is intentional (they belong to the project)

ADR-0002: Multi-Target Build Output

Status: accepted | Date: 2026-01-29

References: ADR-0001, RFC-0001

Context

Context

The current build system writes compiled skills directly to ~/.claude/skills/, which has several problems:

Problem Statement

  1. Data destruction risk: If a user has hand-crafted skills in ~/.claude/skills/rust/, running skc build rust overwrites them without warning or backup.

  2. Single-target limitation: The build output is hardcoded to Claude’s skill directory. Other AI coding assistants (Cursor, Kiro, OpenCode, Copilot, etc.) have their own skill directories.

  3. No canonical source location: Skills can be built from anywhere, making it hard to track what skills exist and where their sources are.

Constraints

  • ADR-0001 defines a layered configuration system with global and project-level overrides
  • RFC-0001 specifies compilation output format (SKILL.md + manifest)
  • Backward compatibility with existing users who expect skc build to “just work”

Options Considered

  1. Keep current design — Accept data loss risk, single-target only
  2. Add backup before overwrite — Reduces risk but doesn’t solve multi-target
  3. Separate source from target — skillc manages source, deploys to targets

Decision

Decision

We adopt a source/target separation model:

Source Resolution (where to find skill source)

Resolution order (highest priority first):

  1. ./.skillc/skills/<skill>/ — Project-local source (recursive-up search)
  2. ~/.skillc/skills/<skill>/ — Global source

Note: Direct paths can be provided to skc build, which imports them to the appropriate source store before building. Use --force to overwrite existing skills during import.

Target Selection (where to write compiled output)

The --target <platform> flag selects the output directory:

skc build rust                    # --target defaults to "claude"
skc build rust --target cursor    # Output to cursor skill dir
skc build rust --target kiro      # Output to kiro skill dir

Target Registry

Target paths are configured in ~/.skillc/config.toml:

[targets]
claude = "~/.claude/skills"
cursor = "~/.cursor/skills"
# Additional targets can be added by user

Built-in defaults are provided for known platforms. Users can override or add custom targets.

Implementation Notes

  1. The --target flag defaults to claude for backward compatibility
  2. Unknown target names are errors (must be configured first)
  3. Build output structure remains unchanged per RFC-0001:C-OUTPUT

Consequences

Consequences

Positive

  • No data destruction: skillc never overwrites user’s hand-crafted skills; it writes to its own source directory
  • Multi-platform support: Same skill source can be deployed to multiple AI assistants
  • Canonical source location: ~/.skillc/skills/ becomes the single source of truth for skillc-managed skills
  • Extensible: New platforms can be added via config without code changes

Negative

  • Migration required: Existing users must move skills to ~/.skillc/skills/ or use skc build <path> to import
  • Additional config: Target registry adds configuration surface area
  • Two-step mental model: Users must understand source vs target distinction

Trade-offs Accepted

  • Complexity of source resolution order is justified by flexibility gained
  • Default to claude target maintains backward compatibility for most users
  • Requiring explicit target configuration for new platforms is safer than guessing paths

Alternatives Considered

  • Keep current design: Accept data loss risk and single-target limitation. Rejected because it violates user trust.
  • Backup before overwrite: Create backup of existing skills before writing. Partial solution - doesn’t address multi-target need.

ADR-0003: MCP as Primary Agent Interface

Status: accepted | Date: 2026-01-29

References: RFC-0002, RFC-0003, RFC-0004

Context

Context

AI coding agents interact with skillc through the CLI via the Shell tool. This architecture has fundamental limitations:

Problem Statement

  1. Sandbox restrictions: Many AI IDEs (Cursor, Claude Desktop) sandbox Shell tool execution. This blocks writes to global directories like ~/.claude/skills/<skill>/.skillc-meta/logs.db.

  2. Workaround complexity: RFC-0007:C-LOGGING specifies a fallback mechanism (write locally, then skc sync), but this requires manual user intervention and adds cognitive overhead.

  3. Interface mismatch: CLI is designed for humans (text parsing, exit codes). Agents benefit from structured data (JSON) and native tool integration.

  4. Performance overhead: Each CLI invocation spawns a shell process, adding latency.

Constraints

  • CLI must remain for human users and automation scripts
  • MCP is the standard agent integration protocol
  • Existing CLI behavior must not regress

Options Considered

  1. Keep CLI-only: Accept sandbox limitations, rely on fallback + sync
  2. MCP for logging only: Add MCP server just for log writes
  3. Full MCP interface: Expose all skillc operations as MCP tools

Decision

Decision

We adopt MCP as the primary agent interface:

Architecture

Human users:  Terminal → skc CLI → skillc core
AI agents:    MCP client → skillc MCP server → skillc core

The MCP server exposes tools that mirror CLI commands:

MCP ToolCLI EquivalentDescription
skc_outlineskc outline <skill>List skill sections
skc_showskc show <skill> [section]Display skill content
skc_openskc open <skill>Open skill in editor
skc_searchskc search <query>Search across skills
skc_statsskc stats [options]Usage analytics
skc_buildskc build <skill>Compile skill
skc_syncskc syncSync local logs
skc_sourcesskc sources <skill>List source files

Key Design Points

  1. MCP server runs outside sandbox: No filesystem restrictions
  2. Structured I/O: JSON input/output instead of text parsing
  3. Same core logic: CLI and MCP share implementation
  4. Logging works naturally: MCP server writes directly to global db

Deployment

The MCP server is registered in the agent’s MCP configuration:

{
  "mcpServers": {
    "skillc": {
      "command": "skc",
      "args": ["mcp"]
    }
  }
}

Consequences

Consequences

Positive

  • No sandbox issues: MCP server has full filesystem access
  • Native agent integration: MCP is the designed protocol for agent tools
  • Structured data: JSON eliminates text parsing errors
  • Reduced latency: No shell spawn overhead per command
  • Simplified logging: No fallback + sync dance needed for agents

Negative

  • Two interfaces to maintain: CLI and MCP must stay in sync
  • MCP server complexity: New component to build and test
  • Setup required: Users must configure MCP server in their IDE
  • CLI fallback still needed: For humans and non-MCP environments

Trade-offs Accepted

  • Implementation cost of MCP server is justified by UX improvement
  • Keeping CLI + MCP means more code, but serves distinct user populations
  • RFC-0007:C-LOGGING fallback mechanism remains for CLI users in sandboxed environments

Alternatives Considered

  • Keep CLI-only: Accept sandbox limitations. Rejected because it degrades agent UX and requires manual sync.
  • MCP for logging only: Partial solution. Rejected because other operations also benefit from MCP.

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

[0.2.1] - 2026-02-07

Fixed

  • Index-based section extraction now correctlyignores headings inside code blocks (WI-2026-02-02-001)

[0.2.0] - 2026-01-31

Added

  • SKL204 heading-first-h1 lint rule per RFC-0008:C-REGISTRY (WI-2026-01-31-003)
  • SKL205 heading-hierarchy lint rule per RFC-0008:C-REGISTRY (WI-2026-01-31-003)
  • Parse optional description from reference file frontmatter (WI-2026-01-31-004)
  • Display description inline with em-dash in stub References section (WI-2026-01-31-004)
  • Truncate descriptions longer than 120 chars with ellipsis (WI-2026-01-31-004)
  • Headings table added to search index database (WI-2026-01-31-005)
  • skc show uses index-based lookup instead of runtime parsing (WI-2026-01-31-005)
  • Em-dash suffix stripping for section queries (WI-2026-01-31-005)
  • Suggestions on section not found (WI-2026-01-31-005)

Changed

  • Stub section listing per RFC-0001:C-SECTIONS - SKILL.md shows H1 and H2 only, other files show H1/filename with optional description (WI-2026-01-31-003)
  • RFC-0004 C-INDEX updated with headings table schema (WI-2026-01-31-005)
  • RFC-0002 C-SHOW updated with lookup behavior (WI-2026-01-31-005)

[0.1.1] - 2026-01-31

Added

  • SKILLC_HOME env var overrides home directory detection (WI-2026-01-31-001)

Fixed

  • MCP lint/build use resolve_skill() (WI-2026-01-31-002)

[0.1.0] - 2026-01-30

Added

  • RFC-0000 defines skillc vision aligned with Agent Skills ecosystem (WI-2026-01-25-001)
  • RFC-0000 includes normative compatibility guarantees (format, offline, portability) (WI-2026-01-25-001)
  • RFC-0001 specifies stub output format (WI-2026-01-25-002)
  • RFC-0001 specifies manifest structure (WI-2026-01-25-002)
  • RFC-0001 defines compilation constraints (WI-2026-01-25-002)
  • Compiler accepts valid Agent Skills directory (WI-2026-01-26-001)
  • Compiler produces stub SKILL.md per RFC-0001:C-STUB (WI-2026-01-26-001)
  • Compiler produces manifest.json per RFC-0001:C-MANIFEST (WI-2026-01-26-001)
  • skc build CLI command works (WI-2026-01-26-001)
  • Implement skc outline command per RFC-0002:C-OUTLINE (WI-2026-01-26-002)
  • Implement skc show command per RFC-0002:C-SHOW (WI-2026-01-26-002)
  • Implement skc open command per RFC-0002:C-OPEN (WI-2026-01-26-002)
  • Implement access logging per RFC-0007:C-LOGGING (WI-2026-01-26-002)
  • Implement skill resolution per RFC-0007:C-RESOLUTION (WI-2026-01-26-002)
  • Implement stats analytics queries per RFC-0003 (WI-2026-01-26-003)
  • Support filters and JSON output schema (WI-2026-01-26-003)
  • CLI integration test harness with snapshots (WI-2026-01-27-001)
  • Integration coverage for gateway and stats commands (WI-2026-01-27-001)
  • Draft RFC-0004 Search Protocol (WI-2026-01-28-001)
  • Create RFC-0005 Error Code Registry (WI-2026-01-28-002)
  • Define canonical error code table (WI-2026-01-28-002)
  • Migrate RFC-0004 C-ERRORS to reference RFC-0005 (WI-2026-01-28-002)
  • Build centralized error code registry in error.rs (WI-2026-01-29-001)
  • Migrate all commands to use canonical error messages per RFC-0005:C-CODES (WI-2026-01-29-001)
  • Implement skc search command with FTS5 index (WI-2026-01-29-003)
  • Build search index during skc build per RFC-0004:C-INDEX (WI-2026-01-29-003)
  • Support .md and .txt file formats per RFC-0004:C-FORMATS (WI-2026-01-29-003)
  • E999 added to RFC-0005 for internal errors (WI-2026-01-29-007)
  • SKC_VERBOSE/-v flag for debug output (WI-2026-01-29-008)
  • CLI examples in –help output (WI-2026-01-29-008)
  • CONTRIBUTING.md documentation (WI-2026-01-29-008)
  • Pass verbose flag through to library functions (WI-2026-01-29-009)
  • Verbose output shows resolved paths for skill resolution (WI-2026-01-29-009)
  • Verbose output shows timing information for operations (WI-2026-01-29-009)
  • skc sources command with tree-style output (WI-2026-01-29-011)
  • --depth, --dir, --limit, --pattern options (WI-2026-01-29-011)
  • Amend RFC-0007:C-LOGGING with fallback logging for sandboxed environments (WI-2026-01-29-012)
  • Add RFC-0007:C-SYNC clause for sync command (WI-2026-01-29-012)
  • Implement fallback logging to workspace when primary fails (WI-2026-01-29-012)
  • Implement skc sync command to merge local logs to global (WI-2026-01-29-012)
  • Stale fallback warning when local logs >1 hour old (WI-2026-01-29-014)
  • ADR-0002 Multi-Target Build Output drafted and accepted (WI-2026-01-29-017)
  • ADR-0003 MCP as Primary Agent Interface drafted and accepted (WI-2026-01-29-017)
  • C-MCP-OVERVIEW clause for MCP interface overview (WI-2026-01-29-019)
  • C-MCP-SERVER clause for server specification (WI-2026-01-29-019)
  • C-MCP-TOOLS clause for tool specifications (WI-2026-01-29-019)
  • --target flag for build command (default: claude) (WI-2026-01-29-020)
  • Target registry in config with built-in defaults (WI-2026-01-29-020)
  • skc mcp command for MCP server (WI-2026-01-29-021)
  • MCP tools: skc_outline, skc_show, skc_open, skc_sources, skc_search, skc_stats, skc_build, skc_sync (WI-2026-01-29-021)
  • Add missing optional params to MCP tools (WI-2026-01-29-022)
  • Create RFC-0007 CLI Reference (WI-2026-01-29-023)
  • Add C-INIT to RFC-0006 for init command (WI-2026-01-29-023)
  • skc init creates .skillc/ project structure (WI-2026-01-29-024)
  • skc init <name> creates project-local skill (WI-2026-01-29-024)
  • skc init <name> --global creates global skill (WI-2026-01-29-024)
  • RFC-0005 amended with warning code specification (WI-2026-01-29-026)
  • Warning codes W001-W003 defined for existing warnings (WI-2026-01-29-026)
  • Warning infrastructure in error.rs (WI-2026-01-29-026)
  • Implement skc lint command per RFC-0008 (WI-2026-01-29-027)
  • Implement SKL1xx frontmatter rules (WI-2026-01-29-027)
  • Implement SKL2xx structure rules (WI-2026-01-29-027)
  • Implement SKL3xx link rules (WI-2026-01-29-027)
  • Implement SKL4xx file rules (WI-2026-01-29-027)
  • Implement skc_init MCP tool (WI-2026-01-30-001)
  • Implement skc_lint MCP tool (WI-2026-01-30-001)
  • Local source compiles to .skillc/runtime/ (SSOT) and symlinks to agent directory (WI-2026-01-30-005)
  • –global flag compiles to ~/.skillc/runtime/ (global SSOT) (WI-2026-01-30-005)
  • –target flag specifies which agents to deploy to (default: claude) (WI-2026-01-30-005)
  • –copy flag forces copy instead of symlink/junction (WI-2026-01-30-005)
  • Cross-platform support: symlink (Unix), junction/copy fallback (Windows) (WI-2026-01-30-005)
  • Unit tests for deploy.rs and integration tests for build command (WI-2026-01-30-005)
  • Config file parsing for global and project configs (WI-2026-01-30-006)
  • Tokenizer preference setting (ascii/cjk) (WI-2026-01-30-006)
  • Import flow for direct paths (copy to .skillc/skills/) (WI-2026-01-30-007)
  • –force flag for overwriting during import (WI-2026-01-30-007)
  • Recursive-up project detection for skill lookup (WI-2026-01-30-007)
  • Enhanced build output showing Source/Runtime/Deploy with scope labels (WI-2026-01-30-007)
  • CLI list command with text output (WI-2026-01-30-008)
  • MCP skc_list tool with JSON output (WI-2026-01-30-008)
  • Skill discovery from project and global source stores (WI-2026-01-30-008)
  • Status detection (normal, not-built, stale) (WI-2026-01-30-008)
  • Filtering by scope, status, limit, pattern (WI-2026-01-30-008)
  • Short flags for common options (-g, -f, -o, -t, -l, -p) (WI-2026-01-30-009)
  • Colored output using comfy-table (WI-2026-01-30-009)
  • Document list command in README (WI-2026-01-30-011)
  • Integration tests for lint command (WI-2026-01-30-012)
  • Integration tests for list command (WI-2026-01-30-012)
  • skc stats --group-by search returns search query breakdown (WI-2026-01-30-013)
  • skc outline --level <n> filters headings by level (WI-2026-01-30-013)
  • skc show --max-lines <n> limits output lines (WI-2026-01-30-013)
  • skc open --max-lines <n> limits output lines (WI-2026-01-30-013)

Changed

  • Error messages include error codes (e.g., error[E001]: …) (WI-2026-01-29-007)
  • Sync always deletes local logs after successful upload (remove –purge option) (WI-2026-01-29-014)
  • Partial failure handling - delete what synced successfully (WI-2026-01-29-014)
  • RFC-0001:C-STUB updated to include MCP preference statement (WI-2026-01-29-018)
  • C-OVERVIEW updated to mention MCP (WI-2026-01-29-019)
  • Source resolution uses ~/.skillc/skills/ instead of ~/.skillc/src/ (WI-2026-01-29-020)
  • Move C-COMMANDS from RFC-0002 to RFC-0007 (WI-2026-01-29-023)
  • Move C-MCP-OVERVIEW from RFC-0002 to RFC-0007 (WI-2026-01-29-023)
  • Move C-MCP-SERVER from RFC-0002 to RFC-0007 (WI-2026-01-29-023)
  • Move C-RESOLUTION from RFC-0002 to RFC-0007 (WI-2026-01-29-023)
  • Move C-LOGGING from RFC-0002 to RFC-0007 (WI-2026-01-29-023)
  • Move C-SYNC from RFC-0002 to RFC-0007 (WI-2026-01-29-023)
  • Remove –source-dir and –runtime-dir CLI flags (WI-2026-01-30-007)
  • Remove SKILLC_SOURCE and SKILLC_RUNTIME env var support (WI-2026-01-30-007)
  • Remove RFC references from CLI help text (WI-2026-01-30-009)
  • Replace regex link extraction with pulldown-cmark AST (WI-2026-01-30-010)

Removed

  • Remove skc_sync from MCP (CLI-only per RFC) (WI-2026-01-29-022)

Fixed

  • Resolver checks runtime store as fallback (WI-2026-01-29-005)
  • Error message for invalid project path should be descriptive (WI-2026-01-29-006)
  • InvalidPath error shows descriptive message (WI-2026-01-29-007)
  • Clippy collapsible if warning in tests/common/mod.rs (WI-2026-01-29-008)
  • Source hash is deterministic across rebuilds (excludes .git/.jj directories) (WI-2026-01-29-010)
  • Init creates non-empty description per RFC-0001 (WI-2026-01-29-025)
  • Compiler rejects symlinks escaping skill root per RFC-0001 (WI-2026-01-29-025)
  • Enforce 100-line stub size limit per RFC-0001:C-CONSTRAINTS (WI-2026-01-30-002)
  • Complete staleness check per RFC-0004:C-INDEX (WI-2026-01-30-002)
  • Status filter documentation (stale -> obsolete) (WI-2026-01-30-009)
  • Linter SKL301 no longer flags links inside code blocks (WI-2026-01-30-010)
  • Linter SKL301 no longer flags links inside inline code (WI-2026-01-30-010)
  • Correct storage path from ~/.skillc/src/ to ~/.skillc/skills/ (WI-2026-01-30-011)

Security

  • Add cargo-deny configuration for dependency auditing (WI-2026-01-29-008)