# Skills Registry — how a rule or command reaches a dev's machine

`tawa skills sync` pulls Claude Code rules and slash-commands onto every dev's
machine. This is where that content comes from, and how to change it.

## The pipeline

```
tawa-docs (git, PR-reviewed)          ← SOURCE OF TRUTH
  conventions/*.md  →  rules/tawa-*.md
  commands/*.md     →  commands/tawa-*.md
        │
        │  .forgejo/workflows/sync.yml   — on every push to main, runs
        │  iec-builder's scripts/seed-skills.ts (plus Koko + Bible sync)
        ▼
iec-builder skills registry (MongoDB)
        │
        │  tawa skills sync
        ▼
~/.claude/rules/  and  ~/.claude/commands/   on every dev's machine
```

> **The database is not the source of truth.** It is a distribution cache. Editing
> a skill directly in the registry works right up until the next seed run
> overwrites it.

## Two kinds of skill

| Kind | Source | Lands at | Becomes |
|---|---|---|---|
| **rule** | `conventions/<slug>.md` | `~/.claude/rules/tawa-<slug>.md` | Always-on guidance |
| **command** | `commands/tawa-<name>.md` | `~/.claude/commands/tawa-<name>.md` | A `/tawa-<name>` slash command |

Rules are loaded into context automatically. Commands are invoked deliberately.
Write a rule when the guidance should always apply; write a command when it is a
procedure someone runs.

## Changing a skill

1. Edit the file in `tawa-docs`: `conventions/` for a rule, `commands/` for a command.
2. Open a PR. This is the review step, and there is no other one: **merging publishes**.
3. On merge to `main`, `.forgejo/workflows/sync.yml` seeds the builder registry. It
   uses the canonical `scripts/seed-skills.ts` from iec-builder, authenticated by the
   repo secret `BUILDER_INTERNAL_KEY`, and also syncs Koko and the Bible. Nobody runs a
   seed by hand, and nobody needs the builder key.
4. Devs pick it up with `tawa skills sync`.

**Checking it published.** The run log for the merge commit says
`Found N skills/rules to seed … Done: 0 created, N updated, 0 errors` (Forgejo →
tawa-docs → Actions). Or run `tawa skills sync` and look for your skill's new version.

**The skills step fails soft.** It is `continue-on-error`, and it skips with
`BUILDER_INTERNAL_KEY not set` if the secret disappears. So a green run is not proof
that the registry updated: check for the `Done:` line. `workflow_dispatch` re-runs it
by hand (Actions → sync → Run workflow).

**Seeding by hand is for recovery only**, for example when CI is down. Run it on the
builder host, where the key already lives, so it never passes through a laptop:

```bash
git -C ~/dev/tawa-docs fetch origin
git -C ~/dev/tawa-docs archive origin/main conventions commands \
  | ssh tawa 'rm -rf /tmp/tawa-docs-seed && mkdir -p /tmp/tawa-docs-seed && tar -x -C /tmp/tawa-docs-seed'
ssh tawa 'cd /opt/iec-builder && INTERNAL_SERVICE_KEY="$(grep ^INTERNAL_SERVICE_KEY= .env | cut -d= -f2-)" \
  TAWA_DOCS_DIR=/tmp/tawa-docs-seed npx tsx scripts/seed-skills.ts; rm -rf /tmp/tawa-docs-seed'
```

> **Correction (2026-09-22):** this page used to say seeding was "manual and deliberate"
> and that merging did not publish, with a laptop command needing `INTERNAL_SERVICE_KEY`.
> `sync.yml` had been seeding on every merge for some time, so that guidance sent
> people after a key they never needed. The PR review is the gate.

## Versions are derived, never hand-written

```
version = 1.0.<sha256(content)[0:6] as int % 100000>
```

A version is a function of the content, so:

- **Identical content always produces an identical version.** A verbatim file move
  should leave every version unchanged — that is how you verify a refactor changed
  nothing.
- **Never hand-pick a version.** Bumping it manually (say to `1.1.0`) will be
  overwritten by the next seed and, worse, may not match the content it claims to
  describe.
- The builder's manifest hashes `name:version`, so a static version would hide
  updates from `tawa skills sync` entirely.

## Naming

A convention seeds as `tawa-<slug>` with `['platform']` tags unless it appears in
`CONVENTION_MAP` in the seed script. Add an entry there when the rule name should
differ from the file name — for example `conventions/auth.md` seeds as
`tawa-oauth`.

Command files must be named `tawa-*.md`; anything else in `commands/` is ignored.

## Gotchas

- **Editing `~/.claude/commands/` directly is a dead end.** It is the *output* of
  the pipeline. Your change survives until the next `tawa skills sync`, then
  disappears.
- **Skills are global, not per-repo.** Everything seeded here reaches every dev on
  every project. Repo-specific guidance belongs in that repo's `CLAUDE.md`.
- **A stale `last_updated` is a lie with a date on it.** Update it when you change
  a doc; it is the only signal a reader has about whether the content is current.

## History

Until 2026-08-28 the five slash-commands (`tawa-auth`, `tawa-domains`, `tawa-pm`,
`tawa-scaffold`, `tawa-troubleshoot`) were seeded from `~/.claude/commands` on a
single machine — no backup, no review, no history. They now live in
`tawa-docs/commands/` alongside the conventions.
