
# Agent Skills

> Write the agent skills that match your Sovrium version into a project, refresh them after an upgrade without touching what you edited, and check them in CI.

```text
Usage: sovrium skills [--output <dir>] [--target claude|agents|all] [--check] [--force]
```

An AI editing your config is only as good as what it knows about Sovrium. Left alone, it guesses from whatever it read during training: option names from an older release, a web page instead of the manual for your version, a config that validates but was never looked at in a browser. Agent skills close that gap. Each one is a short `SKILL.md` your AI reads when a task matches it, plus a `references/` folder it opens when it needs the detail.

The binary carries five of them:

| Skill                 | Use it for                                                                |
| --------------------- | ------------------------------------------------------------------------- |
| `sovrium-app`         | Any change to the config: the edit, validate, run, look, stop loop        |
| `sovrium-data-model`  | Tables, fields, field ids, relations                                      |
| `sovrium-pages`       | Pages, components, design                                                 |
| `sovrium-automations` | Triggers, actions, connections                                            |
| `sovrium-seo-geo`     | Metadata, sitemaps, languages, redirects, and how pages read to AI search |

Part of each `references/` folder is generated from the binary's own option descriptions, so a catalogue of field types or components always describes the version you run.

## What it writes

`sovrium skills` writes every skill into `.claude/skills/<name>/` under the current directory — the `SKILL.md` and its `references/` — and a `.sovrium-skills.json` beside them. `--output <dir>` writes under another project root instead.

The JSON file records, for every file it wrote, a SHA-256 of its bytes and the Sovrium version that wrote it. Commit it with the skills: it is how the next run knows which files are Sovrium's and which ones you changed. Each `SKILL.md` also names its version in its frontmatter, as `metadata.product-version`.

`sovrium init` writes the same skills when it scaffolds a project, whether from the default starter, a `--template`, a template repository or `--from-url`. It never overwrites a skill directory that is already there.

## Refreshing after an upgrade

After installing a new Sovrium version, run the command again:

```bash
sovrium skills
```

Files Sovrium wrote and you did not change are replaced with the new version's. A skill the new version no longer ships is removed, provided you did not edit it. A second run with nothing to do changes nothing.

## Files you edited

A file whose bytes no longer match what Sovrium recorded is yours now, and the command refuses to overwrite it. It exits 1 and names each such file. You can:

- keep your version, and leave that file stale on purpose, or
- run `sovrium skills --force` to take Sovrium's version. `--force` replaces only files Sovrium wrote; a file you added inside a skill folder stays.

A skill directory with a Sovrium name that Sovrium never wrote — your own `sovrium-app`, say — is refused even with `--force`: without the record, nothing proves it is Sovrium's to replace. Skills with other names are never read or touched.

### Symlinks

The command never writes, replaces or deletes anything through a symbolic link. If a skill folder, any file inside it, or `.sovrium-skills.json` is a link, it exits 1 naming the link and writes nothing, in any target. `--force` does not change that. Replace the link with a real file or folder, or remove it, then run the command again. `sovrium init` skips a skill whose folder is a link, says so, and writes the others.

The skills folder itself may be a link: pointing `.claude/skills` at `.agents/skills` to share one copy works, as long as the link resolves inside the project. A skills folder that leads outside the project is refused before anything is written.

## Checking in CI

```bash
sovrium skills --check
```

`--check` writes nothing. It exits 0 when every skill is current, and 1 when a file is missing, left over from an older version, or edited — listing each one. Run it in CI to catch a project whose skills fell behind the binary its pipeline pins.

## Other agents: `--target agents`

Claude Code reads `.claude/skills/`, and so does Cursor. Codex, GitHub Copilot, Gemini CLI and OpenCode read `.agents/skills/`.

```bash
sovrium skills --target agents   # .agents/skills/
sovrium skills --target all      # both directories
```

Each directory keeps its own `.sovrium-skills.json`, so each is refreshed and checked on its own. `claude` is the default.

## As MCP prompts

Claude Desktop has no shell to run `sovrium skills`, and does not read skill folders from your project. When it is connected through `sovrium mcp`, the same skills are there as MCP prompts: pick one from the prompt menu, and its `SKILL.md` text is added to the conversation. A prompt carries the `SKILL.md` alone, not its `references/`. **Your Config over MCP** covers connecting a client.

