feat(cli): skillforge format <path> reformats SKILL.md to canonical shape - #13
Conversation
Reformat a SKILL.md to canonical shape — frontmatter keys in the schema declaration order (name, description, version, tags, author, homepage) with passthrough fields alphabetized at the end, trailing whitespace stripped, runs of 3+ blank lines collapsed to 2, exactly one trailing newline. Fenced code blocks are preserved verbatim. Schema-validates the output before writing. --dry-run reports the diff without writing; --check exits 1 on any change (CI mode); --write=false prints to stdout. Idempotent — running twice produces byte-identical output.
|
Warning Review limit reached
Your plan currently allows 1 review/hour. Refill in 35 minutes and 36 seconds. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more review capacity refills, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
What
skillforge format <path>— reformat aSKILL.mdto canonical shape. Seventh piece of the authoring workflow afterinit,validate,lint,pack,install, andupdate. Thinkprettierfor the SKILL.md envelope:lintflags style smells,formatfixes them.Semantics
name,description,version,tags,author,homepagetags: "[]"→tags: [](coerced back to YAML primitives)```)changed: false, no write, exit 0Body preservation
Unlike
update,formatdoes re-emit the frontmatter envelope — that's the whole point. But the body is treated gently: we trim trailing whitespace per line, collapse blank-line runs, and ensure a single EOF newline. Fenced code blocks are byte-verbatim (test asserts that trailing-space and 4-blank-line runs inside apythonblock survive untouched), and prose is never reflowed.Idempotence
Hard requirement, hard tested: a dedicated test runs format twice on a deliberately scrambled file (out-of-order frontmatter, passthrough keys, trailing whitespace, blank-line runs, code block) and asserts the second run is byte-identical to the first, with
changed: false.--check flag
Alias for
--dry-runthat exits 1 if the file would change. Drops into CI:Validation
The formatted frontmatter is run through
SkillFrontmatterSchemabefore anything hits disk. A description under 20 chars or a malformed version string causesformatto exit 1 with the schema error — the file is left untouched, never a half-written invalid SKILL.md on disk.Exit codes
--checkand the file would changeSame posture as
init/validate/pack/install/lint/update.Surface
src/format.ts—formatSkill()plus the canonical YAML emitter and body normalizer. ~340 LOC. No new runtime deps; reusesgray-matterfor parsing, hand-written emitter.src/format.test.ts— 17 tests covering frontmatter reordering, passthrough alphabetization, stringytagscoercion, trailing-whitespace stripping, blank-line collapse, trailing-newline normalization (add + collapse), code-block verbatim preservation, dry-run,--write=false, idempotence, no-op on canonical input, schema refusal, missing file, dir-without-SKILL.md, dir resolution, no-frontmatter rejection.src/cli.ts— newformatsubcommand with--write,--dry-run,--check.src/index.ts— re-exportsformatSkill,FormatOptions,FormatResult.README.md— new### skillforge format <path>section; status line updated.CHANGELOG.md—Unreleasedentry (no version-section migration; that's a release-prep PR).Gates
pnpm typecheck(tsc --noEmit)pnpm lint(biome)pnpm test(vitest)pnpm build(tsup)./dist/cli.js format … --checkon scrambled input./dist/cli.js format …✓ formatted …, exit 0./dist/cli.js format … --checkafter formatOn
formatvslintlintsurfacestrailing-whitespaceas a warning.formatfixes it. They compose: runformatto fix the auto-fixable, thenlintfor the residual semantic smells (description-no-trigger,missing-when-to-use, etc.) that need human judgment.Declaration of AI-Tools / LLMs usage