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

KindSourceLands atBecomes
ruleconventions/<slug>.md~/.claude/rules/tawa-<slug>.mdAlways-on guidance
commandcommands/tawa-<name>.md~/.claude/commands/tawa-<name>.mdA /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:

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.

Last updated: October 6, 2026