Local AI skills central library + per-project symlink enablement. One AISkills directory holds every skill source; symlink what you need into any project on demand.
FAQ
skillcaddy is a Claude Code plugin with 1 hand-picked skill for development work, indexed on Flowy. Install it with the command on its page. It includes skillcaddy-manager. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
$ npx -y skills add chenweil/skillcaddy --agent claude-code
Repo: chenweil/skillcaddy
Local AI skills central library + per-project symlink enablement. One AISkills directory holds every skill source; symlink what you need into any project on demand.

If you use Claude Code, Codex, OpenCode, or Pi across multiple projects, you eventually hit one of these:
Skillcaddy fixes this with one AISkills directory as the source of truth and per-project symlinks as the delivery mechanism.
~/AISkills/ aggregates official / github / personal / archived / skills.agents/skills/; never copyarchived/ requires explicit namingskills/<name>/ with SKILL.md + agents/openai.yaml and ship with the repoWhether you're a solo dev with half a dozen repos, a small team standardizing on shared skills, or an author publishing reusable ones β the contract is the same: skills belong to your library, not to any one project.
git clone https://github.com/chenweil/skillcaddy.git
cd skillcaddy
npm install
npm start
Requires Node.js >= 20. The web manager uses the fixed default URL http://127.0.0.1:4173. Fill in the target project path on the page, and enable/disable skills. If that port is temporarily occupied, start with PORT=<other-port> npm start.
For the interactive terminal manager, run:
npm run tui -- /path/to/project
# or with explicit root
npm run tui -- --root ~/AISkills /path/to/project
To use the cloned library from any project, link its TUI command once:
npm run install:tui
npm run check:tui
cd /path/to/another-project
skillcaddy
install:tui uses local npm link: it does not download or copy Skillcaddy from the npm registry. The global skillcaddy command remains linked to this clone, which stays the central library and can be updated with git pull. Running skillcaddy without an argument manages the current directory; skillcaddy /path/to/project selects another project. The installer refuses to replace a global skillcaddy package linked to another clone.
The TUI provides a full keyboard-driven interface without needing a browser:
.agents/skills/ and auto-syncs Claude Code.claude/skills/ with .agents/skills/github/ reposnote fields for skills that only have an English descriptionLibrary browsing now shows skills in a compact paginated table (n/p to page through, a to bulk-enable). The skill introduction prefers the metadata note over the raw English description when both exist.
Menu navigation uses number keys (1-10) for actions, /keyword for search, b to go back, q to quit. Ideal for quick terminal workflows or headless environments.
To make the bundled skillcaddy-manager skill available to AI agents from any project, install its global entry once:
npm run install:manager
npm run check:manager
This creates a managed symlink at ~/.agents/skills/skillcaddy-manager pointing back to skills/skillcaddy-manager. It will not overwrite an existing file, directory, or symlink that points somewhere else.
You can also pass the project path through the URL:
http://127.0.0.1:4173/?projectPath=<encoded-project-path>
The page loads that project immediately, keeps recently used project paths in browser-local history, and lets you bulk-enable all available skills from a library with the library-level + button. If a library was enabled by mistake, use the library-level Γ button to clean that library from both Agents and Claude Code.
SKILL.md remains the Agent-facing contract. Human-facing notes and categorization are stored by Skillcaddy under .skillcaddy/metadata/.../skillcaddy.json so external source repositories stay clean:
{
"note": "Useful before and after code changes to keep execution disciplined.",
"tags": ["Developer Tools", "Quality", "Workflow"],
"autoEnable": true
}
Runtime scans and the web UI read metadata only from the local sidecar store. Tags appear as filter tabs and badge pills; notes are shown on each skill card. Set autoEnable to false to exclude a deprecated or risky skill from library-level bulk enable while still allowing single-skill manual enable. This keeps upstream source repositories clean while still making a large local skill library easier to browse.
Since v0.15.0, normal runtime scans ignore legacy <skill-dir>/skillcaddy.json files. The migration command explicitly discovers them, remains available through v0.15.x, and is removed in v0.16.0. Preview and apply the migration with:
npm run migrate:metadata
npm run migrate:metadata -- --yes
The apply command writes equivalent sidecar metadata and retains the legacy file for rollback. Runtime behavior changes only after the sidecar is written.
Some collections require a one-time, per-project setup after their skills are enabled. Skillcaddy keeps these contracts outside third-party clones under collection-metadata/<source>/<collection>.json. /api/state reports each configured collection as missing, partial, ready, or invalid.
Library-level enablement uses POST /api/enable-plan to include the declared setup skill when needed and POST /api/enable-collection to apply the shared plan. One lifecycle now classifies every candidate as enabled, unchanged, skipped, or failed and refreshes setup guidance for both Web and TUI. Enabling links remains allowed, but an incomplete collection is shown as pending rather than ready. Interactive setup is never run silently, and collection metadata cannot provide executable shell commands.
| Platform | Status | Notes |
|---|---|---|
| macOS | β Fully supported | Native directory symlinks |
| Linux | β Fully supported | Native directory symlinks |
| Windows | β οΈ Extra setup required | See below |
Skillcaddy creates directory symlinks via Node's fs.symlink(..., 'dir'). On Windows this call requires one of the following or it throws EPERM:
npm start in an elevated terminalreadlink may return the target with a \\?\ prefix or backslashes, which can affect the duplicate-alias-target detection (existingTarget !== resolvedSkillPath check in enableSkill).To make Skillcaddy work out of the box on Windows, the following strategies will be introduced later β but none are implemented in the current version:
process.platform === 'win32' is detected, prefer junction (fs.symlink(target, path, 'junction')); junctions don't require Developer Mode.EPERM and recursively copy skill contents into .agents/skills/, and modify disableSkill to remove the real directory.resolveLinkTarget strips the \\?\ prefix, normalizes separators, and compares case-insensitively on Windows.βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Skillcaddy (central library) β
β ~/AISkills/ β
β βββ official/ ββ¬β my-skill/SKILL.md β
β βββ github/ ββ€ β
β βββ personal/ ββ΄β another-skill/SKILL.md β
β βββ archived/ β
β βββ skills/ β bundled with the repo (source: local) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
Symlinks created on enable
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Project directory β
β ~/projects/my-app/ β
β βββ .agents/skills/ β
β β βββ my-skill βββββββββββββββΊ ~/AISkills/official/my-skill β
β β βββ another-skill ββββββββββΊ ~/AISkills/personal/... β
β βββ .claude/skills/ β
β β βββ my-skill βββΊ ../../.agents/skills/my-skill β
β β βββ another-skill ββΊ ../../.agents/skills/another-skill β
β βββ .opencode/skills/ (optional) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
Each Agent auto-discovers and loads skills directories
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Agent β Project-level skills path β User-level path β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Claude Code β .claude/skills/ β ~/.claude/skills β
β OpenCode β .opencode/skills/ β ~/.config/... β
β β .claude/skills/ β ~/.claude/skills β
β β .agents/skills/ β ~/.agents/skills β
β Codex β .agents/skills/ β ~/.agents/skills β
β Pi β .pi/skills/ β ~/.pi/agent/... β
β β .agents/skills/ β ~/.agents/skills β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Core design:
.agents/skills is the cross-Agent standard path; every Agent recognizes it..claude/skills is Claude-Code-specific, but uses secondary symlinks pointing back into .agents/skills.skillcaddy/
βββ official/ # Official / upstream skills (gitignored, fill locally)
βββ github/ # Skills cloned from GitHub (gitignored)
βββ personal/ # Personal original skills (gitignored)
βββ archived/ # Retired skills (gitignored)
βββ skills/ # Repo-bundled skills (shipped with this project; currently hosts skillcaddy-manager)
βββ lib/ # Manager code
βββ public/ # Web UI
βββ scripts/ # Maintenance scripts (e.g. pull-github.sh)
βββ server.js
βββ test/
The four external skill source directories (official / github / personal / archived) are added to .gitignore. Use the managed source commands below instead of choosing a destination manually. skills/ is the repo-bundled source, shipped with this project, and is not in .gitignore.
The first release is exposed through repository-local npm commands:
# Read-only inventory and inspection
npm run source -- list
npm run source -- inspect github/example/toolbox
# Preview, then acquire a Git repo, public HTTP(S) ZIP, direct SKILL.md,
# local ZIP, or local directory
npm run source -- add <input>
npm run source -- add <input> --yes
# Direct SKILL.md requires an explicit name and installs under official/<name>/
npm run source -- add https://example.com/SKILL.md --name example --yes
# Replace one registered source; Archive/Local updates require a new input,
# while Git/Remote file updates may reuse their registered origin
npm run source -- update <source-id> [input]
npm run source -- update <source-id> [input] --allow-breaking --yes
# Update all registered Git sources through the same safety path
npm run source -- update-git
add and update are separate operations. An identical repeated add is a successful no-op, while an identity or destination collision stops without authorizing replacement. Use --name or --namespace to resolve Archive/Local naming collisions. Remote files require --name and reject --namespace; use update only for a source identity already present in the source registry. A Remote-file update may omit input to reuse the registered origin or supply a new stable URL to migrate that origin.
CLI exit categories are stable: 0 success or identical no-op, 1 general acquisition/update failure, 2 invalid usage, 3 unresolved identity or collision, and 4 missing authorization for a breaking replacement.
Acquisition changes only the central library. It never creates project links, executes acquired code, runs setup, or invokes runtime preflight. Enablement uses an already acquired skill through the existing Web, TUI, or project-link API. For an explicit combined request, acquire first, rescan state, resolve the one requested skill by full ID, and enable only that selection.
Unknown setup readiness produces no generic warning or gate. A declared setup contract may add a non-blocking reminder after enablement. The publisher skill's runtime preflight remains responsible for proprietary credentials and setup, such as an IMA API key.
Migration preserves physical source paths and project links. Preview it first:
npm run source -- migrate
npm run source -- migrate --yes
The apply command writes only sidecar records under .skillcaddy/sources/; ambiguous sources remain unresolved rather than guessed. For extra recovery protection, copy that registry directory before applying. Restoring that copy restores the previous registry state without moving central-library content. Failed add and update operations clean up or roll back automatically; after any interruption, run npm run source -- list and npm run source -- inspect <source-id> before retrying.
The first release supports complete Git repositories, public HTTP(S) ZIP files, stable direct HTTP(S) /SKILL.md files, local ZIP files, and local directories. It does not provide source acquisition or replacement in Web/TUI, source removal, automatic latest-version selection, or non-ZIP archives. The clone-backed global skillcaddy command only exposes the existing TUI; it does not turn source acquisition into a global npm package. A Remote file acquires only one SKILL.md; skills with companion files must use a ZIP, Local, or complete Git source.
Bundled with this repo (only when contributing to Skillcaddy itself):
skills/<skill-name>/
βββ SKILL.md
βββ agents/
βββ openai.yaml # Codex / OpenCode metadata (optional)
Skills under skills/ are tagged during scan as source: 'local', id: 'local/<name>' β behavior is identical to other sources and they can be enabled into any project's .agents/skills/.
On startup the manager scans every source directory (official / github / personal / archived / skills); no service restart is needed to see new skills in the UI.
Update every registered Git source through the unified fast-forward-only safety path. Dirty working trees are skipped, and breaking updates that affect a known current-project link are blocked:
npm run source -- update-git
Lets an Agent (especially Codex) know how to use Skillcaddy itself correctly:
Safety rules: only operate on project-side .agents/skills symlinks; never delete central source files; never touch archived/ unless explicitly named; always produce a dry-run summary before any state change.
Invocation: agents/openai.yaml sets allow_implicit_invocation: true, so the Agent auto-loads it when seeing a relevant request.
Enable: creates a symlink under the project's .agents/skills/ pointing back into the central library.
<project>/.agents/skills/<alias> -> <skillcaddy>/<source>/<skill>
Sync Claude: creates a .claude/skills/ entry point for Claude Code, where each skill symlinks into .agents/skills/.
<project>/.claude/skills/<alias> -> ../../.agents/skills/<alias>
Disable: removes the symlink. The source file is left untouched.
Why two layers of symlinks?
.agents/skills is the Agent Skills standard; Codex / OpenCode / Pi all recognize it..claude/skills lets Claude Code use them too, with independent enable/disable.Skillcaddy includes a built-in recommendation system to help users discover and choose appropriate skills.
node skills/skillcaddy-manager/scripts/view-recommendations.cjs onboarding
node skills/skillcaddy-manager/scripts/view-recommendations.cjs scenario new-project
When the library is empty, the default recommendation is:
skillsmp, skills.shDevelopment workflow golden combo:
mattpocock/skills (workflow suite)
setup-matt-pocock-skills project configuration with readiness trackinglencx/skills (project control)
node skills/skillcaddy-manager/scripts/check-conflicts.cjs <collection-id> --against <installed-id,installed-id>
node skills/skillcaddy-manager/scripts/check-global-skills.cjs
node skills/skillcaddy-manager/scripts/version-manager.cjs check
See the Skillcaddy manager recommendation branch for detailed documentation.
npm test
Linux Do ζ΅ θ° AI ηΌη¨ ζ·±εΊ¦ζθοΌζΆζθ ζ½ & Loop Engineering
.gitignore
.import-rules.json
AGENTS.md
archived/
.gitkeep
CHANGELOG.md
collection-metadata/
github/
mattpocock.json
CONTEXT.md
docs/
adr/
0001-managed-source-acquisition.md
0002-manage-single-remote-skill-files.md
0003-recognize-common-skill-source-layouts.md
0004-centralize-source-upgrade-lifecycle.md
0005-centralize-source-acquisition-lifecycle.md
0006-centralize-collection-enablement-lifecycle.md
agents/
domain.md
issue-tracker.md
triage-labels.md
assets/
skillcaddy_CN.png
skillcaddy_EN.png
index.html
SOURCE_ACQUISITION_IMPLEMENTATION_PLAN.md
github/
.gitkeep
lib/
canonicalJson.js
claudeStore.js
collectionEnablement.js
collectionSetup.js
enablePlan.js
managerInstall.js
managerSourceWorkflow.js
projectActions.js
projectPath.js
skillMetadata.js
skillStore.js
sourceAcquisition.js
sourceAcquisitionAdapter.js
sourceAcquisitionError.js
sourceAcquisitionPolicy.js
sourceArchive.js
sourceArchiveWorkspace.js
sourceGit.js
sourceGitAcquisitionAdapter.js
sourceGitBatchUpdate.js
sourceGitStaging.js
sourceGitUpgradeAdapter.js
sourceGitUrl.js
sourceHttp.js
sourceLocal.js
sourceLocalAcquisitionAdapter.js
sourceManager.js
sourceMigration.js
sourceMigrationIssue.js
sourcePath.js
sourcePolicy.js
sourceRecord.js
sourceRegistry.js
sourceRemoteArchiveAcquisitionAdapter.js
sourceRemoteFileAcquisitionAdapter.js
sourceRemoteFilePolicy.js
sourceRemoteFileWorkspace.js
sourceSkillDiscovery.js
sourceTree.js
sourceUpgrade.js
sourceUpgradeAdapter.js
sourceUpgradePolicy.js
sourceUpgradeTransaction.js
sourceValidation.js
sourceWorkspace.js
tuiActions.js
tuiInstall.js
tuiLayout.js
version.js
LICENSE
official/
.gitkeep
package-lock.json
package.json
personal/
.gitkeep
public/
agentsUi.js
app.js
claude.css
claudeUi.js
emptyState.js
enabled.css
favicon.svg
index.html
skillcaddy_CN.png
skillcaddy_EN.png
styles.css
README_CN.md
README.md
scripts/
check-imports.js
manager-skill.js
migrate-metadata.js
pull-github.sh
source.js
tui-command.js
tui.js
server.js
skills/
skillcaddy-manager/
agents/
openai.yaml
references/
featured-skills.json
METADATA.md
OPERATIONS.md
RECOMMENDATION_GUIDE.md
skill-platforms.json
scripts/
check-conflicts.cjs
check-global-skills.cjs
translate-skill-notes.cjs
version-manager.cjs
view-recommendations.cjs
SKILL.md
skillcaddy.json
test/
check-imports.test.js
collectionEnablement.test.js
collectionSetup.test.js
enablePlan.test.js
managerInstall.test.js
managerSourceWorkflow.test.js
skillConflictCheck.test.js
skillStore.test.js
sourceAcquisitionContract.test.js
sourceAdd.test.js
sourceCli.test.js
sourceGitAdd.test.js
sourceGitUpdate.test.js
sourceHttpArchive.test.js
sourceManager.test.js
sourceMigration.test.js
sourceRemoteFile.test.js
sourceSkillDiscovery.test.js
sourceUpdate.test.js
sourceUpgradeContract.test.js
sourceUpgradeContractFixtures.js
sourceUpgradeFixtureSupport.js
sourceUpgradeGitContractFixture.js
sourceZip.test.js
testHelpers.js
translateSkillNotes.test.js
tuiActions.test.js
tuiInstall.test.js
tuiLayout.test.js
version.test.js
zipFixtures.jsΒ© 2026 Flowy Β· Free and open source
Built for Claude Code Β· Not affiliated with Anthropic