Skills
What a skill is, how to write, enable, and check one reached a session, and how to read its version history.
A skill is a packaged bundle of instructions — a SKILL.md plus any supporting files —
that an agent can follow while it works. Every skill in your catalog belongs to some
workspace: yours, or a group above it that shares skills down through the hierarchy.
Either way, you decide which ones apply to your work.
This is a different thing from an agent’s capability tags, which describe what an agent can do for fleet placement. A skill is a set of instructions; a capability tag is a label used to match agents to tasks.
Finding the catalog
From the web app: open Set up → Skills. Every member of the workspace can see this page — reading the catalog doesn’t require any special role.
From the CLI: ch skill list — add --enabled or --disabled to narrow it
to one state; see Listing enabled and disabled records.
Before you turn a skill on, it’s worth reading it — a skill is instructions an agent will
actually follow, so it’s worth knowing what you’re switching on. Click a skill’s row to open
its own page: its metadata alongside its files, with the file list on the left and the
selected file’s contents on the right. That view is read-only unless it’s a skill your own
workspace defined and you’re an owner or admin, in which case the same page is the editor.
You can also read any skill from the CLI with ch skill show <slug> — it resolves the same
way the web app does, so it finds a skill your own workspace wrote or one inherited from a
parent group.
Source and Selection — two questions, two columns
The catalog list shows two columns, and they answer two different questions:
- Source — who may edit this skill’s definition. One of This workspace or
Inherited from
<group>. - Selection — where your workspace’s on/off choice for it came from. One of Set
here, Inherited from
<group>, or Default (on) / Default (off) when nobody in the chain has made a choice.
These disagree all the time, and that’s normal — a skill owned by a group above you that
you’ve switched on for your own workspace is Source Inherited from <group>, Selection
Set here. A group’s Selection choice applies to every workspace beneath it; a
workspace’s own choice always wins over its group’s, including turning a skill off that
the group turned on. See Managing workspaces for how groups and their
descendants fit together.
One CLI gotcha worth knowing: ch skill list’s SOURCE column is the Selection axis
above, not the web app’s Source column, and the CLI doesn’t show ownership at all.
Turning a skill on or off
From the web app: click Enable or Disable on the skill’s row. Once your workspace has made its own choice, a Reset selection button appears — it clears your workspace’s choice and returns the skill to whatever it inherits (a parent group’s choice, or the catalog default if there’s no group choice either).
From the CLI:
ch skill enable <slug>
ch skill disable <slug>
ch skill reset <slug>
These commands act on the workspace set by your CH_WORKSPACE_ID environment variable —
see Agents and the CLI for getting ch set up. Use reset, not
“unset,” “revert,” or “clear” — it’s the one word CodeHerder uses everywhere for this
action.
Enabling a skill can be refused if your workspace’s combined enabled skills would go over their size budget — see The workspace-wide size budget below for what counts and what to do about it.
Writing your own skill
Click New skill on the Skills page to open the workbench: a file list on the left, with an Add file action, a running count of how many files you’ve added out of the 64-file limit, and a meter for the skill’s total size; an editor pane on the right shows whichever file is selected.
SKILL.md is always the first file, and it can’t be removed or renamed — it’s the one
file every skill needs. Its frontmatter is the only place a skill’s name, description, and
version live: the Slug, Description, and Version fields above the file list read and write
that frontmatter directly, so typing a slug keeps SKILL.md’s name: field in step.
Description is required.
A checkbox, Enable in this workspace now, turns the skill on for your workspace as part of creating it — it takes effect at the next session the same as any other enable.
A skill has to stay within these limits:
- Slug: 2–64 characters, lowercase letters, numbers, and hyphens, starting with a letter or a number.
- Up to 64 files, including
SKILL.md. - 256 KB per file, 512 KB total per skill.
- Text file extensions:
.md,.txt,.json,.yaml,.yml,.csv. - Script file extensions:
.sh,.bash,.py,.js,.mjs,.cjs,.ts. - Paths are relative and slash-separated, with no
..segments. - Your workspace’s enabled skills also share a combined 2 MB size budget — see The workspace-wide size budget below.
A new slug has to be unique across your whole workspace tree — it can’t already belong to one defined on a parent group, one already in your workspace, or one in a descendant workspace. So a workspace can never shadow a skill it inherits.
From the CLI
You can also keep a skill in a folder in your repository and publish it from CI. Put
SKILL.md and the skill’s other files in one folder. Then run:
ch skill create --from-dir ./skills/samplewriter
The skill’s slug is the name: in SKILL.md. The folder holds every file of the skill.
ch uploads every file in it, including hidden files, and refuses a symbolic link. A new
skill starts disabled. Run ch skill enable <slug> to turn it on.
ch checks the folder with the same rules as the web app: the same file types, the same
size limits, and the same frontmatter rules. A problem names the file at fault, for
example ./skills/samplewriter/run.exe: file type not allowed. When there is a problem,
ch sends nothing.
Add --dry-run to see what would change. It saves nothing. It cannot see a slug that a
descendant workspace already uses. It does not run the malware scan. It does not check the
workspace-wide size budget.
ch skill list, show, enable, disable, reset, and versions stay as they were.
Editing, renaming, and deleting
Only a skill your workspace defined is editable from that workspace’s page — an inherited one opens read-only, with a note on which workspace to go edit it in.
The slug is a skill’s identity and can’t be changed once it’s created; to rename one, delete it and create it again under the new slug. The new slug starts its own version history from scratch — it doesn’t inherit anything from the one you deleted. If you navigate away from the editor with unsaved changes, CodeHerder asks you to confirm first.
Delete removes the skill’s definition and files, along with every workspace’s enable/disable choice for it, behind a typed confirmation. A session spawned after the delete simply doesn’t get it; a session that’s already running is unaffected. Only a skill your workspace owns can be deleted. Its retained versions stay readable after the delete — see Version history below.
From the CLI, ch skill edit <slug> --from-dir <folder> replaces all the skill’s files with
the folder’s files. A file that is not in the folder is removed. Add --dry-run to see each
file as added, removed, changed, or unchanged. ch skill delete <slug> deletes the skill. It
asks you to confirm. In CI, add --yes. You cannot undo a delete.
Version history
CodeHerder keeps a full retained history of a skill’s files. Every time a skill is created or edited, it retains the file set as a new version — unless the bytes are identical to a version it already has, in which case it just marks that version current again instead of adding a new one. Turning a skill on or off, resetting a selection, and duplicating one don’t touch history at all.
That last rule matters for Revert: reverting to an earlier version doesn’t add a new version on top. It makes that earlier version current again. So reverting twice in a row lands you back where you started, and the version count never grows just from going back and forth.
A version has no author — its identity is its content hash, not a person. Each one records its version number, content hash, when it was first retained, and its file count and size.
From the web app: open a skill’s page and its Version history panel lists every retained version, newest first. Compare shows a file-by-file diff between any two versions, and the pair you’re comparing lives in the page’s own address, so you can share a link straight to that diff. Revert sits behind a confirmation and needs an owner or admin — and only works on a skill your own workspace owns. An inherited skill’s panel offers Compare but not Revert.
Speaking of inherited: a skill’s version history belongs to whichever workspace actually owns it, the same as the skill itself. If your workspace enabled a skill from a parent group, its history lives with that group, and the panel says so.
From the CLI: ch skill versions <slug> lists the history, with --limit and --cursor
to page it. Add --version N or --hash <sha256> to read one version in full, files and
all — the two are mutually exclusive. Reading history only needs regular membership;
there’s no revert command in the CLI, since revert is an app-only action.
The workspace-wide size budget
Beyond the per-skill limits above, your workspace’s enabled skills share a combined size budget: 2 MB (2,097,152 bytes) total, across every skill switched on for your workspace — your own and any inherited from a group above you. CodeHerder checks this the moment you make a change, not later: it’s a refusal, not something that quietly drops a skill once a session starts.
Not every change can hit this budget:
- Turning a skill on can be refused if it would push your workspace over the limit.
- Editing a skill that’s currently on can be refused too, if the edit grows it enough to go over.
- Creating a new skill is never refused — a new skill starts switched off, so it adds nothing to the total until you enable it.
- Editing a skill that’s switched off is never refused, for the same reason.
- Turning a skill off is never refused — it can only shrink the total.
If you create a skill with Enable in this workspace now checked while your workspace is near the limit, the skill is still created; only the enable step is refused. Free up some room, then turn it on separately.
If you hit this limit, disable a skill you’re not using, or shrink one. ch skill list
prints a BYTES column for every skill, so you can see where the weight is before deciding
what to trim.
Starting from a skill that already exists
An inherited skill’s page has a Duplicate to this workspace button (visible to an
owner or admin). It opens the create form pre-filled with that skill’s files, under a slug
like <slug>-copy that you’re free to change before saving.
Skills owned by a group
A skill can also be owned by a group rather than a single workspace — the same way devices, repositories, and agents can be. When it is, every workspace nested beneath that group can see it in the catalog and enable it for itself, and only the group can edit or delete it. See Managing workspaces for how groups and the workspaces beneath them relate.
Who can change what
Creating, editing, deleting, enabling, disabling, and resetting all need a workspace
owner or admin, and a human token — an agent’s own token can’t change workspace
settings, so an agent can’t do any of this for itself. The ch skill commands follow the
same rule. In CI, use a human owner’s or admin’s member key. Everyone else sees the same pages
read-only, and reading the catalog only needs regular membership.
What happens after you turn one on
It takes effect on the next session, not the one running now. A session that’s already in flight keeps whatever it started with — turning a skill on or off doesn’t reach back into work that’s already underway. This is the same whether the skill is one you wrote yourself or one you inherited from a group; delivery doesn’t care where a skill came from.
When a new session starts, CodeHerder puts the skill’s files into that session’s working copy and points the agent at them, in whichever way its CLI expects — usually by linking them into the folder that CLI reads its skills from, so the agent can use the skill the same way it would use one already checked into the repo. Every coding CLI CodeHerder can launch for a task gets this treatment; see the harness table on Agents and the CLI for the full list.
Script files
A skill can carry helper scripts, for example scripts/setup.mjs. Scripts follow the same
limits as other files. They count toward the file count and the size budgets.
- The agent sees each script at the same relative path.
- A script that starts with a
#!line is installed as executable. - A script without a
#!line is installed as a plain file. The agent can still run it with its interpreter. - CodeHerder never runs a skill script. The agent runs a script when the skill tells it to.
- The skill page marks each script, so an admin can see what executable content a skill carries.
- A device on an older version installs scripts as plain files, not executable.
Your own copy always wins: if your repo already has a folder with the same name as the skill, CodeHerder leaves it exactly as it is and doesn’t deliver the catalog copy on top of it. Nothing in your repo is ever overwritten.
Nothing about this is committed. The delivered files are excluded from git in that clone, so
they never show up in git status and never end up in a commit or a merge request.
Turning a skill off works the same way in reverse: on the next session, CodeHerder removes what it had delivered — again, not retroactively into a session that’s already running.
Two limits worth knowing:
- Only task sessions get skills. A session you start on a device doesn’t go through this delivery step, so it never gets a Skills section either.
- A device needs a current release to deliver anything. An older release doesn’t inject skills at all, and a session run on it shows no Skills section on its page. Devices update themselves automatically by default, so this only shows up on a device that’s stuck.
Checking that a skill reached a session
Open a task session’s page and look for the Skills section, below the session summary. It lists every skill the session was eligible to receive, each with an outcome:
- linked — linked into the agent’s skills folder for this session.
- already there — it was already linked there; nothing to do.
- copied — copied instead of linked, because that device’s filesystem doesn’t support linking.
- skipped — your repo already has its own folder with that name, so CodeHerder left it alone. This is the same “your own copy always wins” rule above, not a bug.
- removed — the skill is no longer enabled, so CodeHerder removed the copy it had previously delivered.
- Not found / Turned off — the session’s workflow stage narrowed its own skills to a specific list, and one of the names on that list didn’t resolve, or resolved to a skill your workspace has switched off. See Which skills a stage gets for what a stage’s own selection is and how to set one.
Alongside the per-skill list, a counter row totals how many skills were enabled, linked, already linked, copied, skipped, and removed for that session — plus, when the session’s stage narrowed the set, how many it selected.
If the section says no skills are enabled for the workspace, follow its link to turn some
on. If it says CodeHerder doesn’t know a skills folder for the agent’s CLI, that session was
launched with a raw command CodeHerder doesn’t recognize as one of the supported CLIs, so it
can’t tell where that CLI keeps its skills — nothing was injected. A pi session shows only
the counter row with no per-skill list, since pi is handed its skills bundle directly
rather than through a folder to link into.
Related guides
- Version history and going back — how a skill’s history compares to the other things CodeHerder keeps a history of.
- Which skills a stage gets — narrow a workflow stage’s sessions to a specific list instead of the workspace’s whole enabled set.
- Managing workspaces — groups, nesting, and how a group’s settings reach the workspaces beneath it.
- Agents and the CLI — set up
ch, includingCH_WORKSPACE_ID. - Agent personas and system prompts — the other way to shape agent behavior, per-agent rather than per-workspace.
- Workspace wiki — the other shared, inherited store your workspace keeps.
Last updated