# Skills

> Give agents skills, folders of instructions and scripts they follow, shared across agents and versioned.

A **skill** is a folder that tells an agent how to do one thing: a `SKILL.md` with the steps, and any scripts, templates or references it uses. It's the [Agent Skills](https://agentskills.io) format Claude Code, Codex and the other coding harnesses read, so a skill you already have locally works as it is. A skill belongs to your account (or one user) on its own, so several agents can use it, and every change to it is a new version.

## Make a skill

`SKILL.md` starts with a frontmatter block: `name` (lowercase letters and digits, words joined by single hyphens, up to 64) and `description` (what it does and when to use it, up to 1,024 characters). The agent decides when to use a skill from its description, so say both.

```python
import noclick

check = noclick.Skill.create({
    "SKILL.md": """---
name: invoice-check
description: Check an invoice against its purchase order. Use when an invoice arrives.
---
1. Read the invoice's lines with scripts/lines.py.
2. Match each line to the order with scripts/match.py, and flag what differs.
""",
    "scripts/lines.py": open("lines.py").read(),
    "scripts/match.py": open("match.py").read(),
})
same = noclick.Skill.from_dir("./skills/invoice-check")   # or the whole folder from disk
```

```ts
import { Skill } from "noclick";

const check = await Skill.create({
  "SKILL.md": "---\nname: invoice-check\ndescription: Check an invoice against its purchase order. Use when an invoice arrives.\n---\n1. Read the invoice's lines with scripts/lines.py.\n",
  "scripts/lines.py": "import sys\n# ...\n",
});
```

A file that isn't text goes as bytes (`Uint8Array` in TypeScript). A folder holds up to 200 files and 20 MB, `SKILL.md` up to 64 KB. A name is unique among your account's skills (or a user's): a taken one raises `noclick.Conflict` with `existing_id`, and `allow_existing=True` returns the skill already there.

Add `always: true` to the frontmatter for standing instructions every turn should follow (a tone of voice, house rules): the agent then gets the whole of it in every turn instead of choosing when to read it.

## Give agents skills

```python
support = noclick.Agent.from_name("support", create_if_missing=True, instructions="Help customers.",
                                  skills=[check])                      # follows the latest version
closer = noclick.Agent.from_name("closer", create_if_missing=True, instructions="Close deals.",
                                 skills=[check.pinned(1)])             # holds version 1
support.update(skills=[])                                            # takes them all off
```

```ts
import { Agent, Skill } from "noclick";

const check = Skill.fromName("invoice-check");
const support = Agent.fromName("support", { createIfMissing: true, instructions: "Help customers.", skills: [check] });
await Agent.fromName("closer").update({ skills: [check.pinned(1)] });
```

An agent uses up to 20 skills, in the order you give them, and the agent's `skills` lists each as `{id, pin}` (`pin` null: the latest). An agent uses skills of its own scope, and a user's agent the account's too; never another user's. Two skills on one agent can't go by the same name.

How the agent reads them depends on what runs it:

- **A coding harness** (Claude Code, Codex, OpenCode, Hermes, OpenClaw) finds each skill where it reads skills (Claude Code's `~/.claude/skills`, Codex's `~/.agents/skills`, and the like) when its sandbox starts, and uses it as it would on your laptop, scripts included. Attaching one, taking one off, or a new version of one it follows restarts its sandbox at its next turn; its conversations carry on.
- **NoClick's own loop** (`sdk`) sees each skill's name and description every turn and reads one with `skill__read` (its `SKILL.md`, or any other file by path) before it follows it.

## Versions

Every save is a version. `save_version` (`saveVersion` in TypeScript) writes files over the latest (or the whole folder with `replace=True`) and takes `removed` paths out; `base_version` saves only while the latest is still that version, so two people editing at once don't overwrite each other. Saving the same content again makes no version.

```python
check.save_version({"scripts/match.py": open("match.py").read()}, base_version=check.version)
check.update(description="Check invoices and flag those over budget.")    # a new version with SKILL.md's frontmatter rewritten
for v in check.versions():
    print(v.version, v.created_by.type, [f.path for f in v.files])
print(check.read("scripts/match.py", version=1).content)
check.restore(1)                                        # a new version holding what version 1 held
```

```ts
import { Skill } from "noclick";

const check = await Skill.get("skill_id");
await check.saveVersion({ "scripts/match.py": "print('v2')\n" }, { baseVersion: check.version });
for (const v of await check.versions()) console.log(v.version, v.createdBy.type);
await check.restore(1);
```

Renaming a skill (`update(name=...)`) is a version too. `attached_to` lists the agents using it and the version each holds.

## Delete and restore

`delete()` moves a skill to the [trash](https://www.noclick.com/docs/guide/undo.md), restorable for 30 days, and takes it off every agent that uses it; restoring it puts it back on them, each at the version it held. Purging it from the trash deletes its versions and files for good.

## Limits and billing

- 200 files and 20 MB a version, `SKILL.md` up to 64 KB, 20 skills an agent, and an agent's skills together up to 20 MB.
- Skills are free to keep.

## Errors

| Error | When |
| --- | --- |
| `noclick.InvalidRequest` | A folder without `SKILL.md` or its frontmatter, a bad name or description, a path outside the folder, two skills on one agent going by one name. |
| `noclick.Conflict` | A name that's taken (`existing_id`), or a save over a `base_version` the skill moved on from (`current_version`). |
| `noclick.QuotaExceeded` | Over a limit above. |
| `noclick.PermissionDenied` | A user's skill on an agent outside its user, or changing the account's skill from a call acting for a user. |
