A test skill from an extension
日本語の概要は準備中です。原文の説明を表示しています。
Orchestrate the remote rules registry — the shared registry (often connected as a local folder or git repo) that the project's rules are published to and pulled from. Three modes, picked from the user's wording: create scaffolds a new local rules registry ("create a local rules registry", "init a rules registry"); update migrates/promotes local knowledge-base rules from .unikit/memory/ into the remote registry with automatic semver bumps ("migrate local rules to the remote registry", "promote my rules to the registry", "push local rules", "publish local rules", "update the rules registry"); sync pulls registry updates back into memory ("sync the rules registry", "pull registry updates"). Pass "--module <id>" to scope to one knowledge-base module. This skill ONLY orchestrates the CLI (`unikit-ai rules *`) — it never edits .unikit.json or .unikit/memory/ sources directly.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Manage the external rules registry lifecycle from the project side. This skill owns three modes:
.unikit/memory/, and optionally switch the project to use it..unikit/memory/ against the currently configured local registry and push changes back (new rules, content updates with automatic semver bumps, stale deletions)..unikit/memory/ via unikit-ai rules sync (direction: registry → memory).Direction matters:
create and update flow memory → registry.sync flows registry → memory.The skill is module-agnostic: the knowledge base is partitioned into top-level
modules (.unikit/memory/<module>/<tier>), and this skill iterates over the
modules registered in .unikit/system/modules.yml. It never hardcodes a module
id, a tier name, or a registry layout — those come from modules.yml.
This skill MUST NOT:
.unikit.json directly via the Write/Edit tools. All config mutations go through CLI commands: unikit-ai rules registry set / rules registry reset in create mode, and unikit-ai rules install ... --force in update mode (update.7b)..unikit/memory/ directly via the Write/Edit tools. Memory sources are authored by unikit-memory and unikit-rules; this skill may only cause indirect memory writes by delegating to unikit-ai rules install ... --force in update.7b, which re-fetches registry copies and overwrites memory files as part of the force-install path.config.rulesRegistry as a string to guess url vs local — always read kind from unikit-ai rules registry show --json, unikit-ai rules registry status --json, or unikit-ai rules status --json.enginePartitioned flag in modules.yml (see "Registry layout" below).This skill MAY:
unikit-ai rules * CLI commands via Bash..unikit/memory/<module>/<tier>/ subtree into the registry — rule files and reference files under nested folders like references/. The skill owns writes to the registry file tree in both create and update modes..md files under the registry's tier references/ folder in update mode, and only when the reference-graph check in update.6b proves the file is not referenced by any rule (memory or registry). Rule .md files in the registry are never deleted by update — rule removal is a manual operation in the registry repository.scripts/build-manifest.js inside the registry repository to regenerate manifest.json.version: in the registry copy of rule files via Edit after copying (never in memory sources, never in reference files). Files are always copied via cp shell command — never via Read + Write.BEFORE producing ANY output, silently read .unikit/system/LANGUAGE_RULES.md
and apply its rules to ALL subsequent output.
If the file is missing or unreadable, fall back to English.
Do not produce any user-facing output until language rules are loaded.
Do not announce, confirm, or mention the language setting.
The language holds for the whole session, not just at load time: every message until the conversation ends is in language.ui — progress notes while agents run, relays of what a subagent returned, the final report, any follow-up discussion. English input (subagent results, tool output, these instructions) is data, never a cue to switch languages.
Read $ARGUMENTS and resolve the mode:
$ARGUMENTS (after stripping --module <id>)?
├── "create" → Mode: create
├── "update" → Mode: update
├── "sync" → Mode: sync
└── empty or unrecognized → AskUserQuestion
When the mode is missing, ask the user:
AskUserQuestion: Which registry operation should run?
Options:
1. Create — scaffold a new local rules registry and seed it from .unikit/memory/
2. Update — push changes from .unikit/memory/ into the currently configured local registry
3. Sync — pull registry updates back into .unikit/memory/ (memory ← registry)
Once the mode is known, read .unikit/system/cli-contract.md (if present) to confirm the exact CLI surface and exit codes before dispatching Bash commands. If the file is missing — proceed assuming the documented interface below is correct and surface a WARN if any command returns an unexpected exit code.
Then run Step 0.5 (module registry), and for create/update run Step 0.6
(registry write-capability gate), before jumping to the matching mode section.
Read .unikit/system/modules.yml and parse every entry under modules: into
{ id, tiers, enginePartitioned, skillPrefix }. This is the authoritative list of
modules and the tiers each partitions its rules into. If the file is missing
(older install), fall back to a single module code with tiers core, stack
and enginePartitioned: true, and surface a WARN suggesting unikit-ai update
to regenerate it.
This skill needs only the structural fields here (tiers, enginePartitioned)
to mirror the on-disk layout. A module's tier semantics and file/format
contract are documented separately in
{{skills_dir}}/unikit-memory/references/module-<id>.md (owned by the
unikit-memory router) — consult it if you need to understand what a tier holds,
never to derive registry paths.
Resolve the target modules (the policy mirrors --engine):
--module <id> in $ARGUMENTS → validate against the parsed ids.
Valid → operate on that single module; strip the flag. Invalid → ask via
AskUserQuestion (options = registered module ids), then use the chosen id.
Print the module ids with their one-line domain summaries to the screen as plain
markdown first — the question mechanism carries the options and nothing else.modules.yml).AskUserQuestion (options =
registered module ids + "all modules"). Never guess.
Print the module ids with their one-line domain summaries to the screen as plain
markdown first — the question mechanism carries the options and nothing else.Everywhere below, "for each module" means "for each resolved target module", and
"for each tier" means "for each tier of that module from modules.yml".
Registry layout (schema:2, derived per module from enginePartitioned):
code): <registryPath>/<module>/<engine>/<tier>gamedesign): <registryPath>/<module>/<tier>The tier's reference subfolder is <that tier path>/references/. Memory sources
always live at .unikit/memory/<module>/<tier>/. Never hardcode these — assemble
them from the module id, its enginePartitioned flag, the resolved engine, and the
tier.
Write modes must confirm the target registry is reachable, on the latest schema,
and writable before seeding or pushing. sync skips this gate entirely — it is
registry → memory and relies on its own rules sync exit codes (2/5).
Run against the target registry (the configured registry for update; for
create, run it after create.2 against the scaffold target path):
unikit-ai rules registry status --json
The JSON has six facts: { target, kind, schema, isLatestSchema, readable, writable }.
Exit codes: 0 (reachable, schema ≤ latest), 2 (unreachable), 5 (unsupported
schema > latest). Branch on the result:
| Condition | Verdict | Action |
|---|---|---|
exit 2 / schema == null | unreachable | Report registry unreachable and stop. A write mode cannot proceed against a registry it cannot read. |
exit 5 / readable == false (schema > latest) | unsupported schema | Report registry schema is newer than this CLI — upgrade unikit-ai, then stop. |
kind == "local" and isLatestSchema == false | local, behind latest schema | Offer to migrate: AskUserQuestion → run unikit-ai rules registry migrate <target> on yes, then re-run rules registry status --json and re-evaluate. On no → stop (writing schema:2 layout into a schema:1 registry would corrupt it). |
kind == "remote" and isLatestSchema == false | outdated remote | migrate cannot write a remote registry. Report that the user must clone the registry, run rules registry migrate on the clone, open a PR upstream, then point the project at a writable copy. Stop. |
kind == "remote" and isLatestSchema == true | remote, read-only via CLI | A write mode needs a local registry. For update, this duplicates the update.1 guard — report update requires a local registry and stop. (create scaffolds a fresh local target, so this row should not occur there.) |
kind == "local" and isLatestSchema == true (writable == true) | up to date and writable | Proceed to the mode body. |
Only continue into the create-seed / update-diff steps when the gate resolves to
writable (kind == "local" and isLatestSchema == true).
Scaffold a new local registry and seed it with the rules currently installed in .unikit/memory/.
AskUserQuestion: Where should the new rules registry be created?
Options:
1. Project subfolder — ./rules-registry
2. Custom path — I will ask next (relative or absolute)
3. Cancel
pathArg = "./rules-registry". Pass this verbatim to the CLI in create.2. rulesRegistryInitCommand in src/cli/commands/rules.ts resolves it against process.cwd() and auto-creates the target directory via fs.ensureDir.AskUserQuestion for the path as free-form text input. Trim the input; if the result is empty, re-prompt the same text input. Then compute the absolute path via path.resolve(<cwd>, <trimmed-input>) for display only and ask a second AskUserQuestion of this shape:
Target directory will be: <resolved-absolute-path>. Proceed?Yes, proceed / No, enter a different path / CancelpathArg in create.2.Do not pre-check path existence, expand ~, normalize the path, or reject relative paths on the skill side. rulesRegistryInitCommand is the single authority on path validation: it calls path.resolve(cwd, pathArg) itself, auto-creates missing directories via fs.ensureDir, and signals problems through exit codes 3 (INVALID_ARGS), 6 (REGISTRY_ALREADY_INITIALIZED), and 7 (PATH_OCCUPIED) — all handled in create.2 below.
Run:
unikit-ai rules registry init <target-path>
Exit-code handling:
| Exit | Meaning | Action |
|---|---|---|
| 0 | Scaffold OK | Continue to create.2b |
| 3 | INVALID_ARGS (relative path, etc.) | Report stderr and stop |
| 5 | VALIDATION_FAILED (build-manifest.js failed) | Report stderr and stop |
| 6 | REGISTRY_ALREADY_INITIALIZED | Ask the user: reuse existing scaffold and continue? → Yes proceeds to create.2b, No stops |
| 7 | PATH_OCCUPIED | Report target path is not empty and is not a registry, stop |
| other | Unexpected | Report stderr and stop |
registry init creates a fresh schema:2 scaffold, but on the reuse path (exit 6)
the existing directory may be a schema:1 registry. Run the Step 0.6 gate against
<target-path> now. A freshly-initialized target resolves to writable immediately;
a reused schema:1 target routes through the migrate offer. Only continue to
create.3 when the gate resolves to writable.
unikit-ai rules status --json
Parse the JSON and read .engine. Never open .unikit.json directly — the CLI is the source of truth.
If the CLI exits non-zero (project not initialized), stop the skill with an ERROR referencing unikit-ai init.
For each module (Step 0.5) and each tier of that module:
Glob: .unikit/memory/<module>/<tier>/**/* to enumerate the entire subtree — not just top-level *.md. This captures nested folders like references/ that hold reference files referenced by rule headers (quickrefs, catalogs, indexes).relPath relative to .unikit/memory/<module>/<tier>/.<tier-registry-path>/<relPath>, where <tier-registry-path> is the schema:2 layout from Step 0.5 (<target-path>/<module>/<engine>/<tier> for engine-partitioned modules, <target-path>/<module>/<tier> otherwise).relPath contains no /, extension .md) → copy via shell, then inject version into the registry copy only if absent:
Bash: mkdir -p "$(dirname "<target>")" && cp "<src>" "<target>"Bash: grep -q "^version:" "<target>" — if exit 1 (not found), use Edit to insert version: 1.0.0 into the frontmatter of <target>. The source in .unikit/memory/ stays untouched..md extension) → copy via shell verbatim. Never touch frontmatter — reference files are plain docs and must travel with their parent rule as-is:
Bash: mkdir -p "$(dirname "<target>")" && cp "<src>" "<target>"Track per-module/per-tier totals: rulesCopied (top-level rule files) and referencesCopied (everything else). These feed the final table in create.7.
Why recursive: rule files reference reference files via > **References**: headers. A seed that copies only *.md at the top level would publish rules pointing at paths that do not exist in the registry. Mirroring the full tree keeps the references intact.
node <target-path>/scripts/build-manifest.js
> **Load when**: blocks or invalid frontmatter.The scaffold mirrors .unikit/memory/ bit-for-bit on disk — content-wise the new registry agrees with memory. But the state metadata in .unikit.json.rules.installed still points at the old provenance: every rule entry is tagged with its original source (installer / registry) and origin (official / old primary). Flipping rulesRegistry alone does not rewrite those tags, so the project would still look like it is "using the old registry" on the next rules status --json.
To make the switch complete, the skill pairs registry set with a follow-up rules sync --replace --prune. --replace bypasses the source !== 'registry' guard in syncRulesState so installer-sourced rules get walked; the sync loop rewrites source, version, installed_hash, and origin (via HybridRegistry.getResolvedOrigin()) against the new primary registry. --prune removes obsolete stack rules that are not in the new manifest. The HARD GUARD in syncRulesState still prevents discovery of previously-uninstalled rules — only already-installed entries get reclassified.
AskUserQuestion: Switch the current project to this new registry now?
Options:
1. Yes — point .unikit.json at the new registry and reclassify installed rules as primary
2. No — keep the current registry
Mapping to CLI commands (order matters — registry set must succeed before sync runs):
| Choice | Commands |
|---|---|
| 1 | unikit-ai rules registry set <target-path> then unikit-ai rules sync --replace --prune |
| 2 | (skip — do not touch .unikit.json) |
Exit-code handling:
rules registry set exit 3 (INVALID_ARGS) or 5 (VALIDATION_FAILED) → report stderr and stop the skill. Do not run rules sync; the URL has not been written.rules sync --replace --prune exit 2 (NETWORK — local path disappeared between the two commands) or 5 (VALIDATION_FAILED — registry manifest broken) → report stderr and warn the user that .unikit.json.rulesRegistry has already been rewritten to the new path, but rule metadata is still on the old provenance. Instruct them to fix the registry and re-run unikit-ai rules sync --replace --prune manually. Do not attempt to roll back registry set automatically.create.7.Stream stdout/stderr of both commands to the user so the per-rule event log from syncRulesState is visible.
Produce a compact final report — no prose paragraphs, no step-by-step narrative, no CLI echoes. Just one table of the rules that were transferred, followed by two direction reminders. Anything longer than a dozen lines means you are over-reporting.
Table format (add a Module column when more than one module was seeded; omit it when only code ran):
| Module | Tier | Rule | Version |
|--------|-------|-------------------|---------|
| code | core | folders-structure | 1.0.0 |
| code | core | code-style | 1.0.0 |
| code | stack | aspid-mvvm | 1.0.0 |
| code | stack | node-canvas | 1.0.0 |
rulesCopied).+ N reference files under references/ (omit the line if referencesCopied == 0).1.0.0).After the table, print exactly these two reminders (adapt to the configured language):
/unikit-rules-registry update — push later local edits from .unikit/memory/ into this registry./unikit-rules-registry sync — pull registry-side updates back into .unikit/memory/ (opposite direction).If the project was switched to the new registry in create.6, add exactly two lines after the reminders:
✅ rules registry set: <target-path>✅ rules sync --replace --prune: N rules reclassified as primaryN is the number of rules touched by the sync — count the phase2:updating events from the syncRulesState event log (every such event flips one rule's source/origin to the new primary). If the switch was declined, add nothing.
Push changes from .unikit/memory/ into the currently configured local registry and regenerate its manifest.
unikit-ai rules registry show --json
Parse JSON fields configured, url, kind.
kind is not "local" → ERROR: update requires a local registry — run /unikit-rules-registry create first. Stop.configured is false → ERROR: no registry configured. Stop.registryPath = <url>.Run the Step 0.6 gate against registryPath. If the registry is local but
behind the latest schema, this routes through the rules registry migrate offer —
critical, because writing schema:2 layout (<module>/<engine>/<tier>) into a
schema:1 registry (<engine>/<tier>) would corrupt the layout and break
build-manifest.js. Only continue to update.2 when the gate resolves to writable.
unikit-ai rules status --json
Read .engine. Abort on non-zero exit.
For each module (Step 0.5) and each tier of that module:
Glob: .unikit/memory/<module>/<tier>/**/* — walk the full subtree so reference files under references/ (and any other nested folders) are diffed alongside their parent rules.src found in memory, compute relPath relative to .unikit/memory/<module>/<tier>/ and classify it:
relPath has no / and ends with .md (top-level markdown)..md). Reference files carry no version: frontmatter — they travel with their parent rule as plain content.src:
<tier-registry-path>/<relPath> (schema:2 layout from Step 0.5)Bash: diff -q --strip-trailing-cr "<src>" "<target>":
Glob: <tier-registry-path>/**/*. Any file present in the registry but not in memory becomes a delete candidate (handled in update.5). Tag each orphan as rule vs reference file so the prompt can display them in two groups.Why recursive: rule files reference reference files via > **References**: headers. If update diffs only top-level *.md, edits to reference docs (quickrefs, full catalogs) silently stay behind and the registry drifts out of sync with the project's actual knowledge base. Walking the subtree is the simplest way to guarantee every referenced file reaches the registry.
differs rule filesReference files (reference-update from update.3) have no frontmatter version to bump — skip this step for them and handle them directly in update.6.
For every differs rule file, run Bash: diff -u --strip-trailing-cr "<src>" "<target>". Parse the output:
added = number of lines starting with "+" excluding the "+++" headerremoved = number of lines starting with "-" excluding the "---" headeroldTotal = wc -l of <target> (used for the removed > 30% oldTotal rule)Apply the heuristic in order — the first matching row wins:
| Condition | Bump |
|---|---|
removed > 0.3 * oldTotal | major |
removed == 0 AND added <= 5 | patch |
removed == 0 AND added > 5 | minor |
removed <= 3 AND added <= 10 | patch |
removed > 3 AND added > removed | minor |
| otherwise | patch |
Compute the new version:
version: from the target file's frontmatter (if missing, assume 1.0.0).patch → x.y.(z+1)minor → x.(y+1).0major → (x+1).0.0Update is strictly push-only for rule files — it never removes them from the registry. For every rule .md file present in the registry and missing from memory (i.e. top-level *.md under <tier-registry-path> with no counterpart in .unikit/memory/<module>/<tier>/), append { module, tier, filename } to an orphanRuleFiles list. That list is consumed purely by update.8 as a WARN block — no prompt, no delete, no cascade.
Do not walk reference files under references/ here. Reference file reconciliation is a separate concern handled in update.6b via the real rule → references graph; orphan detection at the file level would miss shared reference files and produce false positives.
If orphanRuleFiles is empty after the walk, the WARN block is skipped entirely in update.8.
For each rule file add:
Bash: mkdir -p "$(dirname "<target>")" && cp "<src>" "<target>"Bash: grep -q "^version:" "<target>" — if exit 1 (not found), use Edit to insert version: 1.0.0 into the frontmatter of <target>. The source in .unikit/memory/ stays untouched.For each rule file differs:
Bash: cp "<src>" "<target>"Edit to replace the version: line in <target> with the bumped version from update.4 (insert if absent). The source in .unikit/memory/ stays untouched.For each reference file add or reference-update:
Bash: mkdir -p "$(dirname "<target>")" && cp "<src>" "<target>"Track touchedRuleFiles = [...] — every rule file classified as add or differs in this step, stored as { module, tier, ruleId } (ruleId = filename without .md). This list is consumed by update.7b to drive the post-write rules install --force batch. Reference files are not tracked — installOneRule re-fetches a parent rule's declared references automatically during force install.
There is no delete branch in this step — update never removes rule files from the registry (see ## Boundaries). Companion deletions happen separately in update.6b via the reference-graph check; that step runs after all writes here so it sees the final set of registry files.
All writes happen inside the registry tree only — never touch memory sources.
Reconcile reference files in the registry against the real rule → references graph. Remove any reference .md under a tier's references/ folder that no rule (in memory or in the registry) references anymore. The algorithm covers four scenarios:
| Scenario | referencedByAnyone? | Action |
|---|---|---|
| Parent rule dropped a ref, nobody else holds it | No | Delete |
| Shared — another memory rule still references it | Yes | Keep (protected) |
| Orphan parent rule in registry still references it | Yes | Keep (protected) |
| Zombie — no rule references it anywhere | No | Delete |
Run the algorithm per module + per tier — each <module>/<tier> is an independent namespace and never shares reference filenames across the divide.
For each module + tier:
referencedByAnyone as an empty Set<string> of reference filenames.<tier-registry-path>/*.md (top-level rule files only — do not recurse into references/ here). For every rule file found:
ruleId = basename without .md..unikit/memory/<module>/<tier>/<ruleId>.md exists → parseTarget = memory (memory wins for rules present in both).parseTarget = registry (orphan parent rule — protect its own references using the on-disk registry header).> **References**: header line, and extract every reference filename with the regex references\/([^\s,)]+\.md)/g. This is the exact regex used by rules-registry/scripts/build-manifest.js — stay byte-for-byte aligned so update.6b and the manifest rebuild in update.7 never disagree about what is referenced.referencedByAnyone.Glob: <tier-registry-path>/references/*.md → physical (set of filenames only, strip paths).safeToDelete = physical \ referencedByAnyone (set difference by filename).safeToDelete:
Bash: rm "<tier-registry-path>/references/<filename>" (single-file delete, never recursive, never glob).{ module, tier, filename } to a top-level deletedReferences list consumed by update.8.Documented edge cases (not special-cased — the algorithm handles them naturally):
> **References**: header. The regex returns an empty set for that rule. If nobody else references its former reference files, they become part of safeToDelete. This is the user's explicit intent — removing the header is the signal.referencedByAnyone, so the delete check stays consistent with manifest generation. Nothing is fabricated — this step only deletes.referencedByAnyone handles this: a shared file is recorded once and protected by both rules.This step runs before update.7 — the manifest rebuild must see the final physical layout of references/, otherwise it would list reference filenames that no longer exist on disk.
node <registryPath>/scripts/build-manifest.js
On non-zero exit: print stderr, stop the skill. The most common cause is a rule missing > **Load when**: or invalid frontmatter; the user must fix the rule source in .unikit/memory/ (via /unikit-memory) before re-running /unikit-rules-registry update.
update.6 wrote new and bumped rule files into the registry, but .unikit.json.rules.installed[...] still points at the pre-update version and installed_hash for every touched rule. Without reconciliation:
unikit-ai rules status will lie about installed versions.unikit-ai rules sync (Safe mode) will mark disk files as locally-modified and skip the version update, so the drift never heals on its own.Force-install every touched rule in a single variadic CLI call. Reference files are not listed — installOneRule re-fetches a parent rule's declared references automatically during force install.
Collect installTargets = [ruleId for each entry in touchedRuleFiles], deduplicated. Read the list tracked in update.6.
If installTargets is empty → skip this step entirely. No rule file changed in this run, so there is nothing to reconcile.
Otherwise run one variadic invocation:
unikit-ai rules install <id1> <id2> ... --force
Stream stdout/stderr to the user so the per-rule report (✓ installed …, ↻ already installed …, ✗ failed …) surfaces as events occur.
Exit-code handling:
| Exit | Meaning | Action |
|---|---|---|
| 0 | At least one rule installed (aggregated report may still contain failed rows) | Parse the report, forward any failures into update.8 as a WARN block, continue |
| 2 | NETWORK — registry chain unreachable | Report stderr and stop the skill |
| 4 | NOT_FOUND — every rule failed | Capture the aggregated report, continue to update.8 and surface as a WARN block; do not roll back update.6 writes |
| 5 | VALIDATION_FAILED — registry manifest broken | Report stderr and stop the skill |
| other | Unexpected | Report stderr and stop the skill |
Do not attempt to roll back the writes update.6 already made to the registry. The registry-side update has already succeeded; partial install failures are recoverable by re-running unikit-ai rules install <id> --force manually against specific ids once the root cause is fixed.
installOneRule with force=true covers all three state branches deterministically:
source: registry and stale version → in-place update of source, version, installed_hash, origin.source: local → transition to source: registry, version: <from registry> (first-time publication path). This is how a rule that was previously authored locally and just pushed to the registry in this run becomes "owned" by the registry in .unikit.json.source: registry, version: <from registry>.A free bonus: rulesInstallCommand always regenerates RULES_INDEX.md at the end of its invocation, so the skill does not need a separate index refresh after this step.
Produce a compact final report — same style as create.7. No prose paragraphs, no step-by-step narrative, no CLI echoes. One table of rule changes, optional tallies, optional WARN blocks, one direction reminder. Anything longer than a dozen lines (plus WARN blocks, which can grow if the situation warrants) means you are over-reporting.
Table format (add a Module column when more than one module was pushed; omit it when only code ran):
| Action | Module | Tier | Rule | Version |
|--------|--------|-------|-------------|---------------|
| add | code | stack | aspid-mvvm | 1.0.0 |
| update | code | stack | node-canvas | 1.2.0 → 1.3.0 |
| skip | code | core | code-style | 1.1.0 |
One row per top-level rule file touched. Rows are grouped by action in the order: add, update, skip. Omit the skip rows entirely if every unchanged rule would otherwise bloat the table — keep them only when useful for verification.
There is no delete row for rule files — update is strictly push-only for .md rule files (see ## Boundaries). A rule that only exists in the registry surfaces in the orphan WARN block below, never as a table row.
Version column: for add and skip shows the current registry version; for update shows old → new.
Do not list reference files in the main table. Add a single trailing line directly under the table: + N reference files: X added · Y updated · Z deleted · W unchanged (omit the line if all four counts are zero). Z comes from the deletedReferences list populated in update.6b.
If Z > 0, print a separate deletion table directly under the tally line:
| Action | Module | Tier | File |
|--------|--------|-------|------------------------------|
| delete | code | stack | aspid-mvvm-binders-full.md |
| delete | code | core | old-reference.md |
Rows come from deletedReferences, sorted by module, then tier, then filename. Do not inline the list on one line — the table is both the primary signal and the full record.
If update.5 collected any entries into orphanRuleFiles, print one WARN block before the final two lines. Skip the block entirely when the list is empty:
⚠️ WARN: registry contains orphan rule files not mirrored in .unikit/memory/:
- code/stack/legacy-rule.md
- code/core/retired-guidelines.md
update is push-only; rule deletion must be done in the registry repo directly
(rm + scripts/build-manifest.js + commit).
If update.7b surfaced any failed rows in the rules install --force report (either partial failures on exit 0 or total failure on exit 4), print a second WARN block directly after the orphan block:
⚠️ WARN: state reconcile partially failed — the registry was updated but these rules
stayed on their pre-update versions in .unikit.json:
- stack/aspid-mvvm — <reason from the install report>
Re-run `unikit-ai rules install <id>... --force` manually after fixing the cause.
After the table, the reference files tally, and any WARN blocks, print exactly these two lines (adapt to the configured language):
✅ manifest: ok or ❌ manifest: failed — <one-line reason>/unikit-rules-registry sync — pull registry-side updates back into .unikit/memory/ (opposite direction of this run).Pull registry-side updates back into .unikit/memory/ by delegating to unikit-ai rules sync. Direction is registry → memory (the opposite of update).
This mode does not run the Step 0.6 write-capability gate — it does not write the
registry. rules sync carries its own reachability/validation exit codes (2/5),
which sync.2 handles. rules sync reconciles the whole project and does not
accept --module; a resolved --module <id> does not narrow the CLI call in this
version (it only documents intent for the report).
The CLI exposes two composable flags that used to live behind the single --force:
--replace — overwrite rules already in state (same-version refresh AND local modifications).--prune — remove obsolete stack rules that vanished from the manifest.The question below maps each user choice to a concrete flag combination.
AskUserQuestion: How should the sync run?
Options:
1. Safe — update rules already marked source: registry whose version changed (no rewrite of local modifications, no prune)
2. Replace — also overwrite rules that are up-to-date but locally modified (no prune)
3. Mirror — full parity with the registry: replace AND prune obsolete stack rules (equivalent to the legacy `--force`)
| Choice | Command |
|---|---|
| Safe | unikit-ai rules sync |
| Replace | unikit-ai rules sync --replace |
| Mirror | unikit-ai rules sync --replace --prune |
rules sync does not accept --module — do not append it. The command reconciles
every module's rules in one pass.
Stream stdout/stderr to the user so the per-rule event log from syncRulesState is visible.
Handle exit codes:
Produce a compact final report — same style as create.7 and update.8. No prose paragraphs, no CLI echoes. Parse the per-rule event log from syncRulesState into a single table of what happened in memory, followed by one direction reminder.
Table format (add a Module column when more than one module synced; omit it when only code ran):
| Action | Module | Tier | Rule | Version |
|--------|--------|-------|-------------|---------------|
| add | code | stack | aspid-mvvm | 1.0.0 |
| update | code | stack | node-canvas | 1.2.0 → 1.3.0 |
| delete | code | stack | odin | — |
.unikit/memory/. Group by action in the order: add, update, delete. Do not include skip rows — on sync they are noise.Version column: for add shows the installed version; for update shows old → new; for delete shows —.references/, add a single trailing line: + N reference files refreshed (omit if zero).RULES_INDEX.md was regenerated, print one line: ✅ RULES_INDEX.md: regenerated.After the table, print exactly one reminder (adapt to the configured language):
/unikit-rules-registry update — push local edits from .unikit/memory/ back into the registry (opposite direction of this run).Writable (this skill may create and edit these, strictly inside the registry target path):
<registry-path>/<module>/<engine>/<tier>/** (engine-partitioned modules) or <registry-path>/<module>/<tier>/** (non-engine modules) — rule files and any nested reference files (e.g. references/*.md)<registry-path>/manifest.json (only as a side effect of running build-manifest.js)Deletable (update mode only, under the conditions below):
references/*.md — reference files. Only when the reference-graph check in update.6b proves the file is not referenced by any rule in memory or in the registry (shared-reference protection)..md files in the registry are never deleted by update — rule removal is a manual operation in the registry repository.Read-only (this skill MUST NEVER modify these files directly via Write/Edit):
.unikit/memory/** — owned by unikit-memory. Mutated only indirectly when unikit-ai rules install --force re-fetches registry copies in update.7b..unikit.json — mutated only via unikit-ai rules registry set / unikit-ai rules registry reset / unikit-ai rules install --force..unikit/system/cli-contract.md — regenerated by the build pipeline.unikit/system/modules.yml — module registry snapshot, regenerated by the build pipeline.unikit/config.yaml — project settingsEach mode ends at its own per-mode report (create.7, update.8, sync.3). Do not add a second summary on top of them, and never auto-invoke another skill.
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
A test skill from an extension
日本語の概要は準備中です。原文の説明を表示しています。
A test skill from an extension (v2)
日本語の概要は準備中です。原文の説明を表示しています。
Initialize the UniKit framework in a project. Scans the current project to detect the engine and real tech stack, then generates the base framework documents that give AI agents context about the project — the resolved project description, the architecture doc, AGENTS.md, and the user-editable .unikit/config.yaml. This is the one-time, whole-project setup run before any other unikit skill. Use whenever the user wants to initialize, set up, or onboard the framework, e.g. "initialize unikit", "init the framework", "set up unikit", "set up the project", "configure AI context", "scan my project and set it up", "bootstrap the project". It also actualizes the config of a project already set up — say "update the config", "add missing settings", "actualize configuration", "fix my config".
日本語の概要は準備中です。原文の説明を表示しています。
Generate the architecture guidelines for a game project. Scans the project structure and tech stack, then produces .unikit/ARCHITECTURE.md describing the folder layout, dependency rules, and how modules communicate. Name a specific pattern or let it auto-detect. Use when the user wants to define or document the project architecture, e.g. "generate architecture", "describe the architecture", "which architecture should I use", "set up project architecture", or mentions module structure, module boundaries, project organization, or dependency rules.
日本語の概要は準備中です。原文の説明を表示しています。
Archive completed plans. Moves finished folder plans from .unikit/code/plans/<folder>/ to .unikit/code/archive/plans/<folder>/, so plan lookup and the plan lists stop offering them; an unfinished plan moves only when the user picks it, and is marked as unfinished. Lists every plan with its created and last-change dates; plans can be picked by number or by date. Never deletes, renames or commits. Use when user says "archive plans", "archive completed", "archive old plans", "clean up plans", or "show archived plans". Not for .unikit/code/PLAN.md or FIX_PLAN.md; to check that a plan is really done use /unikit-verify, to commit the move use /unikit-commit.
日本語の概要は準備中です。原文の説明を表示しています。
Create conventional commit messages for {{engine_name}} projects by analyzing staged changes. Handles engine-specific concerns like companion file pairing, binary assets, and linking the related plan. ALWAYS use this skill when the user asks to commit, save changes, or create a commit. Trigger phrases include "commit", "create commit", "commit this", "save changes", "save my work". Even if the user simply says "commit" or asks you to commit after finishing a task — invoke this skill, do NOT commit manually via git.
日本語の概要は準備中です。原文の説明を表示しています。