skills
Enterprise-oriented package manager for Cursor skills. Install skills from private Git repositories into your project's .cursor/skills/ directory with deterministic lockfiles and drift detection.
No telemetry. Authentication is delegated entirely to your system Git configuration (SSH agent, credential helpers, deploy keys, corporate certificates, CI tokens).
Requirements
- Rust 1.70+ (to build from source)
- Git on
PATH
Install
Homebrew (lmrr.cc)
curl -fsSL https://lmrr-cc.pages.dev/install/brew-tap.sh | bash
brew install lmrr/cc/skills
skills --help
Docs: https://lmrr-cc.pages.dev/tools/skills/
Install script (cargo)
curl -fsSL https://lmrr-cc.pages.dev/install/skills.sh | bash
export PATH="$HOME/.local/bin:$PATH"
skills --help
Install from this checkout during development:
SKILLS_REPO="$PWD" ./install.sh
Force reinstall:
SKILLS_FORCE=1 SKILLS_REPO="$PWD" ./install.sh
Update an existing install to the latest main:
skills upgrade
Or rerun the install script:
SKILLS_FORCE=1 curl -fsSL https://lmrr-cc.pages.dev/install/skills.sh | bash
skills update refreshes project skills from skills.toml. skills upgrade refreshes the skills CLI program itself.
Environment variables:
| Variable | Default | Purpose |
|---|---|---|
INSTALL_DIR |
$HOME/.local/bin |
Binary destination |
SKILLS_REPO |
https://github.com/lmrco/skills |
Git repo or local path |
SKILLS_VERSION |
main |
Git branch for remote install |
SKILLS_PATH |
skills-cli |
Crate path for local install |
SKILLS_FORCE |
0 |
Set to 1 to pass --force to cargo install |
Cargo path install
cd skills
cargo install --path skills-cli --bin skills
Quick start
Add and install from a public Git repository:
skills add https://github.com/leonardomso/rust-skills
That auto-detects the default branch, discovers all bundle assets (skills, rules, prompts, agents, and AGENTS.md when present), writes skills.toml, fetches the bundle, and installs into .cursor/.
For skill-only repositories, use --skills-only to discover skills without rules, prompts, or agents:
skills add https://github.com/leonardomso/rust-skills --skills-only
For private bundles with explicit refs and skill names:
skills init --rules
skills add git@gitlab.company.com:ai/cursor-skills.git \
--bundle platform-skills \
--ref v1.0.0 \
that-skill other-skill
Use skills init --rules to opt into Cursor rules sync. Without [rules] in skills.toml, rule sync stays disabled for backward compatibility.
skills add installs immediately by default. Use --register-only to update skills.toml without fetching.
Re-install everything already registered in skills.toml:
skills install
After installation:
.cursor/skills/rust-skills/SKILL.md
.cursor/skills/that-skill/SKILL.md
Install semantics
skills install behaves like npm install / yarn install:
- uses
skills.lockby default when it exists - restores
.cursor/skills/from locked commits after deletion - does not advance branch refs already pinned in the lockfile
- creates or updates
skills.lockonly when the manifest changed or the lockfile is missing
skills install --locked behaves like npm ci / **yarn install --frozen-lockfile`:
- requires
skills.lock - fails if
skills.tomlandskills.lockdiffer - installs exact locked commits (never branch heads)
- never writes the lockfile
- recommended for CI
skills update behaves like npm update / yarn upgrade:
- intentionally re-resolves refs from
skills.toml - updates
skills.lockwith new commits and content hashes - reinstalls changed skills
Example workflow:
skills init
skills add git@gitlab.company.com:ai/cursor-skills.git \
--bundle platform-skills \
--ref main \
code-review security-review
skills install
git add skills.toml skills.lock .gitignore
git commit -m "Add Cursor skills"
Teammate workflow after clone:
skills install
skills verify
CI workflow:
skills install --locked
skills verify
What to commit
| Commit to Git | Do not commit |
|---|---|
skills.toml — desired bundles, refs, and skill names |
.cursor/skills/<managed-skill>/ — reproduced from lockfile |
skills.lock — exact commit + content hash per skill and rule |
.cursor/rules/skills--* — generated Cursor rules (when [rules].gitignore = true) |
.gitignore — managed block synced by skills gitignore |
skills install, skills add, and skills update automatically sync a marked # BEGIN skills-cli managed block in .gitignore. When .cursor/ (or the configured install target) is already ignored, the managed block contains comments only — not individual skill paths.
Project files vs system cache
skills.lock and .skills/ are not the same thing:
| Artifact | Location | Purpose | Commit? |
|---|---|---|---|
| Lockfile | skills.lock at project root |
Pins exact Git commits and BLAKE3 content hashes (npm/yarn-style) | Yes |
| Installed skills | .cursor/skills/<name>/ (or configured target) |
Generated skill content restored by skills install |
No |
| Generated rules | .cursor/rules/skills--<skill>--<rule>.mdc (when rules sync enabled) |
Copy of skill-owned rules for Cursor's project rules engine | No (default) |
| Install cache | $XDG_CACHE_HOME/skills/<project-id>/ (fallback: ~/.cache/skills/) |
Staging dirs and --force backups during install |
No |
The install cache is outside your project. It holds temporary staging copies and up to 10 recent backups when --force replaces skills. Safe to delete; run skills install to restore installed content from skills.lock.
Legacy projects may still have a .skills/ directory from older CLI versions. It is no longer created and can be removed manually.
Commands
| Command | Description |
|---|---|
skills init |
Create skills.toml |
skills init --rules |
Create skills.toml with [rules] sync enabled |
skills add <repo> [skills...] |
Add a Git bundle, discover all bundle assets by default, and install |
skills add <repo> --skills-only |
Discover and install skills only (no rules, prompts, or agents) |
skills add <repo> --bundle <name> --ref <ref> [skills...] |
Add with explicit bundle/ref/skill names |
skills install |
Install skills already registered in skills.toml |
skills install --locked |
CI mode: install exactly from lockfile, never update it |
skills update [skill] |
Refresh project skills from configured refs |
skills upgrade |
Upgrade the skills CLI program |
skills verify |
Fail if local skills drift from lockfile |
skills list |
Show skills with bundle, repo, ref, commit, status |
skills status |
Detailed per-skill status |
skills gitignore |
Sync .gitignore entries for managed skills |
skills rules sync [--check] [--force] |
Generate/update Cursor-visible rules from installed skills |
skills rules list |
List discovered skill-owned rules and generated targets |
skills rules clean [--force] |
Remove stale generated managed rules |
skills remove <skill> |
Remove from manifest, disk, and lockfile |
skills install does not accept a repository URL. Use skills add <repo> instead.
Flags
--skills-onlyonadd: discover and install skills only (legacy behavior for skill-only repos)--register-onlyonadd: updateskills.tomlwithout fetching or installing--forceonadd/install/update: overwrite unmanaged or locally modified skills (creates backup under the system cache,$XDG_CACHE_HOME/skills/<project-id>/backups/)--lockedoninstall: require an existing, consistentskills.lock
Source repository layout
Remote repositories can use either layout:
Cursor bundle layout (multiple skills in one repo):
.cursor/skills/<skill-name>/SKILL.md
.cursor/skills/<skill-name>/...
Repository skills layout (e.g. lmrco/.cursor):
skills/<skill-name>/SKILL.md
skills/<skill-name>/...
Repo-root skill layout (single skill repository such as rust-skills):
SKILL.md
rules/...
For repo-root skills, the skill name is read from the name: field in SKILL.md frontmatter.
Example bundle repository structure:
my-cursor-skills/
.cursor/
skills/
code-review/
SKILL.md
commit-message/
SKILL.md
Cursor assets
skills is a lock-first Cursor bundle manager. In addition to skills, a bundle can install top-level rules, prompts, agents, and AGENTS.md from a Git repository.
Cursor-root bundle layout (for example lmrco/.cursor):
skills/<name>/SKILL.md
rules/<name>.mdc
prompts/<name>.md
agents/<name>.md
AGENTS.md
Installed targets (defaults derived from target = ".cursor/skills"):
.cursor/skills/<name>/
.cursor/rules/<filename>
.cursor/prompts/<filename>
.cursor/agents/<filename>
.cursor/AGENTS.md
Example skills.toml bundle:
[targets]
cursor = ".cursor"
skills = ".cursor/skills"
rules = ".cursor/rules"
prompts = ".cursor/prompts"
agents = ".cursor/agents"
[[bundles]]
name = "cursor"
repo = "https://github.com/lmrco/.cursor"
ref = "main"
source_root = "auto"
skills = ["api-review"]
rules = ["style"]
prompts = ["review-code"]
agents = ["code-reviewer"]
files = ["AGENTS.md"]
CLI examples:
skills add https://github.com/lmrco/.cursor
skills add https://github.com/lmrco/.cursor --all-cursor
skills add https://github.com/lmrco/.cursor --skills-only
Bare skills add <repo> (no selectors) is equivalent to --all-cursor: it discovers all skills, rules, prompts, agents, and AGENTS.md. Use --all-cursor when you want to be explicit, or --skills-only for skill-only installs.
Explicit selectors (unchanged):
skills add https://github.com/lmrco/.cursor \
--bundle cursor \
--skill api-review \
--rule style \
--prompt review-code \
--agent code-reviewer \
--file AGENTS.md
skills remove --rule style
skills update --prompt review-code
source_root = "auto" detects whether assets live at the repository root (skills/, rules/, …) or under .cursor/.
Bundle top-level rules are installed verbatim to .cursor/rules/. That is separate from optional skill-owned rule sync (skills rules sync), which copies rules nested inside installed skills into generated .cursor/rules/skills--* files when [rules] is enabled.
Locked bundle assets appear in skills.lock:
[[assets]]
kind = "rule"
name = "style"
bundle = "cursor"
repo = "https://github.com/lmrco/.cursor"
requested_ref = "main"
resolved_commit = "abc123..."
source_root = "."
source_path = "rules/style.mdc"
installed_to = ".cursor/rules/style.mdc"
content_hash = "blake3:..."
installed_at = "2026-05-25T12:00:00Z"
Git authentication examples
GitLab SSH (recommended)
skills add git@gitlab.company.com:ai/cursor-skills.git \
--bundle platform-skills \
--ref v1.0.0 \
code-review
Ensure your SSH key is loaded:
ssh-add -l
ssh -T git@gitlab.company.com
GitLab HTTPS
skills add https://gitlab.company.com/ai/cursor-skills.git \
--bundle platform-skills \
--ref main \
code-review
Use Git credential helpers or a personal access token via standard Git mechanisms. skills does not store credentials.
Self-hosted GitLab / GitHub Enterprise / Azure DevOps / Bitbucket
Pass any Git-compatible URL as an opaque string:
skills add https://git.company.com/scm/team/skills.git \
--bundle team-skills \
--ref release-2026.05 \
team-review
skills add git@github.company.com:org/cursor-skills.git \
--bundle org-skills \
--ref v2.3.1 \
security-review
Version control (like .gitmodules)
Treat remote skill bundles like Git submodules: commit configuration and lock state, not installed content.
After clone, every developer gets identical skills:
skills install
skills verify
When you intentionally want newer commits from configured refs:
skills update
See Install semantics for the full model.
Manifest and lockfile
skills.toml — desired state:
version = 1
target = ".cursor/skills"
[[bundles]]
name = "platform-skills"
repo = "git@gitlab.company.com:ai/cursor-skills.git"
ref = "v1.0.0"
skills = ["that-skill", "other-skill"]
skills.lock — pinned state (auto-generated, sorted deterministically):
version = 1
generated_by = "skills"
[[bundles]]
name = "platform-skills"
repo = "git@gitlab.company.com:ai/cursor-skills.git"
requested_ref = "v1.0.0"
resolved_commit = "abc123..."
locked_at = "2026-05-25T12:00:00Z"
[[skills]]
name = "that-skill"
bundle = "platform-skills"
repo = "git@gitlab.company.com:ai/cursor-skills.git"
requested_ref = "v1.0.0"
resolved_commit = "abc123..."
source_path = ".cursor/skills/that-skill"
installed_to = ".cursor/skills/that-skill"
content_hash = "blake3:..."
installed_at = "2026-05-25T12:00:00Z"
Cursor rules sync
Cursor Skills and Cursor Rules use separate loading mechanisms. Skill-owned rule files live inside each installed skill:
.cursor/skills/api-review/
├── SKILL.md
└── rules/
└── api-add-pagination-for-list-endpoints-backend.md
When rules sync is enabled, skills copies them into Cursor-visible project rules (extension preserved):
.cursor/rules/skills--api-review--api-add-pagination-for-list-endpoints-backend.md
The skill-owned file remains the source of truth. Generated files under .cursor/rules/ are managed content — copy-based, hash-tracked, and regenerated on install/update.
Enable with skills init --rules or add to skills.toml:
[rules]
enabled = true
target = ".cursor/rules"
source_dirs = ["rules"]
include = ["*.md", "*.mdc"]
layout = "flat"
filename_template = "skills--{skill}--{rule}.{ext}"
delete_stale = true
conflict = "error"
sync_on_install = true
sync_on_update = true
sync_on_remove = true
gitignore = true
Rules sync runs automatically on skills install, skills update, and skills remove when the corresponding sync_on_* flags are true. Manual control:
skills rules list
skills rules sync
skills rules sync --check # CI: exit non-zero if out of sync
skills rules sync --force # overwrite conflicting unmanaged targets
skills rules clean
Locked rules appear in skills.lock:
[[rules]]
name = "api-add-pagination-for-list-endpoints-backend"
skill = "api-review"
source_path = ".cursor/skills/api-review/rules/api-add-pagination-for-list-endpoints-backend.md"
target_path = ".cursor/rules/skills--api-review--api-add-pagination-for-list-endpoints-backend.md"
content_hash = "blake3:..."
generated_by = "skills"
skills verify also checks generated rules when [rules].enabled = true.
CI / locked mode
skills install --locked is CI mode. It:
- requires
skills.lock - validates
skills.tomlandskills.lockare consistent before any Git work - installs exact locked commits (not branch heads)
- never updates, rewrites, or reorders
skills.lock - fails on drift, stale lock entries, or content hash mismatch
skills install --locked
skills verify
install --locked fails if:
skills.lockis missing- a bundle or skill exists in one file but not the other
- repo, ref, source path, installed path, or content hash do not match
- the remote no longer contains the locked commit
Safety model
- no telemetry
- system Git only (no provider APIs)
- no script execution during install
- symlinks blocked by default
- staged installs in system temp (removed after success)
--forcebackups under$XDG_CACHE_HOME/skills/<project-id>/backups/(keeps 10 most recent)- lockfile content hashes (BLAKE3)
skills verifydetects local drift againstskills.lock(skills and generated rules)
Cross-platform determinism
- lockfile paths always use
/ - content hashes normalize relative paths with
/separators - hashes include file bytes only (no mtime, permissions, or platform metadata)
- identical skill trees produce identical hashes on Linux, macOS, and Windows
Security
- No script execution during install
- Symlinks in skill directories are rejected
- Path traversal and unsafe skill names are blocked
- Unmanaged existing skill directories are not overwritten without
--force - Unmanaged existing generated Cursor rules are not overwritten without
--force - Locally modified managed skills are not overwritten without
--force - Locally modified generated rules are not overwritten without
--force - Content hashes use deterministic BLAKE3 over sorted relative paths and file bytes
Development
cargo fmt
cargo test
cargo fmt --check
Run the CLI from the workspace:
cargo run -p skills-cli -- init
cargo run -p skills-cli -- --help
License
MIT