Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/logos/logo-mark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 35 additions & 25 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,43 @@ pnpm test -- --project e2e # E2E tests only
### CLI Commands

```bash
skilld # Interactive menu
skilld add vue nuxt # Add skills for packages
skilld update # Update all outdated skills
skilld update vue # Update specific package
skilld remove # Remove installed skills
skilld list # List installed skills (one per line)
skilld list --json # List as JSON
skilld info # Show config, agents, features, per-package detail
skilld config # Change settings
skilld install # Restore references from lockfile
skilld prepare # Hook for package.json "prepare" (restore refs, sync shipped, report outdated)
skilld uninstall # Remove skilld data
skilld search "query" # Search indexed docs
skilld search "query" -p nuxt # Search filtered by package
skilld cache # Clean expired LLM cache entries
skilld add owner/repo # Add pre-authored skills from git repo
skilld eject vue # Eject skill (portable, no symlinks)
skilld eject vue --name vue # Eject with custom skill dir name
skilld eject vue --out ./dir/ # Eject to custom path
skilld eject vue --from 2025-07-01 # Only releases/issues since date
skilld author # Generate skill for npm publishing (monorepo-aware)
skilld author -m haiku # Author with specific LLM model
skilld author -o ./custom/ # Author to custom output directory
skilld # Interactive menu
skilld add npm:vue npm:nuxt # Install package skills from registry
skilld add gh:owner/repo # Install git skills from GitHub
skilld add @curator # Install all skills from a curator (coming soon)
skilld add @curator/collection # Install a specific collection (coming soon)
skilld add vue # Bare names deprecated, resolves as npm:vue with warning
skilld update # Update all outdated skills
skilld update vue # Update specific package
skilld remove # Remove installed skills
skilld list # List installed skills (one per line)
skilld list --json # List as JSON
skilld info # Show config, agents, features, per-package detail
skilld config # Change settings
skilld install # Restore references from lockfile
skilld prepare # Hook for package.json "prepare" (restore refs, sync shipped, report outdated)
skilld uninstall # Remove skilld data
skilld search "query" # Search indexed docs
skilld search "query" -p nuxt # Search filtered by package
skilld cache # Clean expired LLM cache entries
```

### Author Commands (skill creation and publishing)

```bash
skilld author package # Generate a package skill from docs (monorepo-aware)
skilld author package -m haiku # Author with specific LLM model
skilld author package -o ./custom/ # Author to custom output directory
skilld author publish # Publish skill list to skilld.dev
skilld author eject vue # Eject skill (portable, no symlinks)
skilld author eject vue --name vue # Eject with custom skill dir name
skilld author validate <file> # Validate a skill section
skilld author assemble [dir] # Merge enhancement output into SKILL.md
```

## Architecture

CLI tool that generates AI agent skills from NPM package documentation. Requires Node >= 22.6.0. Flow: `package name β†’ resolve docs β†’ cache references β†’ generate SKILL.md β†’ install to agent dirs`.
CLI tool and curated registry for AI agent skills. Requires Node >= 22.6.0. Primary flow: `skilld add npm:<pkg>` β†’ fetch curated skill from skilld.dev β†’ install to agent dirs. Fallback: `skilld author package <pkg>` β†’ resolve docs β†’ cache references β†’ generate SKILL.md.

**Key directories:**
- `~/.skilld/` - Global cache: `references/<pkg>@<version>/`, `llm-cache/`, `config.yaml`
Expand All @@ -60,7 +69,8 @@ CLI tool that generates AI agent skills from NPM package documentation. Requires
- `src/sources/` - Doc fetching (npm registry, llms.txt, GitHub via ungh.cc)
- `src/cache/` - Reference caching with symlinks to `~/.skilld/references/`
- `src/retriv/` - Vector search with sqlite-vec + @huggingface/transformers embeddings
- `src/core/` - Config (custom YAML parser), skills iteration, formatting, lockfile
- `src/core/` - Config (custom YAML parser), skills iteration, formatting, lockfile, prefix parser
- `src/registry/` - Registry client for skilld.dev API (curated skill fetching)

**Doc resolution cascade (src/commands/sync.ts):**
1. Package ships `skills/` directory β†’ symlink directly (skills-npm convention)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<h1>skilld</h1>
<h1><a href="https://skilld.dev"><img src=".github/logos/logo-mark.svg" alt="" width="28" height="28" valign="middle"></a> skilld</h1>

