kit-sync skill
The kit-sync skill backs both /kit-sync (bulk install) and /kit-update (safe re-copy). It exists because /kit-add is per-component and /setup is one-time bootstrap — neither helps a developer who wants to vendor the entire kit at once or stay current with upstream changes without losing local edits.
| Triggered by | /kit-sync, /kit-update, plus phrases like “install all components”, “bulk copy the kit”, “sync the entire kit into my project”, “refresh anything I haven’t touched” |
| Output | Component TSX/SCSS, ui.tsx foundation, theme CSS, and .acss-kit/manifest.json |
| Manifest | <projectRoot>/.acss-kit/manifest.json — the source of truth for what was generated |
Manifest format
Section titled “Manifest format”.acss-kit/manifest.json records every generated file’s normalized SHA256 at the moment it was written. Drift detection compares on-disk content to that recorded hash to classify each tracked file as clean, modified, or missing.
{ "schemaVersion": 1, "pluginVersion": "0.9.0", "targetDir": "src/components/fpkit", "stylesDir": "src/styles", "themeFile": "acss-kit.theme.json", "generatedAt": "2026-05-03T14:22:11Z", "files": { "src/components/fpkit/ui.tsx": { "source": "asset:foundation/ui.tsx", "sha256": "<hex>", "pluginVersion": "0.9.0", "kind": "foundation" }, "src/components/fpkit/button.tsx": { "source": "ref:components/button.md#tsx-template", "sha256": "<hex>", "pluginVersion": "0.9.0", "kind": "component", "component": "button" } }}kind is one of foundation (ui.tsx, foundation.css, and every file under foundation/sass/), component (a tracked TSX/SCSS pair), style (a generated theme CSS file), or theme (the user’s seed theme.json).
Hash normalization (load-bearing)
Section titled “Hash normalization (load-bearing)”Drift detection runs SHA256 on normalized content, not raw bytes. The same normalization applies before recording the manifest hash and before comparing on-disk content:
- Replace CRLF / CR with LF.
- Strip trailing whitespace (spaces and tabs) from every line.
- Collapse trailing blank lines to a single trailing newline.
Without normalization, a Prettier or editor save would flip every file to modified immediately. The logic lives in scripts/hash_file.py and is duplicated in scripts/diff_status.py.
Bulk install workflow (/kit-sync)
Section titled “Bulk install workflow (/kit-sync)”| Flag | Effect |
|---|---|
--target=<dir> | Override the components directory (default from .acss-target.json, fallback src/components/fpkit). |
--styles-dir=<dir> | Override the styles directory (default from .acss-target.json, fallback src/styles). |
--seed=<hex> | Seed colour for theme generation (default: prompt the developer). |
--skip-styles | Components-only sync; do not seed theme. |
--dry-run | Print the plan tree, do not write files or manifest. |
-
Step S0 — Exit plan mode. If the session is in plan mode, exit it before any other work. The workflow shells out to
detect_target.py,detect_stack.py, andmanifest_read.pyfrom Step S1 onward, and plan mode would block those Bash invocations even though they are read-only. The skill only stays in plan mode when the user explicitly asked for a description without running any scripts. -
Step S1 — Preflight. Detect project root via
detect_target.py; halt if missing. ConfirmcssPipelineincludessassviadetect_stack.py. Read any existing manifest viamanifest_read.py— if present, route every file through the safe-update diff/skip logic before writing. -
Step S2 — Enumerate the catalog. Read
skills/components/references/components/catalog.md. Every component named in the Verification Status table is in scope, plus the inline catalogue entries (Badge, Tag, Heading, Text/Paragraph, Details, Progress) that have a Generation Contract. ExcludesForm(lives as a skill) andUI (foundation)(handled separately asui.tsx). -
Step S3 — Resolve dep tree, dedupe. For each in-scope component, walk its Generation Contract
dependencies:recursively. Union all results into one ordered list, leaves first. -
Step S4 — Show the plan. Display the full plan (foundation, components, styles, manifest) and wait for confirmation. If
--dry-run, exit without writing. -
Step S5 — Generate components bottom-up. For each entry: load the reference doc, substitute placeholders, hash the rendered TSX with
hash_file.py --stdinbefore writing, then write. Repeat for SCSS where the contract has one. Re-sync runs routemodifiedfiles into a skipped list. -
Step S6 — Foundation. For each file in scope (
ui.tsx,foundation.css, and every file underfoundation/sass/), apply the following three-case matrix — the manifest-aware equivalent of the/kit-addStep A4 matrix:Foundation file state Action Absent from target dir and absent from manifest (fresh install) Copy ui.tsx,foundation.css, and the fullfoundation/sass/tree; hash each file; record each askind: "foundation"in the manifest; print an import hintui.tsxpresent,foundation.cssabsent — regardless of manifest state (existing install)Prompt the developer before copying — explains the CSS reset, @layerordering, and spacing/shadow tokens; the developer can opt out to avoid the foundation layerBoth ui.tsxandfoundation.csspresent and tracked in the manifestIf status is clean: overwrite and update the manifest hash. If status ismodified: skip and add to the skipped summary -
Step S7 — Styles (skipped under
--skip-styles). Resolve seed colour (--seed, prioracss-kit.theme.json, or prompt). Rungenerate_palette.pythentokens_to_css.pyto emit<stylesDir>/theme/light.cssanddark.css. Writeacss-kit.theme.jsonfor re-runs. Hash all three and record. Runvalidate_theme.pyand surface any WCAG failures (non-blocking). -
Step S8 — Write the manifest. Pipe the assembled payload to
manifest_write.py. The payload carriesprojectRoot(used to locate the write target — not persisted in the manifest itself), pluspluginVersion(from.claude-plugin/plugin.json),targetDir,stylesDir,themeFile, and a path-keyedfilesmap matching the schema above. -
Step S9 — Verify integration. Run
verify_integration.pyand surface any missing-import reasons as a numbered fix-up list. -
Step S10 — Summary. Print created / skipped counts, the manifest path, and next-step hints (
/kit-update,/kit-update --check).
Safe-update workflow (/kit-update)
Section titled “Safe-update workflow (/kit-update)”| Flag | Effect |
|---|---|
<component>... | Restrict the update to a list of components. Default: every entry in the manifest. |
--check | Report only — do not write. |
--force | Overwrite modified files. Each is backed up to <file>.bak before being overwritten. |
-
Step U0 — Exit plan mode. If the session is in plan mode, exit it before any other work. Even
--checkruns invokemanifest_read.pyanddiff_status.pyvia Bash to produce the report, and plan mode would block them. The skill only stays in plan mode when the user explicitly asked for a description without running any scripts. -
Step U1 — Read the manifest. Run
manifest_read.py. Halts onexists: false(telling the user to run/kit-syncfirst) orschemaMismatch: true(no fall-through to fresh-install — that would bypass drift protection on every tracked file). -
Step U2 — Compute drift. Run
diff_status.py. Captureclean[],modified[], andmissing[]. If a positional component filter was supplied, intersect each list with the requested set. -
Step U3 — Show the report. Display counts plus the modified and missing lists. If
--check, stop here. -
Step U4 — Regenerate clean + missing. For each entry: re-run the bulk-install logic for that file’s
kindandsource, hash the new content, write the file, stage a manifest update. -
Step U5 — Handle modified. Without
--force, skip and add to the summary. With--force, copy to<file>.bak, regenerate, write, hash, update. -
Step U6 — Rewrite the manifest. Pipe the merged payload to
manifest_write.py. Existing entries that were not touched keep their previous SHA — no spurious churn. -
Step U7 — Summary. Print updated / skipped / recreated counts and the manifest path.
Plan-mode behaviour
Section titled “Plan-mode behaviour”Both workflows write component TSX/SCSS, theme CSS, and the manifest, and they shell out to a dozen Python scripts. Exiting plan mode is therefore an explicit first step — Step S0 for the bulk install workflow and Step U0 for the safe-update workflow — so that the preflight/read scripts (detect_target.py, manifest_read.py, diff_status.py) can run via Bash. Plan mode would block those invocations even though they are read-only.
--dry-run and --check are not reasons to remain in plan mode — those flags suppress writes inside the workflow, but the workflow still has to run detect_target.py, manifest_read.py, and diff_status.py via Bash to produce the plan tree or drift report, and plan mode would block those.
The skill stays in plan mode only when the user explicitly asked for a description without running any scripts at all.
When invoked outside a slash command
Section titled “When invoked outside a slash command”If a user phrase auto-triggers this skill, pick the workflow that fits:
- “install everything”, “bulk copy”, “vendor the whole kit” → bulk install workflow.
- “update unmodified”, “refresh clean components”, “safely re-copy” → safe-update workflow.
When ambiguous, the skill asks once: “Bulk install (writes everything) or safe update (only re-copies unmodified files)?”