README
¶
Skillex
Skill management for AI agents in polyglot projects.
Skillex solves the problem of agent skill discovery in monorepos and dependency-heavy projects. It gives agents exactly the skills they need — versioned, scoped, instantly queryable — without polluting their context window with irrelevant documentation.
Packs make that model extensible beyond a single ecosystem. Projects, packages,
Go modules, and future ecosystem integrations can ship a skillex/pack.yaml
manifest that activates the right skills when Skillex sees matching files,
dependencies, or detector values.
The problem
Modern agent workflows depend on "skills": Markdown documents that teach agents how to use packages, follow repo conventions, handle migrations, and work safely in a codebase. As projects grow, skill management breaks down:
- Skills differ by package version — the right guidance for
@acme/foo@2is wrong for v1. - Monorepos may have different versions of the same package in different workspaces.
- The same package name may exist at multiple installed versions in one repo, and the correct answer depends on the active dependency boundary.
- Similar prompts collide across packages and versions. "Add a CTA button" is not enough unless the agent knows which app, which router, and which installed package API is in scope.
- Loading all skills upfront wastes context window. Agents get everything or nothing.
- Skills scattered across docs folders require agents to browse multiple files to find what they need.
This is not just an authoring problem. It is a retrieval problem.
File-crawled skill systems can represent package skills, project skills, path activation, and version metadata, but they still push a lot of work onto the agent:
- Discover the relevant skill catalogs.
- Load metadata for many possible skills into context.
- Decide which paths, versions, and package docs apply.
- Avoid pulling in near-miss guidance for sibling apps or different installed versions.
That approach is workable when the skill surface is small. As adoption grows, the retrieval overhead starts competing with the actual task.
Skillex covers the full lifecycle: authoring, indexing, and retrieving exactly the right skills on demand — in a single query, in microseconds.
How it works
Your repo Agent
───────────────────────────── ──────────────────────────────
skillex.json 1. "What skills apply to
skills/repo.md packages/app-a/src/auth.ts?"
packages/app-a/
package.json 2. skillex query
node_modules/ --path packages/app-a/src/auth.ts
@acme/foo/
skillex/ 3. Returns: repo.md + @acme/foo
public/consumer.md consumer.md + auth.md
public/auth.md (correct version, scoped)
private/internals.md
4. Agent reads skills, proceeds
.skillex/index.db ◀── rebuilt with accurate context
on refresh
Skillex scans your dependencies for skill exports, links them to the right scopes, stores everything in a local SQLite registry, and serves queries in microseconds. The registry is a deterministic build artifact — same repo state always produces the same index.
With packs, skill discovery is no longer limited to Node package exports:
- repos can commit project-local packs in
skillex/pack.yaml - packages and Go modules can ship
skillex/pack.yamlwith their code - packs can define detectors such as
gin,rails, ornextjs - Skillex core keeps only a small baseline detector set and lets communities define the rest
In practice, that means the agent can ask:
I'm working on this file, with these dependencies, on this version. What do I need to know?
And get back the small, correct slice:
- repo skills for the current path
- app or package-area skills for that scope
- only the public skills for dependencies being consumed
- private skills only when working inside the package itself
- the correct installed version when the same package name appears more than once in the repo
That is the core difference: Skillex moves scope resolution out of the model's prompt assembly and into deterministic indexing plus structured query.
Features
- Deterministic — same repo state produces the same index, every time.
- Version-correct — skills are read from the resolved package install, not from the internet.
- Scope-aware — skills are linked to the paths where they apply. A query for
packages/app-a/**never returns skills forpackages/app-b. - Public and private — packages export consumer-facing skills (public) and contributor-facing skills (private). Visibility is enforced automatically.
- Packs — projects, packages, and modules can ship a manifest of skills, detectors, activation rules, and scopes.
- Detector-driven activation — built-in and pack-defined detectors activate skills from project facts such as files and dependencies.
- Polyglot resolver model — Node package support now shares infrastructure with non-Node resolvers; Go modules are the first non-Node resolver.
- Instant retrieval — SQLite index with structured queries plus keyword search over skill
nameanddescription. No document browsing, no embeddings. - MCP native — first-class Model Context Protocol server. Agents with MCP support get typed tool calls and resource discovery.
- CLI fallback — every agent harness can call the CLI. Works in CI, scripts, and terminals.
- AGENTS.md manifest — auto-generated fallback for agents that can't run MCP or shell commands.
- Testable — every skill can have a co-located
.test.mdfile with structured validation scenarios. - Non-invasive — dependencies never modify your repo. No lockfile mutation, no network calls at query time.
Installation
Global binary install (recommended)
Install Skillex as a platform utility that works in any repository:
curl -fsSL https://raw.githubusercontent.com/atheory-ai/skillex/main/install.sh | sh
To install a specific version:
curl -fsSL https://raw.githubusercontent.com/atheory-ai/skillex/main/install.sh | SKILLEX_VERSION=0.6.4 sh
The installer downloads the correct binary for your platform from GitHub Releases
and installs it to ~/.local/bin by default. Set SKILLEX_INSTALL_DIR to choose
a different install directory.
npm dev dependency (Node.js projects)
Node projects can pin Skillex as a local dev dependency:
npm install --save-dev @atheory-ai/skillex
# or
pnpm add -D @atheory-ai/skillex
# or
yarn add -D @atheory-ai/skillex
The package automatically installs the correct binary for your platform (macOS arm64/x64, Linux arm64/x64, Windows x64) via npm's optionalDependencies mechanism — only the binary for your OS is downloaded.
Go install
go install github.com/atheory-ai/skillex/cmd/skillex@latest
Build from source
git clone https://github.com/atheory-ai/skillex
cd skillex
make build # produces ./skillex
make install # installs to $GOPATH/bin
Quick start
Initialize your repo
skillex init
This creates:
skillex.json— configuration file (default)skills/repo.md— a starter repo-wide skillAGENTS.md— auto-generated agent instructions (MCP + CLI).skillex/index.db— the registry (rebuilt on each refresh)
To also configure MCP for your agent harness:
skillex init --harness cursor # writes .cursor/mcp.json
skillex init --harness claude-code # writes .claude/mcp.json
skillex init --harness windsurf # writes .windsurf/mcp.json
Write your first skill
Edit skills/repo.md:
---
topics: [conventions, git]
tags: [getting-started]
---
# Repository Conventions
## Commit messages
We use conventional commits: feat:, fix:, chore:, docs:
## Branch naming
feature/<ticket>-<short-description>
Rebuild the index
skillex refresh
Query skills
# All skills for a file path
skillex query --path packages/app-a/src/auth.ts
# By topic
skillex query --topic error-handling
# By tag
skillex query --tags migration,breaking-change
# By package
skillex query --package @acme/foo
# Compound query — intersection of all filters
skillex query --path packages/app-a/** --topic auth --tags v2
# Full content, ready to pipe to an agent
skillex query --path packages/app-a/** --format content
Configuration
skillex.json
{
"Version": 4,
"Rules": [
{
"Scope": "**",
"Skills": ["skills/repo.md"]
},
{
"Scope": "packages/*/**",
"Skills": ["skills/package-dev.md"]
},
{
"Scope": "packages/app-a/**",
"DependencyBoundary": "packages/app-a"
}
]
}
JSON is the default format generated by skillex init.
To generate YAML instead:
skillex init --yaml
Rules are additive. A path matching multiple rules accumulates skills from all of them.
| Field | Description |
|---|---|
Scope |
Glob pattern. Skills in this rule apply when the working path matches. |
Skills |
Repo-local skill files to attach to this scope. |
DependencyBoundary |
Path to a package.json. The scanner reads its dependencies and links any that export skills. |
Skills
A skill is a Markdown file with optional YAML frontmatter.
---
name: Error Handling
description: How to handle errors and validation when using FooClient in @acme/foo.
topics: [error-handling, validation]
tags: [v2, breaking-change]
---
# Error Handling in @acme/foo
When using FooClient, all API calls return a Result type...
Frontmatter fields
| Field | Description |
|---|---|
name |
Short title for the skill. Recommended; used by --search and result summaries. |
description |
One-line summary. Recommended; used by --search. |
topics |
Semantic categories. Used for --topic queries. |
tags |
Freeform labels. Used for --tags queries. |
source |
(Vendor skills) URL the skill was imported from. |
reviewed |
(Vendor skills) Timestamp of last agent review. |
topics and tags are optional. Skills without frontmatter are still indexed and queryable by path, scope, and package. Skills without name or description are not matched by --search; skillex doctor warns about missing fields.
Project-local packs
A pack bundles skill files with activation rules. Packs are the extension point for ecosystem and framework-specific guidance: a community can publish a pack for a framework, a library can ship a pack with its code, and a repo can commit a project-local pack for its own conventions.
Project-local packs activate during skillex refresh when files, dependencies,
or detector values match the repository.
Skillex discovers project-local pack manifests at:
skillex/pack.yaml
skillex/packs/*/pack.yaml
Example:
name: docker
version: 1.0.0
description: Docker guidance for repositories with Dockerfiles.
detectors:
docker:
matches:
- file:
path: Dockerfile
- file:
path: Dockerfile.*
skills:
- file: docker.md
activate-when:
detector: docker
scope: subtree
- file: typescript.md
activate-when:
files-matching:
- "**/*.ts"
- "**/*.tsx"
scope: matching-files
The skill file path is relative to the pack manifest. A co-located
docker.test.md file is discovered automatically.
Supported activation and scope fields in this initial pack implementation:
| Field | Description |
|---|---|
activate-when.files-present |
Glob patterns matched against repository files. |
activate-when.files-matching |
Glob patterns matched against repository files. |
activate-when.dependency-declared |
Dependency conditions matched against the boundary that resolved a package-shipped pack. |
activate-when.detector |
Friendly detector name registered by Skillex core or a loaded pack. |
detectors |
Optional detector definitions registered by the pack while it is loaded. |
files |
Optional glob patterns for scope: matching-files; when omitted, the activation matches are used. |
scope: repo |
Activate the skill for the whole repository (**). |
scope: boundary |
Activate for the dependency boundary that resolved a package-shipped pack. |
scope: subtree |
Activate for the directory containing the matched file and below. Default. |
scope: directory |
Activate for files immediately inside the matched file's directory. |
scope: matching-files |
Activate for the exact files matched by the activation or files patterns. |
scope: nearest-ancestor |
Activate for the nearest containing directory and below. |
Pack skills are indexed individually with source_type: pack. Existing projects
with no pack manifests behave exactly as before.
Detector names are extensible. Skillex core includes only a small baseline of
stable detectors, such as docker, go, javascript, and typescript. Packs
can register framework, library, or ecosystem-specific detector names for the
current refresh run. Conflicting detector definitions are rejected unless they
are identical, so core does not need to own every possible term.
Exporting skills from a package
Any npm package can export skills by adding a skillex field to its package.json:
{
"name": "@acme/foo",
"skillex": true
}
Then create the skill directories:
skillex/
public/ ← skills for consumers of the package
consumer.md
consumer.test.md
migrations.md
migrations.test.md
private/ ← skills for contributors to the package
architecture.md
dev-workflow.md
To initialize a package for skill exports:
skillex init --package
Public skills are linked when the package appears as a dependency of the current scope. Private skills are linked when the agent's working path is inside the package's source tree.
Packages can also ship a pack manifest alongside the legacy directories:
skillex/
pack.yaml
usage.md
public/
consumer.md
name: "@acme/foo"
version: 1.0.0
skills:
- file: usage.md
activate-when:
dependency-declared:
- source: npm-package
name: "@acme/foo"
scope: boundary
When skillex/pack.yaml is present, Skillex activates matching pack skills at
refresh time and indexes them individually with package metadata. The existing
skillex/public and skillex/private behavior remains supported.
Go modules can ship the same skillex/pack.yaml convention. The Go resolver
detects go.mod dependency boundaries, reads declared modules, and resolves
local replace or vendor module roots without downloading dependencies or
mutating module state.
Custom skill directory
{
"skillex": {
"path": "docs/skillex"
}
}
Skill tests
Every skill can have a co-located test file (<name>.test.md). Tests are structured scenarios that agents use to self-evaluate whether a skill produces correct guidance.
# Tests: consumer.md
## Validation: API initialization
Prompt: "How do I initialize the @acme/foo client?"
Success criteria:
- Response references the FooClient constructor
- Response includes the required config object
- Response does not expose internal implementation details
## Validation: Error handling
Prompt: "How should I handle errors from @acme/foo?"
Success criteria:
- Response covers the FooError type
- Response shows try/catch pattern with specific error codes
## Validation: Migration from v1
Prompt: "I'm upgrading @acme/foo from v1 to v2"
Skills: consumer.md, migrations.md
Success criteria:
- Response mentions the breaking change in auth flow
- Response provides the v2 config shape
- Response does not suggest deprecated v1 patterns
The agent is the test runtime. Skillex validates structure; agents validate behavior. To check structural integrity:
skillex test validate
skillex test validate --check # exit non-zero on errors (CI)
MCP server
Skillex runs as a Model Context Protocol server, providing native integration for MCP-capable agent harnesses (Cursor, Claude Code, Windsurf, and others).
skillex mcp
MCP configuration
Add to your harness's MCP config (e.g. .cursor/mcp.json):
{
"mcpServers": {
"skillex": {
"command": "skillex",
"args": ["mcp"]
}
}
}
Or let skillex init --harness <name> write this for you.
MCP primitives
Tool: skillex_query
Parameters:
path string File path or glob pattern
topic string Comma-separated topic filters
tags string Comma-separated tag filters
package string Package name filter
search string Keyword search over skill name and description (space/comma tokens, OR)
format string "content" or "summary" (default: summary when search is set, else content)
Resources
Each skill in the registry is exposed as a discoverable MCP resource at:
skillex://skills/{scope}/{package}/{filename}
Agents discover available resources through the MCP protocol's resource listing — no AGENTS.md parsing required.
CLI reference
All commands support --json (structured stdout) and --quiet (suppress stderr).
skillex init
skillex init # Interactive setup for a repo
skillex init --yes # Accept all defaults (creates skillex.json)
skillex init --yaml # Generate skillex.yaml instead
skillex init --package # Initialize a package for skill exports
skillex init --harness cursor # Also configure MCP for Cursor
skillex refresh
skillex refresh # Rebuild the registry (dev mode)
skillex refresh --mode prod # Production deps + public skills only
skillex refresh --check # Fail if registry is stale (CI)
skillex refresh --dry-run # Preview without writing
skillex query
skillex query --search "<concepts>"
skillex query --path <filepath>
skillex query --topic <topic>
skillex query --tags <tag1,tag2>
skillex query --package <name>
skillex query --search "auth" --topic security
skillex query --path <glob> --topic <topic> --format content
skillex query --format summary --json
skillex test validate
skillex test validate # Check all test files
skillex test validate --check # Exit non-zero on errors (CI)
skillex test validate --scope "packages/app-a/**"
skillex doctor
skillex doctor # Full diagnostics report
skillex doctor --json # Machine-readable report
Checks: configuration validity, registry health, test coverage, topic/tag distribution, skills missing name/description (search discoverability), AGENTS.md presence, vendor skill provenance.
skillex get
skillex get <url> # Fetch and vendor a remote skill
skillex get <url> --topic react,hooks # Assign topics on import
skillex get <url> --skip-review # Skip safety review
Fetches a skill from a URL, runs a structural safety review (checking for prompt injection patterns, exfiltration attempts, and dangerous commands), converts it to skillex format, and vendors it to skillex/vendor/<source>/.
skillex import
skillex import ./docs/api-patterns.md
skillex import ./docs/api-patterns.md --visibility public --topic api,patterns
skillex import ./legacy-rules/ --batch
Imports a local file through the same review and conversion pipeline as skillex get. Use this to migrate Cursor rules, Windsurf rules, or any existing Markdown documentation.
skillex mcp
skillex mcp # Start MCP server on stdio
skillex version
skillex version
skillex version --json
CI integration
Add to your CI pipeline:
# Fail if the registry is out of date with the source files
skillex refresh --check
# Fail if any test files are malformed
skillex test validate --check
Recommended package.json scripts:
{
"scripts": {
"skillex:refresh": "skillex refresh",
"skillex:test": "skillex test validate",
"skillex:doctor": "skillex doctor"
}
}
Vendoring external skills
Skillex provides a controlled pipeline for adopting skills from external sources. Vendor skills are committed to your repo, making them auditable, diffable, and version-controlled.
# Fetch from a URL
skillex get https://raw.githubusercontent.com/someone/react-patterns/main/hooks.md
# Import from a local file
skillex import ./cursor-rules.md --visibility public --topic react
# Batch import a directory
skillex import ./legacy-docs/ --batch
Vendored skills land in skillex/vendor/<source>/ with:
- Normalized frontmatter (name, description when present, topics, tags)
- Source URL recorded for provenance
- Auto-generated test stubs
AGENTS.md
On every refresh, Skillex auto-generates (or updates) a section in AGENTS.md. This serves as a fallback for agents that support neither MCP nor shell execution.
<!-- skillex:start -->
## Skillex
This project uses Skillex for skill management. Use the skillex MCP server
if available (preferred), otherwise use the CLI commands below.
### MCP (preferred)
...
- `skillex_query` parameters include `search` for intent-based discovery.
### CLI (fallback)
...
- `skillex query --search "<concepts>"`
...
### Available scopes
- **
- packages/app-a/**
### Available topics
error-handling, configuration, migration, authentication
### Available tags
v2, breaking-change, deprecated, getting-started
### Packages with skills
@acme/foo (2.3.1) — 3 public, 2 private
<!-- skillex:end -->
Skillex manages only its own section, delimited by markers. It never modifies other content in the file.
Project structure
.
├── skillex.json # Configuration (default)
├── AGENTS.md # Agent instructions (auto-updated)
├── skills/ # Repo-level skills
│ ├── repo.md
│ └── repo.test.md
└── .skillex/
└── index.db # Registry (build artifact, not committed)
For packages exporting skills:
my-package/
├── package.json # "skillex": true
└── skillex/
├── public/ # Consumer-facing skills
│ ├── consumer.md
│ └── consumer.test.md
├── private/ # Contributor-facing skills
│ ├── architecture.md
│ └── dev-workflow.md
└── vendor/ # External skills (committed)
├── github.com/someone/react-patterns/
│ └── hooks.md
└── local/
└── imported-guide.md
How agents use Skillex
With MCP (preferred)
The agent discovers available skills through MCP resource listing and calls the skillex_query tool directly — no shell commands, no file parsing.
With CLI (fallback)
The agent reads AGENTS.md at session start to learn what's available and how to query, then calls skillex query when it needs skills for a specific path or topic.
Skill testing model
When validating a skill, the agent:
- Queries the registry for the skill and its test scenarios
- For each scenario, evaluates the prompt with the skill loaded
- Self-assesses the output against the success criteria
- Reports which validations passed, failed, and why
The CLI validates structure. The agent validates behavior.
Architecture
┌─────────────────┐
│ AGENTS.md │ Fallback
└────────┬────────┘
│
┌────────┴────────┐
│ MCP Server │ Native (resources + tools)
└────────┬────────┘
│
┌────────┴────────┐
│ CLI │ Foundation (Cobra + Lipgloss)
└────────┬────────┘
│
┌──────────────────────┴──────────────────────────────┐
│ skillex core │
│ │
│ Scanner → Linker → Registry (SQLite) → Query engine │
│ Validator │
└─────────────────────────────────────────────────────┘
Core engine (Go library):
| Component | Responsibility |
|---|---|
| Scanner | Discovers skill files in the repo and in installed npm packages |
| Linker | Resolves public/private visibility and scope assignments |
| Registry | SQLite database storing skills, topics, tags, scopes, and test scenarios |
| Query engine | Structured retrieval by path, topic, tags, and package |
| Validator | Checks that skill and test files are well-formed |
Interface layers (all backed by the same core):
| Layer | Use case |
|---|---|
| CLI | Universal. CI, scripts, terminals, any agent harness |
| MCP server | Native integration for MCP-capable harnesses |
| AGENTS.md | Last resort for agents that can't run MCP or shell commands |
Building from source
Requirements: Go 1.22+
git clone https://github.com/atheory-ai/skillex
cd skillex
make build # ./skillex
make install # $GOPATH/bin/skillex
make test # go test ./...
make lint # go vet ./...
make dist # cross-compile for all platforms → dist/
make release-assets # package GitHub release archives + checksums
Cross-compiled targets:
| File | Platform |
|---|---|
dist/skillex-darwin-arm64 |
macOS Apple Silicon |
dist/skillex-darwin-x64 |
macOS Intel |
dist/skillex-linux-x64 |
Linux x64 |
dist/skillex-linux-arm64 |
Linux arm64 |
dist/skillex-win32-x64.exe |
Windows x64 |
Versioning and releases
Skillex uses a single source of truth for releases: the root VERSION file.
- Go binaries read the version at build time via
-ldflags. - npm package versions are synced from
VERSIONbefore packaging. - Local development builds default to
<VERSION>-dev.
To prepare a release:
- Update
VERSIONin a pull request. - Merge the PR to
main. - From a clean local checkout of
main, runmake release-tag. - GitHub Actions verifies the tag, publishes GitHub release assets, and publishes to npm after release approval.
make release-tag reads VERSION, creates the matching v* tag, and pushes it. It refuses to run unless you are on main, your worktree is clean, HEAD matches origin/main, and the tag does not already exist.
To build npm tarballs locally for inspection:
make npm-pack
To build GitHub release assets locally for inspection:
make release-assets
make npm-publish still exists as a manual fallback, but the intended release path is the GitHub Actions release workflow.
At the moment, releases are maintainer-only. In practice, only @ladyhunterbear should bump VERSION, create release tags, or approve the npm-release publish environment until additional maintainers are explicitly added.
Security
- Dependencies never modify the consumer repository.
- No network access at query time — all data comes from the local registry.
- No lockfile mutation.
skillex getandskillex importrun a structural safety review before vendoring any external skill, checking for prompt injection patterns, exfiltration attempts, and dangerous commands.- The SQLite database is fully reproducible from source inputs.
License
Apache 2.0