[![npm version](https://img.shields.io/npm/v/skilld?color=yellow)](https://npmjs.com/package/skilld)
[![npm downloads](https://img.shields.io/npm/dm/skilld?color=yellow)](https://npm.chart.dev/skilld)
Expand Down
76 changes: 38 additions & 38 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ packages:
overrides:
global-agent: ^4.1.3
catalog:
'@mariozechner/pi-ai': ^0.63.1
'@mariozechner/pi-ai': ^0.64.0
'@mdream/crawl': ^1.0.3
'@types/semver': ^7.7.1
bumpp: ^11.0.1
Expand Down Expand Up @@ -36,7 +36,7 @@ catalogs:
mlly: ^1.8.2
oxc-parser: ^0.121.0
p-limit: ^7.3.0
sqlite-vec: ^0.1.7
sqlite-vec: ^0.1.8
tinyglobby: ^0.2.15
unist-util-visit: ^5.1.0
dev-build:
Expand Down
37 changes: 30 additions & 7 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,24 +149,43 @@ async function brandLoader<T>(work: () => Promise<T>, minMs = 1500): Promise<T>
return result
}

// ── Deprecation forwarder ──

function deprecatedForwarder(
oldName: string,
newName: string,
loader: () => Promise<any>,
): () => Promise<any> {
return () => loader().then((cmd: any) => {
const original = cmd.run
return defineCommand({
...cmd,
meta: { ...cmd.meta, name: oldName },
async run(ctx: any) {
console.warn(`\x1B[33m⚠ \`skilld ${oldName}\` is deprecated. Use \`skilld ${newName}\` instead.\x1B[0m`)
return original(ctx)
},
})
})
}

// ── Subcommands (lazy-loaded) ──

const SUBCOMMAND_NAMES = ['add', 'eject', 'update', 'info', 'list', 'config', 'remove', 'install', 'uninstall', 'search', 'cache', 'validate', 'assemble', 'setup', 'prepare', 'author', 'publish']
const SUBCOMMAND_NAMES = ['add', 'eject', 'update', 'info', 'list', 'config', 'remove', 'install', 'uninstall', 'search', 'cache', 'validate', 'assemble', 'setup', 'prepare', 'author', 'publish', 'upload']

// ── Main command ──

const main = defineCommand({
meta: {
name: 'skilld',
version,
description: 'Sync package documentation for agentic use',
description: 'Curated agent skills for your projects',
},
args: {
agent: sharedArgs.agent,
},
subCommands: {
add: () => import('./commands/sync.ts').then(m => m.addCommandDef),
eject: () => import('./commands/sync.ts').then(m => m.ejectCommandDef),
update: () => import('./commands/sync.ts').then(m => m.updateCommandDef),
info: () => infoCommandDef,
list: () => import('./commands/list.ts').then(m => m.listCommandDef),
Expand All @@ -177,11 +196,15 @@ const main = defineCommand({
uninstall: () => import('./commands/uninstall.ts').then(m => m.uninstallCommandDef),
search: () => import('./commands/search.ts').then(m => m.searchCommandDef),
cache: () => import('./commands/cache.ts').then(m => m.cacheCommandDef),
validate: () => import('./commands/validate.ts').then(m => m.validateCommandDef),
assemble: () => import('./commands/assemble.ts').then(m => m.assembleCommandDef),
setup: () => import('./commands/setup.ts').then(m => m.setupCommandDef),
author: () => import('./commands/author.ts').then(m => m.authorCommandDef),
publish: () => import('./commands/author.ts').then(m => m.authorCommandDef),
// Author group (nested subcommands)
author: () => import('./commands/author-group.ts').then(m => m.authorGroupDef),
// Deprecated forwarders (old top-level commands β†’ skilld author <subcommand>)
eject: deprecatedForwarder('eject', 'author eject', () => import('./commands/sync.ts').then(m => m.ejectCommandDef)),
validate: deprecatedForwarder('validate', 'author validate', () => import('./commands/validate.ts').then(m => m.validateCommandDef)),
assemble: deprecatedForwarder('assemble', 'author assemble', () => import('./commands/assemble.ts').then(m => m.assembleCommandDef)),
publish: deprecatedForwarder('publish', 'author publish', () => import('./commands/author.ts').then(m => m.authorCommandDef)),
upload: deprecatedForwarder('upload', 'author publish', () => import('./commands/upload.ts').then(m => m.uploadCommandDef)),
},
async run({ args }) {
// Guard: citty always calls parent run() after subcommand dispatch.
Expand Down
12 changes: 12 additions & 0 deletions src/commands/author-group.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { defineCommand } from 'citty'

export const authorGroupDef = defineCommand({
meta: { name: 'author', description: 'Create, generate, and publish skills' },
subCommands: {
package: () => import('./author.ts').then(m => m.authorCommandDef),
publish: () => import('./upload.ts').then(m => m.uploadCommandDef),
eject: () => import('./sync.ts').then(m => m.ejectCommandDef),
validate: () => import('./validate.ts').then(m => m.validateCommandDef),
assemble: () => import('./assemble.ts').then(m => m.assembleCommandDef),
},
})
2 changes: 1 addition & 1 deletion src/commands/author.ts
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ function printConsumerGuidance(packageNames: string[]): void {
}

export const authorCommandDef = defineCommand({
meta: { name: 'author', description: 'Generate portable skill for npm publishing' },
meta: { name: 'package', description: 'Generate a package skill from documentation' },
args: {
out: {
type: 'string',
Expand Down
Loading
Loading