Forge migrate
An assembly line for AI software development. 35 skills, 11 agent personas, 29 commands. From raw idea to shipped code.
npx -y skills add aneja5/forge-skills --skill forge-migrateAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when upgrading forge-skills across a major version (e.g., from v2.x or v3.0/3.1 to v3.2+), when .forge/ artifacts exist but lack forge:meta headers, when forge-sync reports a wall of "untracked" rows, or when the user asks "why doesn't sync see my existing files".
SKILL.md
6.2 KB, as published. Nobody here has run it
forge-migrate
Overview
Backfill forge:meta headers onto pre-existing .forge/ artifacts so they enter the dependency tracking system. Reads filenames against the canonical artifact table in references/forge-dependency-graph.md to infer generated_by and depends_on. Sets generated_at to the file's mtime (UTC), and computes content_hash from the current contents. Read-then-write only — never regenerates an artifact, just annotates what's already there.
When to Use
- Upgrading from a pre-3.2.0 forge-skills release where
.forge/artifacts had no headers forge-syncreports every artifact as "untracked" / "no header"- A teammate without the plugin produced
.forge/files on a shared branch and you want them tracked - Need to bring legacy artifacts under the dependency graph without re-running expensive skills (interviews, audits)
When NOT to Use
- The artifact is genuinely stale and should be regenerated — use the source skill instead (e.g.,
/specto refreshprd.mdrather than back-stamping it) .forge/doesn't exist — there's nothing to migrate- All artifacts already have valid
forge:metaheaders —forge-syncwill tell you this; migration is a no-op - The file isn't on the canonical artifact list — don't invent dependencies for ad-hoc files
Common Rationalizations
| Thought | Reality |
|---|---|
| "I'll just re-run every skill to get fresh headers" | Forces re-interview and re-audit — burns hours when a 30-second backfill is correct |
| "The files work without headers" | They work for reading. They break for forge-sync, /forge-migrate itself, and downstream staleness detection. |
| "I'll write the headers by hand" | Hand-written headers drift from the schema. The skill enforces UTC, hash format, dependency inference. |
| "Use today's timestamp — it's close enough" | Today's timestamp tells forge-sync the artifact is newer than its upstream. False UP_TO_DATE. Use the file's mtime. |
| "All artifacts depend on prd.md, just list that" | Inferring depends_on from the canonical graph keeps cascade rules correct. Don't fabricate dependencies. |
Red Flags
- A migrated artifact has
generated_atset tonowinstead of file mtime generated_atis local time instead of UTC withZsuffixcontent_hashis missing or not 8 hex chars- A file not on the canonical artifact list received a fabricated
generated_by - The skill regenerated content instead of just adding a header
Core Process
Step 1: Scan .forge/ for unheadered files
For every file under .forge/ (recursively):
- Read the first ~30 lines.
- If a
<!-- forge:meta -->block (or# forge:metafor YAML) is present and well-formed → skip, already tracked. - If absent or malformed → candidate for migration.
If .forge/ doesn't exist, exit: "Nothing to migrate."
Step 2: Match each candidate against the canonical graph
Read references/forge-dependency-graph.md. Look up each candidate's filename in the "Artifact-producing skills" table to recover:
generated_by(the skill that owns this filename)depends_on(the canonical upstream set)
For unmatched files (not on the canonical list), do NOT fabricate a header. Report them under "unmatched — manual review" and move on. Common cases: ad-hoc notes, half-finished drafts, project-specific extensions.
For globbed outputs (contracts/*.md, adr/*.md, redacted/*), every file in the directory inherits the parent skill's depends_on.
Step 3: Compute metadata per file
For each matched candidate:
generated_at: read the file's mtime viastat; convert to ISO 8601 UTC withZsuffix (e.g.,2026-05-12T14:30:00Z). If mtime is unavailable, fall back to "now" UTC and flag for user awareness.content_hash: sha256 over the entire current file body; take the first 8 hex chars.depends_on: from Step 2.generated_by: from Step 2.
Step 4: Confirm with the user before writing
Present the proposed migration plan:
3 files will receive backfilled headers:
.forge/prd.md
generated_by: spec-driven-development
generated_at: 2026-04-22T09:15:00Z (file mtime)
depends_on: [.forge/idea-brief.md]
content_hash: 3f9a2b1c
.forge/architecture.md
...
.forge/contracts/auth-service.md
...
1 file will NOT be migrated (unmatched):
.forge/scratch-notes.md — not in canonical artifact table
Proceed? Y/n
Do not write until confirmed. Migration is structurally non-destructive, but the user's confirmation is the chain-of-custody event.
Step 5: Prepend headers
For each confirmed file, prepend the forge:meta block at the top. For Markdown, use the HTML comment form. For YAML, use the # forge:meta indented form. Do NOT modify any other content.
After writing, verify by re-reading the first lines and confirming the block parses.
Step 6: Report
Print a summary:
Migrated 3 files. Unmatched: 1 (.forge/scratch-notes.md — review and either add to canonical graph or delete).
Run /sync next to see the chain status with these new headers.
Recommend /sync as the natural follow-up — the user just installed headers; verifying the dependency chain is the immediate next step.
Verification
- Every candidate file's
generated_atis set to its mtime in UTC withZsuffix (not "now") - Every
content_hashis 8 hex chars, computed over the entire current file body -
generated_byfor each migrated file matches an entry in the canonical artifact table -
depends_onfor each migrated file matches the canonical graph (not fabricated) - Files not on the canonical list are reported under "unmatched", not migrated with invented headers
- Glob outputs (
contracts/*.md,adr/*.md) each got their own header - User confirmed the migration plan before any file was written
- No artifact's body content was modified — only the header was prepended
-
/syncrecommended as next step