Skills, explained.
A skill is a piece of folded-up procedural knowledge: a recipe carlos can reach for when a task fits its description. You can write skills by hand. You can drop the ones the open agentskills.io standard already publishes into a folder. And here's the distinguishing part: carlos can watch a transcript, notice that a piece of work probably wants to be reusable, and propose a new skill for you to review before it ever lands on disk. Nothing auto-publishes. The human is always the gate.
01What a skill is.
A skill is a directory containing a SKILL.md file with YAML frontmatter and a markdown body. Frontmatter declares the metadata; the body is the prompt content the model loads when the skill is relevant. Optional scripts/ and reference/ subdirectories can ship alongside for deterministic code or supporting docs.
Frontmatter fields
name. Kebab-case identifier; must match the enclosing directory or the bundle file name.description. Load-bearing. Used to retrieve the skill on intent match. Phrase it as "Use when …" describing the triggering condition, not the implementation.backend,frame_default,frames. Optional, route the skill to a specific provider or frame (per Capability config).triggers,tools. Optional, legacy keyword hints and required-tool declarations kept for forward compatibility.provenance. One ofinduced/hand-written/imported. Hand-written is the default for anything you author.
Caps: body up to ~20,000 chars (≈5,000 tokens), 50 files per skill directory. Bigger than that, split it.
Example shapes
Three real skills from this codebase, switchable below: a bundled one carlos ships with, a hand-written one a user might add, and an induced proposal as it lands in the approval queue before promotion.
--- name: calendar-apple description: Drive Calendar.app on macOS via osascript. Reads, creates, deletes events in the user's local Calendar database. backend: apple frame_default: personal triggers: [calendar, apple, ical, schedule, event, meeting] --- # calendar-apple You drive Calendar.app on macOS through `osascript`. This skill only works on darwin. If the host is Linux, stop and tell the user to switch backends. Run every AppleScript snippet via the `bash` tool: tool: bash args: command: osascript -e '<applescript here>'
--- name: release-bump description: Use when the user asks to cut a new release of this project. Bumps the version in go.mod aux, regenerates the CHANGELOG via git-cliff, drafts release notes, and tags. provenance: hand-written --- # release-bump Steps, in order. Each is a single tool call. Never bundle. 1. Read VERSION. Parse it. Confirm the bump kind (major/minor/patch) with the user before changing anything. 2. Run `git-cliff --unreleased` to draft the changelog delta. Show the user; let them edit before commit. 3. Update VERSION and CHANGELOG.md in a single commit titled `release: vX.Y.Z` (no emoji prefix; releases use plain prefixes). 4. Tag with `git tag -s vX.Y.Z` and push only when explicitly asked. Never push to main without the user's explicit OK.
--- name: gh-pr-from-branch description: Use when the user asks to open a PR for the current branch and the branch has unpushed commits. Pushes with -u, drafts a title and body from the diff, and opens via gh pr create. provenance: induced inducer_model: anthropic:claude-sonnet-4-7 induced_from: [agent-7f3e, agent-7f9c] --- # gh-pr-from-branch # Confidence: 0.82 from replay-eval against 14 historical transcripts # Reuse predicted: 6 invocations / 30d Verify the branch exists on origin (`git rev-parse --abbrev-ref --symbolic-full-name @{u}`); if not, push with -u. Then run `gh pr create` with a title under 70 chars and a body built from the diff summary…
02Where they live.
Carlos looks for skills in four locations, in priority order. Later wins on name collision, so a project-local skill overrides a user-level one of the same name. Carlos respects both the Claude convention (.claude/skills) and the open agentskills.io standard (.agents/skills), so you don't have to choose.
- 1~/.claude/skills/user · Claude convention
- 2~/.agents/skills/user · open standard
- 3<projectRoot>/.claude/skills/project · Claude convention
- 4<projectRoot>/.agents/skills/project · open standard
Two layouts are supported: a single-skill directory with one SKILL.md plus optional scripts/ and reference/ subdirs; and a bundle directory with multiple .md files, one per skill, each carrying its own frontmatter. The shipped calendar bundle uses the second shape to namespace six related skills (calendar, calendar-apple, calendar-caldav, calendar-ics-file, calendar-mcp, calendar-cross-frame-view) without spawning six sibling directories.
03Authoring a new skill.
The smallest possible flow:
- Pick a name. Make a directory:
~/.agents/skills/your-skill-name/. - Drop a
SKILL.mdin it with the frontmatter from §1. - Write the body as if you were instructing a careful intern. Be concrete about steps, tool calls, and when to stop and ask.
- Restart your carlos session, or just open a new chat. Skills are scanned at session start.
That's it. No build step, no install command, no manifest registry. The description is what gets matched against intent, so phrase it as "Use when …". That wording is load-bearing. If the description is vague, carlos can't reach for it; if it's too narrow, it'll be invisible to adjacent tasks that should have triggered it.
Naming and shape rules of thumb
- One skill should do one thing. If a skill needs branching logic for completely different cases, it's probably two skills with a shared entry-point dispatcher.
- Prefer executable scripts in
scripts/over long prose. Deterministic operations belong in code; prose lives in the body to explain when and why. - If your skill depends on a tool that may not exist (
gh,osascript,jq), check for it explicitly and stop with a clear message instead of failing mid-flight. - Skills are cheap. Write one for any procedure you've explained more than twice.
04How carlos proposes skills.
The distinguishing piece. Carlos watches transcripts and, when it spots a chunk of work that's likely reusable, generates a SKILL.md proposal in the same shape you'd hand-author, then routes it through the same approval queue your plans and diffs go through. Nothing publishes itself. The model proposes; the human disposes.
skill: <name>. You accept, reject, or edit before accepting..agents/skills/<name>/ (or your configured location). On reject, the proposal is discarded but the rejection is logged so the inducer can learn what shape you didn't want.The architectural commitment is the human gate. Even with perfect replay scoring, carlos will not auto-publish a skill. The cost of a wrong skill is high (every future session loads it on relevance match), and the cost of pausing for a one-second approval is low. That asymmetry is why the queue exists.
05What's in scope, what isn't.
Honest about where the system is today, since this is a v0 area still moving.
working today
- Hand-authored skills in all five search paths.
- Bundled calendar skills shipped in the binary.
- Induction pass with structured proposal output.
- Optional replay-evaluator gating before the queue.
- Approval queue + accept/reject workflow.
- Curator: skills go
active → stale → archivedbased on use-recency; never hard-deleted.
still ahead
- Auto-triggered induction wired to the supervisor (today the caller invokes it explicitly).
- Real description-embedder (today's retrieval is a deterministic stub for v0; a real embedder comes when the cost is worth it).
- Skill versioning, dependencies, and sharing/marketplace. Local-only for now.
- A first-class
carlos skill newCLI scaffolder.
If you author a skill you think the world should have, the right place to share it today is the open agentskills.io ecosystem. Anything that follows that format works in carlos without modification, and anything you write for carlos works in the other clients that adopt the same standard. Skills are portable on purpose.
internal/skills/skill.go (data model), internal/skills/library.go (loader), internal/skills/inducer.go (proposal), internal/skills/skillwire/wire.go (queue + promotion), internal/skills/curator.go (lifecycle). Open standard: agentskills.io.