Architecture
How it works
rolecraft install <source> is the reference path; the other commands reuse its pieces.
- Resolves the source (local path, GitHub/GitLab/SSH, npm) and parses
SKILL.mdfrontmatter. A directory may contain more than one skill; nested skill containers (.claude/skills/,.agents/skills/,skills/) are discovered up to 3 levels deep - Runs the security scan over the resolved files — prompt injection, command injection, obfuscated code, credential harvesting, sensitive file access. Scores 0–100. Every install path enforces this:
install,bundle,update,setup,search --interactive,watch,ci,profile apply. It does not run under--dry-run. What it does not catch → - Copies (or symlinks with
--symlink) the skill's top-level files to each target directory. Files in subdirectories of the skill are not installed, hashed or scanned — #325 - Computes a SHA256 content hash and stores it in the lockfile
- Writes
~/.agents/.skill-lock.jsonfor global installs and<cwd>/.agents/.skill-lock.jsonfor project installs. rolecraft owns these files; agents do not read them rolecraft verifycompares the installed files against the stored hash. It checks the directories derived from the lockfile entry;rolecraft doctorchecks a different, narrower set and can disagree with itrolecraft cire-installs skills and MCP servers from lockfiles. It re-resolves each source live and records a hash of what it installed — it does not pin sources and there is no--frozenmode. #402rolecraft doctorruns a system health check across Node.js, agent directories and lockfilesrolecraft profilesaves, applies, diffs, edits, exports, imports and links multi-agent configuration profilesrolecraft mcpmanages MCP server configurations —install,list,search,check,updateandremoverolecraft agents-xmlgenerates a skills XML block forAGENTS.mdrolecraft watchwatches installed skills for changes and auto-syncs. Only local sources are watched, and it refuses to sync a skill the scan blocksrolecraft convertconverts betweenSKILL.mdand.mdcformats- Skills installed by
@agentskill.sh/cli,add-skillor by hand are read as-is. This is inferred from the slug normalisation andlockfile.version = 3; it is not covered by a test
Project structure
rolecraft/
├── bin/rolecraft.js # CLI entry point, command table, flag validation
├── src/
│ ├── agents.js # the 87 agent records: directories, support level, MCP capability
│ ├── index.js # public API entry point
│ ├── agents/
│ │ └── manifest.js # docs-generation view of the agent table
│ ├── api/ # business logic; importable via `import { ... } from 'rolecraft'`
│ │ ├── agents-xml.js # AGENTS.md XML block generation
│ │ ├── bundle.js # multi-skill install from a bundle file
│ │ ├── bundle-internal.js# bundle install core
│ │ ├── check.js # skill update checking
│ │ ├── ci.js # lockfile-driven re-install
│ │ ├── completions.js # shell completion script generation
│ │ ├── compose.js # combine skills into one
│ │ ├── convert.js # SKILL.md <-> .mdc conversion
│ │ ├── diff.js # compare two states
│ │ ├── doctor.js # system health check
│ │ ├── init.js # SKILL.md scaffolding
│ │ ├── install.js # skill installation + MCP install
│ │ ├── list.js # list installed skills
│ │ ├── mcp.js # MCP server install/list/update/remove
│ │ ├── profile.js # agent config profile management
│ │ ├── remove.js # skill removal
│ │ ├── rollback.js # restore a previous skill version
│ │ ├── search.js # GitHub/skills.sh search
│ │ ├── setup.js # programmatic setup (the CLI uses commands/setup.js)
│ │ ├── test.js # skill quality scoring
│ │ ├── update.js # skill re-install
│ │ ├── upgrade.js # self-upgrade
│ │ ├── use.js # skill preview
│ │ ├── verify.js # integrity verification
│ │ └── watch.js # watch for changes and auto-sync
│ ├── commands/ # CLI wrappers: parse args, call api/, format output
│ │ ├── agents-xml.js ├── agents.js ├── bundle.js
│ │ ├── check.js ├── ci.js ├── completions.js
│ │ ├── compose.js ├── convert.js ├── diff.js
│ │ ├── doctor.js ├── init.js ├── install.js
│ │ ├── list.js ├── mcp.js ├── profile.js
│ │ ├── remove.js ├── rollback.js ├── search.js
│ │ ├── setup.js ├── test.js ├── update.js
│ │ ├── spec.js ├── upgrade.js ├── use.js
│ │ ├── verify.js └── watch.js
│ └── utils/
│ ├── agent-detection.js# which agents are installed on this machine
│ ├── converter.js # frontmatter parsing, SKILL.md <-> .mdc
│ ├── debounce.js # slug-keyed debounce for watch
│ ├── errors.js # UserError + CLI error formatting
│ ├── http-fetch.js # fetch with timeout
│ ├── installer.js # copy/symlink files to target dirs
│ ├── lock-write.js # atomic write + cross-process lock for lockfiles
│ ├── lockfile.js # .skill-lock.json schema + content hashing
│ ├── mcp-lock.js # .mcp-lock.json
│ ├── mcp.js # MCP server config read/write + source resolution
│ ├── paths.js # home/cwd path helpers
│ ├── profile.js # profile capture/apply utilities
│ ├── resolver.js # source resolution: local / GitHub / GitLab / npm
│ ├── scan-gate.js # scan policy: what to do about a finding
│ ├── security.js # static analysis scoring (0-100)
│ ├── spinner.js # terminal spinner
│ ├── templates/ # `init` scaffolding templates
│ └── tui.js # theme, tables, pickers
├── e2e/ # end-to-end tests (not run by `npm test` — see #388)
├── benchmark/ # install-speed benchmark
├── scripts/ # docs generation, hooks, benchmarks
├── hooks/ # git hooks installed by postinstall
├── docs/ # documentation site sources
├── package.json biome.json CHANGELOG.md CONTRIBUTING.md SECURITY.md
├── AGENTS.md MANIFEST-MATRIX.md RELEASE.md SKILL.md
└── README.mdArchitecture overview
Three layers, and where each one is allowed to reach.
1. src/api/ — business logic. Modules export async functions that take options and return plain objects. Intended to be side-effect free and importable via import { ... } from 'rolecraft'. Two caveats: api/install.js writes progress warnings with console.error, and two modules reach into commands/ (api/doctor.js, utils/profile.js).
2. src/commands/ — CLI layer. Parses args, calls api/, formats output. Most files are thin: setup.js keeps only the interactive skill picker and the output, everything else is one setupApi call (#306), and completions.js only prints what api/completions.js generates. spec.js is the single description of the command surface — every command, its flags, their descriptions and its aliases — from which bin/rolecraft.js derives flag validation and help, and api/completions.js derives all three shell scripts (#410).
3. src/utils/ — shared helpers. No circular dependencies. Not strictly a bottom layer: utils/profile.js imports from commands/setup.js, which is how detectAgents ended up reachable from four places before it moved to utils/agent-detection.js.
The command surface is 26 modules under src/commands/ over 25 under src/api/, exposed as 25 top-level handlers in bin/rolecraft.js (profile and mcp each carry several subcommands). Those handlers hold no flag lists: they read flags by exact name, and the one validateFlags call in main() checks them against commands/spec.js. A flag added there appears in --help, in validation and in all three completion scripts at once. Unknown commands and flags exit 2, so a typo is distinguishable from a failed operation.
See also
rolecraft install— where files actually land on disk.- Node.js API — the programmatic surface the CLI is built on.
- Glossary — the vocabulary used throughout these docs.
