Imported from xinyuehtx/skill-module (
AGENTS.md). Install upstream withnpx skills add xinyuehtx/skill-module. Copyright stays with the author.
AGENTS.md — skillmodule
A CLI tool for Agent Skills — dependency resolution via node_modules, SKILL.md rewriting, and multi-platform distribution.
Project Overview
skillmodule is a CLI tool that treats Agent Skills (SKILL.md files) as npm packages. It delegates all version management and dependency conflict resolution to existing npm ecosystem tools (npm, pnpm, yarn, bun), and focuses on:
- Dependency resolution — Skills can declare dependencies on other skills, resolved recursively from node_modules with circular dependency detection
- node_modules integration — All versioning, deduplication, and lock files are handled by the user's package manager (pnpm, npm, yarn, bun)
- Multi-platform install — Hard-link skills into
.claude/skills/,.cursor/skills/,.gemini/skills/,.codex/skills/,.agents/skills/ - Chain triggering — Auto-appends a
## Dependent Skillstable to each SKILL.md so agents can discover transitive dependencies via relative paths - Skill tree building — Reads SKILL.md from node_modules, rewrites with dependency table, and writes to
.skills/output directory
📄 README · 📐 Design Doc
Tech Stack
| Technology | Version / Spec | Purpose |
|---|---|---|
| TypeScript | 5.x, strict: true |
Primary language |
| Node.js | >= 18 | Runtime |
| ESM | "type": "module" |
Module system — imports must use .js suffix |
| tsup | 8.x | Build & bundle (ESM, dts, sourcemap) |
| vitest | 3.x | Unit testing + benchmarks |
| commander | 13.x | CLI framework |
| gray-matter | 4.x | YAML frontmatter parsing |
| pnpm | — | Package manager |
Project Structure
skill-repo/
├── AGENTS.md # AI Agent collaboration guide (this file)
├── src/
│ ├── index.ts # CLI entry point (commander registration)
│ ├── commands/ # CLI command implementations
│ │ ├── init.ts # skillmodule init — generate package.json from SKILL.md
│ │ ├── install.ts # skillmodule install — resolve deps from node_modules, rewrite, link
│ │ ├── publish.ts # skillmodule publish — publish skill package to npm
│ │ ├── tree.ts # skillmodule tree — visualize dependency tree
│ │ └── validate.ts # skillmodule validate — validate skill package format
│ ├── core/ # Core business logic (pure functions preferred)
│ │ ├── skill-parser.ts # Parse SKILL.md frontmatter → SkillMeta
│ │ ├── dependency-resolver.ts # Recursive dependency resolution + cycle detection
│ │ ├── node-modules-resolver.ts # Resolve skill packages from node_modules
│ │ ├── skill-rewriter.ts # Rewrite SKILL.md (append dependent skills table)
│ │ └── platform-installer.ts # Multi-platform hard-link installation
│ ├── types/
│ │ └── index.ts # All shared TypeScript type definitions
│ └── utils/
│ └── logger.ts # Logging utilities (info, success, warn, error, heading, tree)
├── tests/
│ ├── core/ # Unit tests (path mirrors src/core/)
│ │ ├── skill-parser.test.ts
│ │ ├── dependency-resolver.test.ts
│ │ ├── node-modules-resolver.test.ts
│ │ ├── skill-rewriter.test.ts
│ │ └── platform-installer.test.ts
│ ├── bench/ # Performance benchmarks
│ │ ├── install.bench.ts
│ │ └── reinstall.bench.ts
│ └── fixtures/ # Test data (mock skill packages)
│ ├── simple-skill/
│ ├── skill-with-deps/
│ ├── circular-deps/
│ ├── duplicate-name/
│ └── multi-version/
├── examples/ # Usage scenario examples
│ ├── basic/
│ ├── monorepo/
│ ├── duplicate-name/
│ ├── multi-version/
│ └── platform-install/
├── docs/
│ ├── skill-package-manager-design.md # Design document
│ ├── rfcs/ # RFC proposal documents
│ └── specs/ # SPEC documents (1:1 with RFCs)
├── package.json # name: skillmodule, version: 0.1.0
├── tsconfig.json # strict, ES2022, ESNext, bundler resolution
├── tsup.config.ts # ESM, node18, dts, sourcemap, shebang
└── vitest.config.ts # tests/**/*.test.ts, bench/**/*.bench.ts
Architecture
The core modules form a processing pipeline, orchestrated by the install command:
node_modules (managed by npm/pnpm/yarn/bun)
│
▼
┌───────────────────────┐
│ node-modules-resolver │ Discover skill packages in node_modules
└──────┬────────────────┘
│
▼
┌──────────────┐
│ skill-parser │ Parse SKILL.md frontmatter → SkillMeta
└──────┬───────┘
│
▼
┌────────────────────┐
│ dependency-resolver│ Recursive dep tree → DependencyNode[]
└──────┬─────────────┘ (with circular dependency detection)
│
▼
┌────────────────┐
│ skill-rewriter │ Append "## Dependent Skills" table (relative paths)
└──────┬─────────┘
│
▼
┌────────────────────┐
│ .skills/ output │ Write rewritten SKILL.md files (flat layout)
└──────┬─────────────┘
│
▼
┌────────────────────┐
│ platform-installer │ Hard-link to .claude/skills/, .cursor/skills/, etc.
└────────────────────┘
Design Principles
- Delegate versioning — All version management, dependency conflict resolution, and lock files are handled by the user's package manager (npm, pnpm, yarn, bun)
- Pure functions first —
src/core/modules are stateless, input-determines-output functions for easy unit testing - Commands orchestrate —
src/commands/handles IO, user interaction, and composes core modules - Centralized types — All shared type definitions live in
src/types/index.ts, never scattered across modules - Interface abstraction —
PackageSourceinterface decouples dependency resolution from the package source (node_modules, registry, etc.)
Development Workflow (SDD + TDD)
This project follows Spec-Driven Development + Test-Driven Development:
Step 1: RFC
└── Create proposal doc in docs/rfcs/
└── Contents: background, goals, solution design
└── Submit for review — proceed only after approval
Step 2: SPEC
└── Create spec doc in docs/specs/ (named to match RFC, e.g., 001-xxx.SPEC.md)
└── Contents: function signatures, inputs/outputs, edge cases
Step 3: Test First (Red)
└── Write test cases based on SPEC
└── Test files go in tests/ (mirroring src/ structure)
└── All tests should fail initially
Step 4: Implement (Green)
└── Write minimal code to make tests pass
└── Refactor while keeping tests green
Step 5: Validate
└── pnpm test — run all unit tests
└── pnpm bench — run performance benchmarks
└── pnpm lint — TypeScript type check (tsc --noEmit)
Step 6: Release
└── Update README.md and README_zh.md
└── pnpm build — build with tsup
└── npm publish — publish to registry
Code Conventions
TypeScript & ESM
- Strict mode enabled (
"strict": true) - ESM modules: import paths must include
.jssuffix (e.g.,import { foo } from "./bar.js") - Target: ES2022, Module: ESNext, Module Resolution: bundler
- Use
export function— no default exports
Naming
| Element | Convention | Example |
|---|---|---|
| Files | kebab-case | skill-parser.ts, content-store.test.ts |
| Functions | camelCase verb phrases | parseSkillContent, computeSkillHash |
| Types / Interfaces | PascalCase nouns | SkillMeta, DependencyNode |
| Variables | camelCase descriptive nouns | processedCache, storeDir |
Function Design
- Core modules export pure functions (no side effects, output determined by input)
- Use
export function, neverexport default - Async functions return
Promise<T>, sync functions return directly - Prefer small, focused functions over large monolithic ones
Comments
- All exported functions must have JSDoc comments describing purpose and parameters
- Add inline comments for complex logic explaining why, not what
- No TODO comments — implement directly or track in issue tracker
Error Handling
- Throw with descriptive messages:
throw new Error("Package not found: ${name}") - Commands layer catches errors and calls
process.exit(1) - Never silently catch errors — always handle or re-throw
Type Management
- All shared types defined in
src/types/index.ts - Use
import typefor type-only imports:import type { Foo } from "../types/index.js" - Prefer
interfacefor object shapes,typefor unions and utility types
Testing
Framework
vitest 3.x — with describe / it / expect API.
Directory Conventions
| Category | Path | Notes |
|---|---|---|
| Unit tests | tests/core/<module>.test.ts |
Mirror src/core/ structure |
| Command tests | tests/commands/<command>.test.ts |
If needed |
| Benchmarks | tests/bench/<scenario>.bench.ts |
Performance baselines |
| Fixtures | tests/fixtures/<scenario>/ |
Mock SKILL.md, package.json, etc. |
Writing Tests
- Test naming:
it("should <expected behavior> when <condition>") - Each core module must cover: happy path, edge cases, error cases
- Use fixture data from
tests/fixtures/— avoid hardcoding large content in tests - Keep tests focused and independent (no shared mutable state between tests)
Commands
pnpm test # Run all unit tests
pnpm test:watch # Watch mode (auto-rerun)
pnpm bench # Run performance benchmarks
pnpm lint # TypeScript type check (tsc --noEmit)
Build & Release
Build
pnpm build # tsup → dist/ (ESM, dts, sourcemap)
Output: single file dist/index.js with #!/usr/bin/env node shebang banner.
Publish
skillmodule publish [dir] # Publish a skill package to npm
npm publish # Publish the skillmodule CLI itself
Key Types
Core types defined in src/types/index.ts:
| Type | Purpose |
|---|---|
SkillMeta |
Parsed SKILL.md frontmatter (name, description) |
SkillPackageJson |
Skill package.json structure (with skill field) |
ResolvedSkillPackage |
Fully resolved skill with resolvedDir and dependencies |
DependencyNode |
Node in the dependency tree (includes resolvedDir) |
DependentSkillEntry |
Row in the "Dependent Skills" table appended to SKILL.md |
PlatformId |
Supported platform identifiers: claude, cursor, gemini, codex, agents, all |
InitOptions |
Options for skillmodule init command |
InstallOptions |
Options for skillmodule install command |
PublishOptions |
Options for skillmodule publish command |
Helper functions: extractSkillName().
CLI Commands Reference
| Command | Description | Entry File |
|---|---|---|
skillmodule init [dir] |
Generate package.json from SKILL.md frontmatter |
src/commands/init.ts |
skillmodule install |
Resolve deps from node_modules → rewrite → link | src/commands/install.ts |
skillmodule publish [dir] |
Publish skill package to npm registry | src/commands/publish.ts |
skillmodule tree |
Visualize skill dependency tree | src/commands/tree.ts |
skillmodule validate [dir] |
Validate skill package format | src/commands/validate.ts |
Options:
install --platform <claude|cursor|gemini|codex|agents|all>— Link to platform skill directoryinstall --output <dir>— Custom output directory (default:.skills)init --all— Batch init all skills under a directoryinit --scope <scope>— npm scope prefix (e.g.,@myteam)publish --dry-run— Preview without publishingpublish --tag <tag>— npm dist-tag (default:latest)
