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".
Scanned 5/28/2026
npx -y skills add aneja5/forge-skills --skill forge-migrate --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Forge Migrate?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/aneja5-forge-migrate)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: forge-migrate
description: 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".
---
# 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-sync` reports 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., `/spec` to refresh `prd.md` rather than back-stamping it)
- `.forge/` doesn't exist — there's nothing to migrate
- All artifacts already have valid `forge:meta` headers — `forge-sync` will 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_at` set to `now` instead of file mtime
- `generated_at` is local time instead of UTC with `Z` suffix
- `content_hash` is 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:meta` for 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 via `stat`; convert to ISO 8601 UTC with `Z` suffix (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_at` is set to its mtime in UTC with `Z` suffix (not "now")
- [ ] Every `content_hash` is 8 hex chars, computed over the entire current file body
- [ ] `generated_by` for each migrated file matches an entry in the canonical artifact table
- [ ] `depends_on` for 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
- [ ] `/sync` recommended as next step
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!