Sanity Migration
sanity-io/agent-toolkit
Plans, implements, and reviews migrations from other CMSes and content systems into Sanity.
Apply DESIGN, canon, and modules to every page in the inventory, producing a deployable static HTML site.
$ npx skills add adobe/skills --skill migrate -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install adobe/skills migrate --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/adobe/skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/stardust/skills/migrate .claude/skills/migrate && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "migrate" agent skill from https://github.com/adobe/skills/tree/main/plugins/stardust/skills/migrate into .claude/skills/migrate/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/adobe/skills/tree/main/plugins/stardust/skills/migrateType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add adobe/skills --skill migrate -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install adobe/skills migrate --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/adobe/skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/stardust/skills/migrate .agents/skills/migrate && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "migrate" agent skill from https://github.com/adobe/skills/tree/main/plugins/stardust/skills/migrate into .agents/skills/migrate/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add adobe/skills --skill migrate -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install adobe/skills migrate --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/adobe/skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/stardust/skills/migrate .cursor/skills/migrate && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "migrate" agent skill from https://github.com/adobe/skills/tree/main/plugins/stardust/skills/migrate into .cursor/skills/migrate/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/adobe/skills.git --path plugins/stardust/skills/migrate--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add adobe/skills --skill migrate -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install adobe/skills migrate --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/adobe/skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/stardust/skills/migrate .gemini/skills/migrate && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "migrate" agent skill from https://github.com/adobe/skills/tree/main/plugins/stardust/skills/migrate into .gemini/skills/migrate/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install adobe/skills migrateInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add adobe/skills --skill migrate -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/adobe/skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/stardust/skills/migrate .github/skills/migrate && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "migrate" agent skill from https://github.com/adobe/skills/tree/main/plugins/stardust/skills/migrate into .github/skills/migrate/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add adobe/skills --skill migrate -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install adobe/skills migrate --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/adobe/skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/stardust/skills/migrate .opencode/skills/migrate && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "migrate" agent skill from https://github.com/adobe/skills/tree/main/plugins/stardust/skills/migrate into .opencode/skills/migrate/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
migrateApply DESIGN, canon, and modules to every page in the inventory, producing a deployable static HTML site.
Migrate is an agent skill from adobe/skills. Apply DESIGN, canon, and modules to every page in the inventory, producing a deployable static HTML site. Use to migrate or render the whole captured site into the redesigned static tree ("migrate the pages", "render the migrated site", "apply the design to all pages", "build the deployable site", "convert the approved prototype into the full site") — the page-rendering step between prototype and deploy/rollout. Three render branches (approved page, template-applied sibling, unique render), with a declared…
Its SKILL.md is about 7.6k tokens, which your agent loads only when the skill is triggered. The skill folder holds 15 other files, including scripts (for example `reference/asset-bundling.md`, `reference/content-preservation.md` and `reference/fidelity-tiers.md`). Compatibility notes: Requires Node 22+, Playwright with Chromium resolvable from the project, playwright-cli on PATH, and the impeccable skill (github.com/pbakaus/impeccable)…
It works with Adobe Experience Manager. The repository describes itself as: Adobe Skills for Agents. The licence is Apache-2.0.
4 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit cbc9952. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 2 files in scripts/ (JavaScript), which the agent can run.
Shell commands in SKILL.md call:
nodenpmFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
google.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Requires Node 22+, Playwright with Chromium resolvable from the project, playwright-cli on PATH, and the impeccable skill (github.com/pbakaus/impeccable) installed alongside stardust.
From compatibility in the SKILL.md frontmatter.
Migrate loads about 7.6k tokens when it runs. Until then it costs about 152 tokens; SKILL.md has 2,963 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from adobe/skills at commit cbc9952, republished under its Apache-2.0 licence (© adobe). 2,963 words, ~7,564 tokens.
.claude/skills/migrate/SKILL.md (or your agent's skills folder). This skill also uses 11 other files; get the full folder from GitHub.Apply the target spec authored by direct, the visual canon
written by prototype --prep, and the brand-module catalog
extracted during prepare-migration to every page in the
inventory. Produces a self-contained, deployable static HTML site
under stardust/migrated/. Per-page, incremental, idempotent.
migrate is the final stardust phase. Output is platform-
agnostic HTML — downstream conversion (AEM EDS, a CMS, a
framework) is the job of a separate plugin that consumes
migrated/ plus DESIGN.json plus the per-page _meta.json
sidecars.
<slug> — optional positional. Migrate just this page. Without
it, migrate every page whose status is directed,
prototyped, or approved (and not stale).--all — migrate every page including stale ones.--force — re-migrate every page even when the idempotent
skip would skip them.--require-approved — refuse to migrate any non-approved
page. Default behaviour migrates directed pages too (using
Path A′ or Path B per
reference/template-and-module-rendering.md); this flag flips
approval-gating on.--strict-canon — refuse approvals that conflict with canon.
Default logs the deviation and continues. Useful for projects
where canon discipline matters more than per-template
flexibility.--clean — delete assets previously bundled but no longer
referenced from stardust/migrated/assets/. Off by default
(migrate is additive). Implies --force: every page is
re-rendered so the run's bundledAssets Set is the complete
union of currently-referenced assets — otherwise --clean
would risk deleting assets still referenced by
idempotent-skipped pages. See
reference/asset-bundling.md § Stale asset cleanup.--pin-timestamp <ISO8601> — pin the migrate-provenance
timestamp so re-runs without source changes produce byte-
identical HTML. Default re-uses the current wall clock, which
is fine for normal use; CI deployment fingerprinting may want
the pin.The mobile-adapt audit, content-sourcing scan, and placeholder
refusal are all mandatory gates — there is no --skip-* or
--allow-* flag to bypass them. If a gate refuses a page, the
remediation is to fix the proposed file (re-prototype, edit
inline, or run an impeccable command) and re-invoke migrate.
Playwright re-probe (mandatory first step). --no-save playwright
installs from earlier phases are pruned by any later real npm i
(extract SKILL.md § Setup → --no-save installs are ephemeral). Before
any rendering step, probe
node -e "import('playwright').then(()=>process.exit(0))" from the
project root and re-install (npm i -D playwright --no-save --legacy-peer-deps) on failure.
Run the master skill's setup
(skills/stardust/SKILL.md § Setup). Flow guard. If
stardust/state.json exists without flow and the ask is a
migration (a URL plus "migrate" / "to EDS" / "re-platform"), do not
run: print the two-flow table from the master skill § Two migration
flows and hand back to its routing — the flow is chosen and stamped
there before any sub-skill runs
(skills/stardust/reference/state-machine.md § Flow keys): replica
unless the ask names a redesign.
(Recorded: migrate <url> as the first command of two same-design
migrations led to a hand-built compiler tuned by eye instead of the
replica gate.)
Verify stardust/state.json exists with at least one
directed page.
Verify project-root DESIGN.md and DESIGN.json exist with
DESIGN.json.extensions.canon populated.
Verify stardust/canon/ exists with at least
header.html, footer.html, canon.css.
Canon auto-bootstrap (when steps 3–4 find no canon). The
documented prototype → migrate → deploy happy path does not
run prepare-migration, so a first migrate legitimately arrives
with no canon (observed on 4 of 6 e2e sites, where every run had
to derive canon by hand to proceed — this is the fix). When
canon is absent and at least one approved prototype exists,
do not stop: run the canon write-back inline from the first
approved prototype (the canon-author, default home) per
../prototype/reference/canon-extraction.md § Five-step
procedure — extract header.html / footer.html / canon.css
to stardust/canon/, pin tokens + compositional moves to
DESIGN.json.extensions.canon, and record
canon.source: "auto-bootstrap: <slug>". This is exactly what
prototype --prep does on first approval; migrate performs it
on demand so the core pipeline never dead-ends. Only stop and
recommend $stardust prepare-migration when canon is absent
and no approved prototype exists (there is nothing to derive
canon from). Under state.json.handsOff the bootstrap is
automatic and logged; interactively, surface it as a one-line
notice before proceeding.
Verify stardust/direction.md has an active (not pending)
direction.
Read state.json.pages[] and partition into:
directed, prototyped, or
approved, stale: false (or --all / explicit
<slug>).Validate provenance on every in-scope page. Call
validateProvenance(page) per
skills/stardust/reference/state-machine.md § Provenance
validation for every page in inScope. Abort with the
helper's error when any page lacks live-render evidence —
migrating a synthesized page record produces deployable HTML
that misrepresents the source site, the exact failure mode
that motivated the validator. Surface Provenance OK on N pages in the migrate-plan output before Phase 1.
Mobile-adapt audit on every Path A / Path A′ source. For
every page whose render branch consumes a proposed or
archetype HTML file (Path A, Path A′ per
reference/template-and-module-rendering.md § Render path
selection), run the audit per skills/prototype/SKILL.md
§ Mobile-adapt audit:
<meta name="viewport" content="width=device-width, ...">
present, width not pinned to a fixed pixel value.@media (max-width: ...) rule.Refuse pages that fail — the audit is mandatory; there is no
skip flag. The user fixes the proposed file (re-prototype or
chat-driven impeccable command) and re-invokes migrate.
Record the audit result per page in the migrate report and
in the post-render _meta.json#audit.adapt sidecar. Path B
(unique-renders) skips the audit because adapt hasn't run
on those pages — a Path B page that needs mobile coverage
gets it via $impeccable adapt invoked separately by the
user. Surface this distinction in the report so it's not
read as a silent skip.
Dynamic-surface precondition (safety net). If
stardust/dynamic-features.md is missing, the hand-run flow
(extract → direct → prototype → migrate) never passed a pre-import
gate: run the stardust dynamics skill Phases 1–3 now (extract --dynamics
for reach if needed, detector on the archetypes, triage draft, curate)
before rendering any page. Never import a site as static without a
decision per dynamic row. Per page, rows of the inventory that touch it
become contentDeviations[] kind: "dynamic-dependency" entries
(reference/content-preservation.md § Dynamic dependencies).
Gated-archetype precondition (flow: replica). Before rendering any
sibling-tier page, read stardust/replica/progress.json: the page
type's archetype must have a gate result at every configured breakpoint
that is pass: true, or over the bar with every residual carrying a
cause (../replica/reference/source-fidelity-gate.md § Residual
logging format — a documented residual is a pass with an asterisk). An
archetype never gated, or over the bar with no residual entries, blocks
its page type: report the archetype slug and $stardust replica <archetype>, and render nothing for that type. The same rule guards
rollout Setup; the published-origin re-gate is unchanged. Thresholds
are the gate's.
Print the plan and wait for confirmation when the scope is large:
migrate plan
============
In scope: 127 pages
Path A (approved) 6 pages: home, news/post-housing-summit, news, ...
Path A' (template-applied) 118 pages: 84 article, 5 listing, 11 program, 2 form, 16 static
Path B (unique) 3 pages: 404, search, faq
Skipped: 0 stale, 0 unscoped
DESIGN.md sha: 1a2b3c4
DESIGN.json sha: 5d6e7f8
Canon shas: header:7g8h9i footer:9i0j1k css:1k2l3m
Output: stardust/migrated/ + per-page _meta.json sidecars
Idempotent skip: enabled (run with --force to override)
Reply "go" to proceed.For 1-3 pages or <slug> invocation, skip the confirmation.
In the replica flow a sibling renders only after its archetype is deployed and gated at the
published origin (../replica/reference/handoff-contract.md § 3 row C, unit C-archetype; #126);
the render is the encoder's input, its gate is the row after PUT. For each page in scope, follow
reference/migration-procedure.md and
reference/template-and-module-rendering.md:
designMd, designJson, sourceCurrent, sourceProposed,
canonShas, archetypeSource).[data-placeholder]
elements or non-empty _provenance.unsourcedContent[] are
present — the user fills the missing content in the proposed
file before re-invoking migrate. No bypass flag.fidelityTier from the branch — A → archetype (craft-gated),
A′ → sibling (canon-fork, the cheap default for breadth — variance-probed
once per template before cloning, reference/fidelity-tiers.md § Sibling
variance probe; deltas become variant classes, never per-page forks),
B/bodyless → thin — per reference/fidelity-tiers.md. Record
fidelityTier, archetypeSource, template (the archetype's slug;
the archetype's own sidecar leaves it null), modules[] (the page's
block ids — composite sections only) and gatesPassed[] in
_meta.json so coverage shows what was craft-gated vs cloned and
rollout groups and dedups from the sidecars, without a census.stardust/canon/modules/<id>.html; bespoke slots logged
with data-bespoke.reference/content-preservation.md. Internal-link rewriting
always emits migrated-tree paths; missing slugs flagged
broken.reference/fidelity-tiers.md § Content-count acceptance:
compare role-classified node counts (headings, body/list
nodes, CTAs, images) between the captured source page JSON
and the rendered result. A count drop in any class not
covered by a logged contentDeviations[] entry fails the
page — dropped-content importer bugs must surface here,
while the importer is still cheap to fix, not at a
downstream fidelity gate. Record the pass in
_meta.json#gatesPassed[] as "content-count".<head> metadata per
reference/metadata-and-jsonld.md (five categories;
page-type-driven JSON-LD).reference/asset-bundling.md § Detection), copy each unique
referenced subpath from stardust/current/assets/<subpath> to
stardust/migrated/assets/<subpath> (preserving subdir
structure), then rewrite every reference to the root-relative
form /assets/<subpath>. Cross-page dedup uses a
module-level Set seeded from
state.json.migrate.bundledAssets[]. Missing source assets
warn-and-skip per § Edge cases; the bundle stays internally
consistent.reference/media-reconciliation.md. Cross-origin <img> kept
as source URLs must skip createOptimizedPicture (it drops
the ?v= key and corrupts the rendition); broken URLs are
repaired (missing ?-delimiter, wrong host) or omitted, never
shipped as about:error. rollout re-runs the authoritative
network resolve at delivery (media-reconcile.mjs).<slug>-cinematic.html exists).
Migrate consumes the STATIC prototype only — the cinematic layer
is never merged. Copy the motion assets (lenis.min.js,
lenis.min.css) from stardust/prototypes/ to
stardust/migrated/assets/motion/ (idempotent) for downstream
consumers (deploy/rollout decide whether to wire them), and
record cinematic-variant-not-consumed in the page's
_meta.json#migrationDecisions[].index.html and the _meta.json
sidecar in the same directory. Provenance block as first
child of <head>. Record assetsBundled (count of unique
asset refs on this page) in _meta.json.The mechanics of this phase are scripted:
node skills/migrate/scripts/migrate.mjs render <slug…|--all> (the
project copy runs from stardust/scripts/migrate/) builds the page
map, places each page at its URL-literal path, rewrites internal
links, bundles assets, composes <head> (provenance, :root,
canonical and JSON-LD defaults), validates strictly and writes the
sidecar, skipping pages whose input shas are unchanged. The judgments
it cannot make are recorded on the sidecar with gate, deviation,
decision, variant and modules on the same script; it never
advances pages[].status.
Recorded units. A whole-site render is bookkept as units in
stardust/migrate/progress.json, the shape of rollout's C-deliver unit
ledger (../replica/reference/handoff-contract.md § 3 row C):
units.<name>: {status: pending|running|done|failed, kind: plan|render|assets|report, templates[], pages: n, startedAt, endedAt, verdict}. One plan unit (Phase 1), one render unit per template
cluster of at most ~8 siblings (migrate.mjs render <slug…> takes the
cluster's slug list), one assets unit when Phase 3 rehosts media, one
report unit (Phase 4). Per unit, in this order: the progress.json
write → the checkpoint commit → the next unit; a unit end is a safe
resume point, not a stop. A session resumed inside migrate reads the file
and runs only the units not done; a unit left running re-renders its
slugs — the driver is idempotent, unchanged pages are skipped. A recorded
run rendered 31 siblings through five parallel builders as one unit in
one session — its most expensive — with no resume point between the plan
and the final report.
Per-page asset bundling already happened in Phase 2 (every
referenced media subpath is on disk under
stardust/migrated/assets/). Phase 3 fills in the sitewide
assets that no individual page references explicitly:
Copy stardust/current/assets/logo.<ext> to
stardust/migrated/assets/logo.<ext> (only if missing or
stale). Record under state.json.migrate.bundledAssets[].
Verify favicon variants and font files were generated by
prepare-migration Phase 4. If absent, log a warning and
continue (the migrated site renders without them, just
missing some platform-specific affordances).
Add stardust/migrated/robots.txt and sitemap.xml
derived from the migrated page inventory per
reference/metadata-and-jsonld.md § Sitemap entry.
If --clean was passed, compute
stale = priorBundle.filter(p => !bundledAssets.has(p))
from state.json.migrate.bundledAssets[] and remove each
stale subpath from stardust/migrated/assets/. Record the
deletions under state.json.migrate.cleanedAssets[]. Per
reference/asset-bundling.md § Stale asset cleanup.
Verify portability. The bundle must work via file://,
at a webserver root, and at any subpath — "one shape, works
everywhere". Run every audit; any non-empty grep output or
non-zero fixture exit fails the run with the cited error
message:
# No source-tree escapes
find stardust/migrated/ -type f -name '*.html' -exec grep -l '\.\./current/' {} +
# Error: "asset still points outside the migrated tree; rewrite via the
# asset-bundling pass per reference/asset-bundling.md § Detection"
# No absolute internal references in attribute values (404 on file:// and subpath)
grep -rE '(href|src)="/[^/]' stardust/migrated/ --include='*.html'
# Error: "absolute href `/beers/` will 404 on file:// and on subpath hosts;
# rewrite via the page map per migration-procedure.md § Reference shape"
# No absolute internal references in url() (inline style, <style> blocks, CSS)
grep -rE 'url\(\s*["'\'']?\s*/[^/]' stardust/migrated/ --include='*.html' --include='*.css'
# Error: "absolute url(/...) reference will 404 on file:// and on subpath hosts;
# rewrite via the asset-bundling pass per asset-bundling.md § Rewrite"
# No directory-only nav (doesn't resolve on file://). Pattern accepts
# only relative or root-absolute hrefs (./, ../, /, or bare segment)
# so external URLs like https://google.com/ aren't false-flagged.
grep -rE 'href="(\.{0,2}/|[a-zA-Z0-9_-])[^:"#?]*/"' stardust/migrated/ --include='*.html'
# Error: "directory-only href `./beers/` won't resolve on file://;
# append the explicit index.html (or the source URL's .html leaf)
# per § Reference shape"
# pageMap consistency — every internal href appears as an outputPath
node skills/migrate/fixtures/pagemap-audit.mjs stardust/migrated/ stardust/state.json
# Error: "internal href has no pageMap entry; link rewriting bypassed the
# page map per § Page map (build once, use everywhere)"
# Headless file:// round-trip — the test that proves zip-and-deploy works
node skills/migrate/fixtures/file-protocol-audit.mjs stardust/migrated/
# Error: "<offending file> linked <ref> that 404s under file://; see the
# Playwright network log printed above"The audits are mandatory — there is no skip flag. The contract is "self-contained, zip-and-deploy" and these audits are the verifiers that back the claim.
Asset migration is idempotent — files are content-hashed and copied only when missing; per-page bundling deduplicates across the run.
Update state.json:
status advances to
migrated, append a history entry, clear any stale flag,
set migratedPath.state.json.lastRun.failures[].migrate block per
skills/stardust/reference/migrate-output-format.md
§ State.json contract: selfContained: true, outputDir,
totalAssetsBundled, bundledAssets[], per-page
assetsBundled counts, missingAssets[], cleanedAssets[].
This is the forward-compat signal downstream consumers test
for.Print the run summary:
migrate complete
================
122 migrated home, about, news/post-housing-summit, ...
3 unchanged about, programs/shelter, news/post-old (idempotent skip)
2 failed contact (validation: required slot missing),
legal/privacy (validation: color-reservation violated)
0 stale skipped
Render branches:
Path A 6 approved-from-prototype
Path A' 116 template-applied (84 article, 5 listing, 11 program, 2 form, 14 static)
Path B 3 unique-render (404, search, faq)
Pages with non-trivial decisions: 12
about canon-deviation: footer carries financials disclaimer
donate template-adapted: amount-pills slot moved above headline
...
Broken internal links: 5
/events referenced by 2 pages; not in inventory
/press referenced by 1 page; not in inventory
...
Bespoke slots crossing promotion threshold: 1
hotline-211: "state" (3 instances) — consider `$stardust prepare-migration --refine-module`
Missing assets: 2
generated/orphan-1.jpg referenced by 1 page (home)
generated/orphan-2.jpg referenced by 2 pages (about, contact)
(Re-extract or accept the gap — bundle is deployable; refs 404 at view time.)
Output: stardust/migrated/ (122 pages, 47 bundled assets, 4.2 MB) — self-contained, zip-and-deploy
Next:
- Review: open stardust/migrated/index.html in a browser
- Audit: $impeccable critique stardust/migrated/
- Deploy: cd stardust/migrated && zip -r ../site.zip .
upload the zip to any static host that serves at the host root
- Refine: edit DESIGN.md or canon files, then re-run $stardust migrate| Path | Purpose |
|---|---|
stardust/migrated/<source-url-path> | Migrated page. Output path mirrors the source URL literally (see reference/migration-procedure.md § Output path mapping). The bundle is zip-and-deploy: drop on any static host at any path, or open index.html directly via file://. Every internal reference is relative to the page that emits it; nav targets carry an explicit index.html (or the source URL's literal filename) so file:// resolves without a server. |
| _meta.json sidecar | Lives next to each migrated page. For <dir>/index.html the sidecar is <dir>/_meta.json; for <dir>/<name>.html the sidecar is <dir>/<name>._meta.json so multiple .html siblings don't collide. Per reference/migration-procedure.md § _meta.json sidecar. |
stardust/migrated/index.html | The home page (special case). |
stardust/migrated/_meta.json | Home sidecar. |
stardust/migrated/assets/logo.<ext> | Brand logo (sitewide). |
stardust/migrated/assets/<subpath> | Every asset referenced by any migrated page, bundled. Source subdir structure preserved verbatim. |
stardust/migrated/assets/favicon.<ext> + variants | Favicon and apple-touch-icon, manifest icons. |
stardust/migrated/assets/fonts/... | Downloaded font files (from canon @font-face URLs). |
stardust/migrated/robots.txt | Minimal robots.txt. |
stardust/migrated/sitemap.xml | Sitemap derived from migrated inventory + page types. |
stardust/state.json | Updated with migrated status, history, and the migrate block (selfContained: true, asset counts). |
The driver (node stardust/scripts/migrate/migrate.mjs render …) writes
the per-page rows above (index.html / <name>.html, _meta.json,
bundled assets/**) and the migrate block of state.json (pageMap[],
bundledAssets[], pages[], missingAssets[], lastRun); status
changes, robots.txt and sitemap.xml stay with Phases 3–4.
The whole pipeline is built around two properties:
$stardust migrate with no
changes produces zero file writes. Every page is sha-compared
across designMd, designJson, sourceCurrent, sourceProposed
(Path A), canonShas, archetypeSource (Path A′) — and skipped
if all match.These properties hold even when DESIGN.md, canon, or modules are edited mid-run: the edit changes the relevant sha, so the next migrate run re-renders every affected page (canon and DESIGN.md edits typically affect every page).
When direction.md, canon, or the module catalog changes after
some pages have been migrated:
stale: true per
skills/stardust/reference/state-machine.md § Stale flagging.
Stale-flagging is content-aware in all three trigger cases.$stardust migrate (no flags) skips stale pages and reports
the count.$stardust migrate --all re-migrates each stale page,
clearing the flag on success.$stardust migrate <slug> always operates on the named page,
stale or not.The user decides whether stale pages should be refreshed — direction/canon/module changes don't invalidate prior migrated work, they just mark it as out-of-step.
$stardust direct (or
$stardust extract if no extracted state).$stardust direct.$stardust prepare-migration (or approve a prototype first).state.json.lastRun.failures[]. Do not abort the whole run.migrationDecisions[] with
kind: "asset-missing". The migrated <img src> keeps the
original absolute URL as a fallback.[data-placeholder]
elements. Surface the unsourced list and recommend sourcing
real content (re-prototype, or edit the proposed file
directly). There is no bypass flag — shipping placeholders to
a public site is the failure mode this gate exists to prevent.extensions.divergence.brand_faithful_inversions[] is lifted
from validation per T&M § Brand-faithful inversion handling.
Emit a one-line note in the run summary acknowledging the
lift.$impeccable critique stardust/migrated/ after migration if
you want a quality assessment.prototype;
migrate consumes the result.reference/migration-procedure.md — per-page render procedure,
output path mapping, validation, provenance shape, idempotent
skip, sidecar schema.reference/template-and-module-rendering.md — three render
branches in detail, slot injection, deviation policy,
validation contracts.reference/metadata-and-jsonld.md — head composition, JSON-LD
per page-type, canonical strategy.reference/content-preservation.md — what's kept,
transformed, dropped; internal-link rewriting; asset path
rewriting; form handling.reference/asset-bundling.md — detection / copy / rewrite
contract for the per-page asset-bundling phase.skills/stardust/reference/migrate-output-format.md — the
self-contained-bundle contract downstream consumers can rely
on (asset reference shape, directory layout,
state.json.migrate block).skills/stardust/reference/token-contract.md — :root block
refreshed from DESIGN.md on every render.skills/stardust/reference/data-attributes.md — structural
attributes including data-template, data-module,
data-slot, data-canon, data-deviation, data-bespoke,
data-broken-link.skills/stardust/reference/state-machine.md — page lifecycle,
page typing, stale-flagging cascade.skills/stardust/reference/artifact-map.md — provenance shape
for migrated artifacts; canon files; sidecar shape.skills/prototype/reference/canon-extraction.md — how canon
is built (input to migrate).skills/prepare-migration/SKILL.md — the cascade that
produces every input migrate consumes.© adobe, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 11 other files (scripts) in plugins/stardust/skills/migrate of adobe/skills.
Open the folder on GitHubat commit cbc9952
Migrate next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Migrate this skilladobe/skills | 195 | — | ~7.6k | Automated safety check: Pass | Apache-2.0 | |
| Sanity Migrationsanity-io/agent-toolkit | 187 | — | ~1.4k | Automated safety check: Pass | MIT | |
| Content Management Systemsgithub/awesome-copilot | 40k | 1 repos | ~1.3k | Automated safety check: Pass | MIT | |
| App Builder UI ScaffolderNeverSight/learn-skills.dev | 216 | 1 repos | ~2.2k | Automated safety check: Pass | Apache-2.0 | |
| Authoring Analysismajiayu000/claude-skill-registry | 666 | 2 repos | ~3.1k | Automated safety check: Pass | MIT | |
| Block Inventorymajiayu000/claude-skill-registry | 666 | 1 repos | ~2.1k | Automated safety check: Pass | MIT |
sanity-io/agent-toolkit
Plans, implements, and reviews migrations from other CMSes and content systems into Sanity.
github/awesome-copilot
Workflow for building and modifying content management systems across WordPress, Shopify, Wix, Squarespace, Drupal, WooCommerce, Joomla, HubSpot CMS Hub, Webflow, Adobe Experience Manager, and…
NeverSight/learn-skills.dev
Generates React Spectrum UI code for Adobe Experience Cloud Shell apps and AEM UI Extensions from annotated patterns.
majiayu000/claude-skill-registry
Analyze content sequences and determine authoring approach (default content vs blocks).
majiayu000/claude-skill-registry
Survey available blocks from local AEM Edge Delivery Services project and Block Collection to understand the block palette available for authoring.
majiayu000/claude-skill-registry
Identify section boundaries and content sequences within a scraped webpage for AEM Edge Delivery Services import.
adobe/skills
Scaffolds, implements, deploys and debugs Adobe Runtime actions in App Builder projects, with templates for webhooks, events, database CRUD, sequences and Asset Compute workers.
adobe/skills
Launches Chrome with an unpacked extension over CDP, opens its sidepanel, popup or options page, and hands over to cdp-connect for clicks, typing and screenshots.
adobe/skills
Extracts icons, metadata, text, forms, videos and social links from any web page with playwright-cli, with SVG icon classification and cleanup.
adobe/skills
Detect all languages used on a webpage — both declared (html@lang, hreflang alternate links, nested lang= attributes, meta content-language) and actually present in the body text (Google CLD3 via…
adobe/skills
Prepare any webpage for clean interaction by detecting and removing disruptive overlays (cookie banners, GDPR consent, modals, popups, newsletter signups, paywalls, login walls).
adobe/skills
Reduce a webpage to a structural skeleton with semantic tokens.
Works with
Apply DESIGN, canon, and modules to every page in the inventory, producing a deployable static HTML site. Migrate is an agent skill from adobe/skills. Apply DESIGN, canon, and modules to every page in the inventory, producing a deployable static HTML site.
Migrate fits situations like: render the whole captured site into the redesigned static tree (migrate the pages; render the migrated site; apply the design to all pages; build the deployable site.
Run `npx skills add adobe/skills --skill migrate -a claude-code`. Or copy the skill folder (plugins/stardust/skills/migrate in adobe/skills) into .claude/skills/migrate in your project. Claude Code loads it when a task matches its description.
Run `npx skills add adobe/skills --skill migrate -a codex`. Or copy the skill folder (plugins/stardust/skills/migrate in adobe/skills) into .agents/skills/migrate in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add adobe/skills --skill migrate -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/migrate, .gemini/skills/migrate, .github/skills/migrate and .opencode/skills/migrate in your project.
Going by SKILL.md and its folder, Migrate needs JavaScript for the scripts in its folder and the command-line tools its instructions call (node and npm). Our summary lists: Node.js. Compatibility (from SKILL.md): Requires Node 22+, Playwright with Chromium resolvable from the project, playwright-cli on PATH, and the impeccable skill (github.com/pbakaus/impeccable) installed alongside stardust..
SKILL.md names 1 domain. In commands or code: google.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Migrate is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.6k tokens (SKILL.md is roughly 30k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Migrate: Sanity Migration (sanity-io/agent-toolkit, 187 stars), Content Management Systems (github/awesome-copilot, 40k stars), App Builder UI Scaffolder (NeverSight/learn-skills.dev, 216 stars) and Authoring Analysis (majiayu000/claude-skill-registry, 666 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
adobe (a GitHub organization) maintains it in adobe/skills, which has 195 GitHub stars. The repository holds 105 skills in this directory. The repository was last updated on October 6, 2026.
Source: adobe/skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.