convert-spec
Skill4 starsChanged 2 months agoMITView on GitHub
Convert an existing design/spec file into a SpecForge spec in the store. Use when the user asks to "convert <file> to a spec", "import this design doc", or "turn this markdown/HTML into a SpecForge spec". Handles two cases: an existing SpecForge-style .html is ingested as-is; a .md or freeform design doc is re-authored into a full house-style HTML spec. Attaches the result to this session and lints before finishing.
In this repository10 other files it gives its agents.
- create-specSkill
- export-mdSkill
- exportSkill
- generate-templateSkill
- list-specsSkill
- migrate-specSkill
- review-specSkill
- start-specforgeSkill
- tune-templatesSkill
- write-reviewSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 0 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 76
Do not go looking for references/spec-language.md to supplement it: a rule the owner deleted is deleted.
- Very specific: line 79
Read the report before you touch anything.
- Very specific: line 95
Read the house rules: ${CLAUDE_PLUGIN_ROOT}/templates/house-rules.md, and the language contract, which is the language field above rather …
- Very specific: line 106
Keep every <section id="…">, the theme CSS, and the floating <nav class="toc"> (update TOC links to match the sections you keep).
- Very specific: line 147
Do not start a watcher or poll while idle.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
convert-spec
Bring an existing file into the SpecForge store. ${CLAUDE_PLUGIN_ROOT} below
denotes the installed plugin directory. Claude and Pi export it; Codex provides
the exact value in SpecForge SessionStart context. Substitute it in every path
and shell command.
1. Inspect the source
- The user names a file (
$ARGUMENTS). Read it and decide:- Already a SpecForge-style HTML spec (has the section ids / theme contract / structured plan) → ingest as-is (step 2A).
- A
.md→ convert withimport-md, then edit the result (step 2B). Do not hand-author a markdown source: the CLI does the mechanical part faithfully and reports what it could not read, which is a better starting point than a blank scaffold and your reading of the file. - A freeform
.htmldesign doc → author it into a scaffolded spec by hand (step 2C). There is no deterministic path for arbitrary HTML.
- Infer the spec type from the source —
research(a findings report),design(a design doc, no plan),design-impl(design + a plan), orimpl(a build plan). When the source is none of those, usegeneral: the scaffold plus a TL;DR, sections taken from the source's own headings. Pass it as--typebelow. A converted document keeps its own shape, sogeneralis the right answer more often here than when authoring from scratch.
2A. Ingest an existing HTML spec
node "${CLAUDE_PLUGIN_ROOT}/lib/specforge-cli.mjs" import "<file>" --title "<title>" --type <type> --model <your model id>Prints { id, htmlPath, url, status, type, language } — the file is copied into
the store, attached to this session, daemon ensured. Apply language to
anything you write into this spec, on the terms in 2B. Lint htmlPath
(step 3). If lint fails
because it isn't house-style, fall back to 2C and author into the htmlPath
you already have; 2C says so too, and running create there would leave this
spec behind and attach a second one. Not 2B: that path runs a markdown parser,
and handing it HTML would mechanically reconvert the document instead of shaping
it.
2B. Convert a .md — deterministic pass first, then edit
A markdown source is converted by the CLI, not by hand. It reads the file,
maps its headings onto sections, rebuilds any plan into the data-sf-* markup,
inlines the images that sit beside it, and produces a lint-passing spec:
node "${CLAUDE_PLUGIN_ROOT}/lib/specforge-cli.mjs" import-md "<file>" --model <your model id> [--title "<title>"] [--type <type>]--model is your own model id; the harness is detected. It credits you as the
converted spec's author, the same way create does.
It prints { id, htmlPath, url, type, status, language, report }. Then edit
htmlPath — the deterministic pass gives you a valid document to improve,
never a blank scaffold to fill.
language is the writing contract in force, and it is the whole of it. Not a
note added to a contract you read somewhere else: it already contains SpecForge's
own rules, unless this store's owner edited or removed them. Follow what it says and nothing it does not,
and apply it to everything you write while improving the converted document.
Do not go looking for references/spec-language.md to supplement it: a rule the owner deleted is deleted.
They edit this in the Configuration pane, under Language.
Read the report before you touch anything; it is the list of what needs you:
unsupported— constructs the parser could not read (setext headings, footnotes, reference links), each with its line number. The content is in the spec as plain text; convert it to house markup by hand.assetsDropped— images that were not inlined, with the reason (missing, too large, outside the source directory). Say so when you hand off.lint—PASSnormally. If it isFAIL,lintFailuresnames the checks.sections— how many the source produced.
Type: omit --type and the import is a general spec, which imposes no
section set — usually right, because a converted document keeps its own shape.
Pass --type only when the source really is a design / research / impl doc.
Then improve the result:
- Read the house rules:
${CLAUDE_PLUGIN_ROOT}/templates/house-rules.md, and the language contract, which is thelanguagefield above rather than a file. This is where an original's essay voice leaks through: convert the content, not the register. - Map the source onto the type's sections exactly as the
create-specskill describes (design / research / design-impl / impl) — adapt sections to the content; keep stable unique ids, the theme, and the floating TOC in sync. For impl types buildimpl-planas Stages → Tasks (data-sf-stage/data-sf-task/data-sf-status, one stage = one PR, each task averify:note) mirrored intotask-tracker, and leave the Runtime stubs. Preserve the author's intent; don't invent scope. - Keep every
<section id="…">, the theme CSS, and the floating<nav class="toc">(update TOC links to match the sections you keep).
For a spec general no longer fits (the source turned out to be a design with a
build plan), rescaffold with create --type <type> and move the content across;
do not grow a plan inside a general spec and call it typed.
2C. Author a freeform HTML doc into a spec
Arbitrary HTML has no deterministic path: it carries someone else's structure and styling, and there is nothing to map it onto mechanically. It gets authored.
Arriving from 2A (an HTML spec that turned out not to be house-style): you
already have an htmlPath in the store, attached to this session. Author into
that file. Do not run create — it would make a second spec and leave the
malformed one attached, so a later edit or handoff could pick up either. The
language 2A printed still applies: this is the authoring pass it was for.
Arriving from step 1 with a freeform HTML doc and no spec yet, scaffold one:
node "${CLAUDE_PLUGIN_ROOT}/lib/specforge-cli.mjs" create --title "<title>" --type "<type>" --model <your model id>It prints { id, htmlPath, url, type, language }. Author into htmlPath,
following the same house rules, section mapping and language contract as 2B
above, and applying language on the same terms.
3. Lint (must pass)
node "${CLAUDE_PLUGIN_ROOT}/lib/lint-spec.mjs" <htmlPath>Fix and re-run until PASS. Do not finish on a failing lint.
4. Hand off + arm review delivery
- Print the spec
url. The spec is attached to this session. Mention the original file is left untouched (its path is recorded as the spec'sorigin). - In Codex, finish the turn: the host-owned watcher delivers browser comments automatically.
Do not start a watcher or poll while idle. For explicit pickup, run
node "${CLAUDE_PLUGIN_ROOT}/lib/specforge-cli.mjs" review-waitonce and followreasonwhenreadyis true. Anext-turnresult means finish without re-arming. - In Claude Code, run that command as one background task per session and re-arm it after handling delivered work. Pi owns delivery through its extension.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