## What the skills are built on

The skills follow the Agent Skills format, and their advice is drawn from published sources: search-engine documentation for the SEO skill, public design and accessibility guidance for the pages skill, and published agent-skill collections for their structure. Each skill lists what it drew on, with the date and the licence, in its `references/sources.md`.

## Behaviour

### `sovrium skills` Writes the Binary's Agent Skills into a Project

- `sovrium skills` writes every embedded skill into `.claude/skills/<name>/` — its `SKILL.md` and every `references/*.md`, never an `evals/` file — plus the `.sovrium-skills.json` manifest
- Every written `SKILL.md` opens with frontmatter whose `name` equals its directory (at most 64 lowercase characters and hyphens), whose `description` is 1 to 1024 characters, and whose `metadata.product-version` equals `sovrium --version`
- The manifest carries `format: sovrium-skills`, `schemaVersion: 1`, the engine and the target, and lists every written file with a sha256 that matches its bytes on disk
- `--output <dir>` writes the skills and the manifest under `<dir>` and nothing under the current directory
- A second run with nothing changed is a no-op: exit 0, and no file or manifest byte changes
- After an engine change, the files the person did not edit are replaced, and the frontmatter stamp and the manifest engine move to the running version
- A file the person edited is refused: exit 1, nothing written, and the message names the file and `--force`
- `--force` overwrites an edited file the manifest lists, and leaves a file the manifest does not list untouched
- A same-name skill directory the manifest does not own is refused even with `--force`, and its files are left as they were
- With no manifest, files already byte-equal to the embedded skills are adopted into a new manifest rather than refused
- A skill of another name in the same directory is never read, rewritten or removed
- `--check` writes nothing and exits 1 listing each missing, stale and edited file, and exits 0 once the skills are current
- `--target agents` writes `.agents/skills/`, `--target all` writes both directories each with its own manifest, and an unknown target exits 1 naming the accepted values
- A skill the binary no longer ships is removed when unedited, and kept and reported when edited
- A project that still holds `.claude/agents/app-editor.md` is told in one line that the skills supersede it, and the file is never deleted
- `sovrium init`, bare and with `--template <slug>`, writes the skills and the manifest add-only: an existing `.claude/skills/<name>/` is kept as it was
- `sovrium init --from-url` and a remote `owner/repo` template write the skills the same way
- `sovrium skills --help` prints the usage and exits 0 without writing, and `sovrium --help` lists `skills`
- The compiled binary writes skills and a manifest byte-identical to the from-source run, from a clean directory
- `sovrium-app` names `sovrium docs` first as the manual, and the published llms.txt index only for a client that cannot run commands
- `sovrium-app` gives a verification loop naming `sovrium validate`, `sovrium start --watch`, a browser MCP (Playwright MCP or Claude in Chrome) for visual and behavioural checks, an API check against `/api/openapi.json`, and a bounded number of passes
- `sovrium-data-model` says an omitted field `id` is assigned by position, and tells the agent to give a new field the next unused id
- `sovrium-app` names `sovrium mcp` with `--project` on one line
- `sovrium-app` gives the MCP write loop in order: `_config_read_file`, `_config_write_file` with `expectedSha`, `_config_validate`, `_config_undo`
- `sovrium-app` says config writing is off until `MCP_CONFIG_WRITE=1`, and never calls the MCP surface read-only without that qualifier
- Every `sovrium docs <address>` cited in any written skill exits 0 on the same binary
- Every generated reference file is byte-equal to a fresh `bun run build:skill-references` run
- Every `references/<file>` linked from a `SKILL.md` exists and sits one level below that `SKILL.md`
- A symlink at or below `<target>/<skill>/`, or at the manifest path — to a file or a directory, dangling or not — refuses the run before anything is written or deleted in any target: exit 1, and the message names the link
- `--force` does not override the symlink refusal: the link's target is left untouched and nothing is written
- `sovrium init` skips a skill whose directory name is a symlink and reports it, instead of throwing, and still writes the other skills
- A `.claude/skills` root that is a symlink resolving inside the project is written through; one resolving outside the project is refused before anything is written
- Writing, refreshing, refusing, checking and targeting skills, from source (regression)
