TL;DR: A skill is a single markdown file that teaches the agent a habit — drop it in ~/.claude/skills/<name>/SKILL.md (user-wide) or .claude/skills/<name>/SKILL.md (project-wide). The agent picks it up automatically based on its description field.
A skill is the smallest way to teach the agent a habit. One markdown file, two fields, three sentences of instruction. Drop it in the right folder; the agent picks it up next turn and behaves differently forever. This tutorial covers what a skill actually is, where it lives, and the two ways to install one someone else wrote.
Before you write your own, install someone else's. That's the right way to learn — the same way you'd brew install a tool before reading its source. A skill is a small, opinionated unit of agent behavior: "when X comes up, do Y this specific way." Someone on your team writes one for the convention they're tired of explaining. They hand it to you. You drop it in a folder. The agent now knows.
The whole mechanism is simpler than it sounds. The agent reads a one-line description of every available skill on every turn. If the description matches what you're doing, the agent loads the skill's body — usually a few paragraphs of plain English — and follows the instructions inside. No build step, no runtime, no plugin manager required for the basic case.
This tutorial is the consumer side. If you want to write your own skill from scratch, head to Write a custom skill after you finish here.
SKILL.md fileOpen any skill someone shared with you. It will look something like this:
---
name: test-before-commit
description: Use when the user says "commit", "push", or "ship". Always run `npm test` first and report the result before staging anything.
---
Before any commit, run the project's test suite:
1. Check for a `package.json` and run `npm test` (or the equivalent for the stack).
2. If tests pass, proceed with staging and the commit.
3. If tests fail, stop and surface the failure — do not commit.
That's it. The YAML frontmatter at the top has two required fields: name (used to invoke the skill manually) and description (used by the agent to decide when to load it). The markdown below is the actual instruction — what the agent should do when the skill fires.
The description is the load-bearing piece. The agent reads it on every turn alongside every other skill's description and decides whether the current situation matches. A specific description like "when the user says commit, push, or ship" wins; a vague one like "helps with testing" gets ignored.
CLAUDE.md is always loaded — use it for project-wide invariants. A skill is loaded only when its description matches — use it for situational habits. An MCP server adds new capabilities (talking to APIs, querying databases) — use it when the agent needs something it can't already do.
LingCode is more than the Mac app — there's also the lingcode CLI and the Claude-provider chat panel, which run under a separate (older) loader. The two readers look in different directories, and you need to know which one you're targeting.
| If you use… | Skills live in… |
|---|---|
| LingCode Mac app — the slash-command popup and the skill-drafts review panel | ~/.cursor/skills/<name>/SKILL.md (user-wide).cursor/skills/<name>/SKILL.md (per-project, alongside your code) |
lingcode CLI or the Claude provider in any chat |
~/.claude/skills/<name>/SKILL.md (user-wide).claude/skills/<name>/SKILL.md (per-project) |
Project-local wins over user-wide if both define the same skill — useful for "this repo overrides my personal habit."
~/.cursor/skills/ is invisible to the CLI; a skill in ~/.claude/skills/ is invisible to the Mac app's slash menu. If you want it available everywhere, drop the same file in both. This is the most common reason a "freshly installed" skill seems to do nothing.
The simplest install: someone hands you a SKILL.md file (or pastes its contents). You want it available to the Mac app's slash menu.
# 1. Make the folder. The folder name becomes the skill name.
mkdir -p ~/.cursor/skills/test-before-commit
# 2. Save the SKILL.md inside it.
mv ~/Downloads/SKILL.md ~/.cursor/skills/test-before-commit/
# 3. Confirm the layout.
ls ~/.cursor/skills/test-before-commit/
# → SKILL.md
For a project-scoped install — for example, a skill that's only relevant to this repo's conventions — substitute .cursor/skills/ at the project root for ~/.cursor/skills/. Commit the folder to git so your team gets it on next pull.
Verify it loaded:
/, and look for your skill's name in the popup. If it's there, the agent sees it too./skills — every loaded skill is listed with its description.If someone shares a plugin instead of a loose file, that's just a folder with a .claude-plugin/plugin.json manifest and one or more skills inside. Install it once and every skill it bundles is available everywhere the plugin is loaded.
# Local folder (someone gave you a directory):
lingcode plugin install ./team-skills
# Git URL (a published plugin):
lingcode plugin install https://github.com/your-team/lingcode-plugin-ship-checklist
Skills inside a plugin are namespaced as <plugin>:<skill>, so two plugins that each ship a tdd skill don't collide. Invoke a namespaced one with /team-skills:tdd.
Plugins can also bundle hooks, slash commands, agents, and MCP server configs — anything more than skills is its own story. See Install and configure plugins for the full plugin model.
If the agent isn't picking up a skill you just installed, the cause is almost always one of these:
name: and description: in the YAML block. If either is missing or empty, the loader silently skips the skill — no error, just absence. Reopen the file and check.~/.cursor/skills/, not ~/.claude/skills/. CLI users: the reverse. If you're not sure which surface you're testing on, drop the file in both directories./<skill-name>./your-skill-name at the start of your message will load the skill explicitly. Use this to confirm the file is parseable before you go hunting for description-tuning issues.