# Catalog Authoring

> Author and improve basicly catalog sources — skills and fragments — in their YAML source format (never a discoverable .md), then project and verify them. Use when adding or editing a skill or fragment, building a catalog, or deciding where guidance should live (always-on fragment vs on-demand skill).

- Skill: `niksavis/catalog-authoring` (Agent Skill)
- Install (CLI): `npx skillmds@latest add niksavis/catalog-authoring`
- Raw SKILL.md: https://api.skillmd.com/api/skills/niksavis/catalog-authoring/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: niksavis (https://skillmd.com/u/niksavis)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/niksavis/catalog-authoring

---

<!-- Generated by `basicly skills-build` from skill.yaml. Do not edit; edit the source. -->

# Catalog Authoring

## Scope

Owns authoring the two projected catalog content types — **skills** and
**fragments** — in their non-discoverable YAML source format, and projecting
them to the files coding agents actually load.

- A **fragment** is always-on guidance merged into the projected `CLAUDE.md`,
  `AGENTS.md`, and `copilot-instructions.md` (and, when scoped, into per-path
  rules/instructions files). Keep it terse; point at commands, do not restate
  mechanically-enforced rules.
- A **skill** is an on-demand runbook projected to `SKILL.md` at the target
  skill roots and loaded only when its `description` trigger matches.

## The non-negotiable rule: sources are never named for discovery

Coding agents auto-discover context by **filename/extension** — `SKILL.md`,
`AGENTS.md`, `CLAUDE.md`, `*.instructions.md`, `*.mdc`, `GEMINI.md`. So catalog
**sources** are authored as YAML (`skill.yaml`, `<id>.fragment.yaml`) and the
discoverable `.md` is emitted only at the target roots by the projector. Never
add a `SKILL.md` or `*.fragment.md` under `.basicly/core/`; the `catalog lint`
gate rejects it.

## Author a skill

1. Scaffold: `basicly catalog new skill <slug>` writes `core/skills/<slug>/skill.yaml`.
2. Fill in `name` (must equal the slug), a strong one-line `description` (the
   discovery trigger — state *when* to use it), and the `instructions` body as
   a `|` literal block scalar (markdown, indented two spaces).
3. Project + verify: `basicly skills-build` then `basicly skills-check` —
   bare, both write and check every default root, which is what the
   `projection-skills` gate runs.

## Author a fragment

1. Scaffold: `basicly catalog new fragment <id> --category <category>` writes
   `core/fragments/<category>/<id>.fragment.yaml`.
2. Fill in `id`, `description`, `category`, `applies_to` (e.g. `[all]`), and the
   `body` block scalar. Optional: `priority`, `tags`, `status`, `title`,
   `scope.paths` (path-scoped rules), and the `replaces`/`override` overlay
   fields.
3. Project + verify: `basicly build` then `basicly check`.

## Technology scoping

A source that only makes sense for one stack or environment tool declares
`technologies: [python]` (skills, fragments, agents, and hooks all accept it);
an untagged source is universal and always ships. Values come from the
controlled vocabulary in `basicly.schema.TECHNOLOGIES` (stack tags plus
environment tools like `zsh`/`tmux`) — `catalog lint` rejects anything else.
Consumers narrow what they receive with `basicly install --technologies ...`;
don't tag a source unless it is genuinely useless outside that technology.

## Phrasing rules for guidance bodies

Distilled from Anthropic's memory/best-practices docs and the curated
CLAUDE.md corpus (2026-07 research, epic basicly-84v):

- Concrete and verifiable beats vague intent: "use 2-space indentation" works,
  "format code properly" does not.
- Put runnable commands in code fences — a fenced command is run verbatim, a
  command described in prose gets improvised on.
- Pair every prohibition with the alternative the agent should take instead;
  a bare "never X" leaves it stuck.
- Give a one-clause rationale so the rule generalizes beyond its literal case.
- Emphasis is a scarce resource: at most one `IMPORTANT`-style marker per
  projection, or every marker becomes invisible.
- Every rule should trace to a real incident, not a hypothetical one; the
  quirks category exists for exactly those.
- Apply the deletion test before adding a bullet: would removing it cause the
  agent to make mistakes? If not, leave it out.

## YAML source shape

Every source starts with a `# yaml-language-server: $schema=...` header (editor
and agent validation against `core/schemas/`) and a `schema_version`. The prose
body is a literal block scalar so markdown round-trips losslessly:

```yaml
# yaml-language-server: $schema=../../schemas/skill.schema.json
schema_version: 1
name: my-skill
description: What it does and when to use it.
instructions: |
  # My Skill
  ...
```

## Gate

`basicly catalog lint` schema-validates every source, forbids `.md`-named
sources under the catalog, and forbids non-`.yaml` YAML there. It runs on
commit and in CI — run it locally before committing.

## Read the composed selection before hunting a projection by hand

`basicly catalog dump` prints what the sources compose to: every planned output
with the two axes the output itself declares, every item it selected with the
core or `.basicly-local` file that item was read from, and each overlay
override named beside the core source it shadows. A wrong projection is a
selection question, and this is the answer — `build` prints only the files it
wrote.

## Verify against what the agent is told, not the file you edited

The projected file is **not** the delivered artifact. A host may substitute or
fall back, so a change that reads correctly in the projection can land
differently in the agent's context — and a size claim measured on the source can
be a fraction of the real one.

The concrete case (`basicly-m4zv.1`): a user-invoked skill projects no
`description:`, and Claude Code then fills that slot from the **first body
line**, which is the generated drift marker. The measured 430-character saving
was really 157, and the entry went on advertising a string — just a useless one.
It surfaced only because the change showed up in the authoring session's own
skill list, after the commit.

So when a change alters what an agent is *told*:

- Read it back where the agent reads it — the advertised skill list, the
  always-on file as loaded, the rule as injected — not the file you edited.
- Re-measure any size or cost claim on the delivered artifact before writing a
  figure into a design document. A number measured on the source is a guess
  about the host.

