Skip to content

Latest commit

 

History

History
383 lines (282 loc) · 11.6 KB

File metadata and controls

383 lines (282 loc) · 11.6 KB

zero-md-formatter

GitHub Release npm version npm downloads CI

Zero-dependency GFM and MDX formatter with structural guardrails — trailing whitespace removal, table alignment, fence normalization, pipe-safety checks, column-count enforcement, and drift detection.

Designed for AI-agent workflows but works anywhere Node.js >=24 runs.

npm install -g zero-md-formatter
mdfmt --fix README.md

The CLI and formatter module have zero npm runtime dependencies. Installable on any system with Node.js >=24.


Quick start

Install from npm

npm install -g zero-md-formatter
mdfmt --fix README.md

Requires Node.js >=24. Zero runtime npm dependencies — no config file, no plugin system.

Use via npx (no install)

npx zero-md-formatter --fix README.md

Use programmatically

import { formatContent } from 'zero-md-formatter';

const result = formatContent(rawMarkdown);
console.log(result);

Run from source

git clone https://github.com/CodeSigils/zero-md-formatter.git
cd zero-md-formatter
node src/index.js --fix --guard README.md

What it does

Formatter-owned behavior:

  • Remove trailing whitespace
  • Ensure a final newline
  • Normalize leading-tab indentation outside fenced code blocks
  • Align GFM table columns when the table has no empty-cell ambiguity
  • Normalize tilde fences to backtick fences, escalating the backtick count when nested content requires it

Guard-owned behavior:

  • Fence closure and malformed fence info strings
  • Table column counts (header vs delimiter vs data row alignment)
  • Unescaped inline-code pipes in table rows
  • Adjacent-pipe table hazards (||| |)
  • Pre/post structural drift detection and rollback when --guard is used

What it doesn't do

  • No formatting config file — no .prettierrc, .markdownlintrc, or similar. No plugin system. Zero runtime dependencies means no extension points.
  • No dialect extensions — no Obsidian wiki-links, Mermaid, Pandoc, or frontmatter semantics.
  • No JSX/MDX validation — formats Markdown containers only; JSX inside is passed through unchecked.

CLI reference

mdfmt [options] <path...>
Flag Description
--check Read-only pipe-safety and format check (exit 0 if clean)
--fix Format files in-place after pipe-safety preflight (default)
--all Process directories recursively
--guard Pre/post structural check; rollback on drift; clean snapshots
--verify Run formatting, idempotence, and structural checks without writing
--fences Validate fenced code block info strings
--validate Run all structural validations
--doctor Check runtime prerequisites without modifying files
--dry-run, -n Run pipe-safety preflight, preview changes without writing
--audit-tables Print table row cell counts and pipe hazards without writing
--no-repair Report repairable table issues instead of modifying them
--version Print version number and exit
--help, -h Display help message

File exclusion

Create .mdfmtignore in the project root to exclude files from --all and explicit path processing. One pattern per line; # for comments. Patterns ending with / match directory prefixes; * matches any non-/ characters.

# Skip vendored docs and generated output
vendor/
docs/generated/
*.generated.md

Examples

# Check formatting (read-only, CI-safe)
mdfmt --check README.md

# Format with rollback-safe structural guards
mdfmt --fix --guard docs/

# Validate structure across a directory
mdfmt --validate --all docs/

# Diagnose installed readiness
mdfmt --doctor

Table and pipe safety

GFM tables are notoriously fragile in agent-generated Markdown. This formatter includes guard scripts that catch the most common failure modes before formatting:

  • Adjacent pipes (||) create empty cells per GFM. Write modes automatically insert a space (| |), preserving empty-cell semantics. Read-only modes block with a clear error.
  • Inline-code pipes (| cmd | opt | title |) look like extra columns to naive formatters. Guard scripts detect them and block formatting before corruption.
  • Column drift — rows with mismatched column counts are detected and, in write mode, repaired by padding short rows or rolling back on structural drift.
  • Empty-cell tables that remain ambiguous are preserved by skipping the full formatter pass. The delimiter row is still normalized to GFM-canonical width.
  • Unclosed-fence preflight — all modes detect unclosed fences before running table/pipe checks and skip validation that cannot be trusted while a fence is open. Read-only and guarded modes fail without modifying the file; unguarded write modes warn and continue formatting around the open fence.

Table-shaped content inside fenced code blocks is always left untouched.


Agent skill usage

The formatter ships as a standard agentskills-compatible skill via SKILL.md. It works with any agent that supports agentskills.io-formatted skills.

Install as a skill

With the standard skills CLI:

npx skills add CodeSigils/zero-md-formatter --skill markdown-formatter
Hermes Agent

Recommended for development — clone the repo and add to external_dirs:

skills:
  external_dirs:
    - /path/to/zero-md-formatter/skills

Every commit is immediately reflected without reinstalling.

For end users — install from hub:

# Add repo as skill tap (one-time), then install
hermes skills tap add CodeSigils/zero-md-formatter
hermes skills install CodeSigils/zero-md-formatter/markdown-formatter --yes

Then use the formatter via npm (recommended — gives mdfmt binary):

npm install -g zero-md-formatter
mdfmt --fix --guard README.md

Or run from source (no npm install):

node src/index.js --fix --guard README.md

For auto-wiring on every write_file or patch call — the hook script ships with the skill. You just need to register it:

# The script is already at:
#   ~/.hermes/skills/markdown-formatter/scripts/check-markdown.sh
# No download needed.

Then add the hook to config.yaml:

hooks:
  post_tool_call:
    - command: ~/.hermes/skills/markdown-formatter/scripts/check-markdown.sh
      matcher: write_file
    - command: ~/.hermes/skills/markdown-formatter/scripts/check-markdown.sh
      matcher: patch

This runs --fix --guard on every written Markdown file — formatting, repairing adjacent pipes, normalizing fences, aligning tables, and rolling back on structural drift before they reach git.

Codex CLI

For a repo-specific Codex skill, copy the tap payload into .agents/skills:

mkdir -p .agents/skills
cp -R skills/markdown-formatter .agents/skills/markdown-formatter

For a user-wide Codex skill, copy it to $HOME/.agents/skills instead. Codex also works directly with the CLI:

npm install -g zero-md-formatter
mdfmt --fix --guard README.md
Claude Code / OpenCode / Gemini CLI

All three can run the formatter as a normal shell CLI:

npm install -g zero-md-formatter
mdfmt --fix --guard README.md

Or clone the source and run the bundled CLI directly:

git clone https://github.com/CodeSigils/zero-md-formatter.git
node zero-md-formatter/src/index.js --fix --guard README.md

For native Agent Skills support, copy the tap payload to the runtime's documented skill directory:

# Claude Code
mkdir -p .claude/skills
cp -R skills/markdown-formatter .claude/skills/markdown-formatter

# OpenCode
mkdir -p .opencode/skills
cp -R skills/markdown-formatter .opencode/skills/markdown-formatter

# Gemini CLI
mkdir -p .gemini/skills
cp -R skills/markdown-formatter .gemini/skills/markdown-formatter

OpenCode and Gemini CLI also discover .agents/skills/markdown-formatter/. Claude Code also supports $HOME/.claude/skills/markdown-formatter/ for user-wide installs.

Portability

Component Portable?
CLI (src/index.js) Pure Node.js, no agent runtime required
SKILL.md agentskills.io base frontmatter
Guard scripts (4) Node.js, no agent tools referenced
Post-write hook config Hermes-specific (platform feature)

Safety policy

Reference spec: GitHub Flavored Markdown Spec.

  • check-tables.js enforces formatter-safe table column counts and pipe consistency, including unescaped pipes inside inline code spans. Stricter than GFM body-row parsing because autonomous formatting should not guess table intent.
  • check-pipes.js detects adjacent pipes in table rows, which create valid empty cells per GFM. Write modes repair them by inserting a space between the pipes. Read-only modes block with a clear error.
  • All CLI modes run pipe-safety preflight checks before table operations. When an unclosed fence is detected, the CLI warns that table and pipe checks are unreliable and skips them. Read-only modes and write mode with --guard fail fence validation without modifying the file. Unguarded write modes continue formatting around the open fence.
  • Write-mode --guard runs structural snapshots before and after formatting. If post-format structure doesn't match the pre-format snapshot, the original content is restored.

Supported file types

  • .md
  • .markdown
  • .mdx

Prerequisites

  • Node.js >=24
  • jq (Hermes shell hook only)

Run mdfmt --doctor to verify runtime readiness.


Install payload

The shipped runtime payload contains:

zero-md-formatter/
  SKILL.md
  src/index.js
  src/format-content.mjs
  guard/check-structure.js
  guard/check-fences.js
  guard/check-tables.js
  guard/check-pipes.js
  scripts/check-markdown.sh

The npm tarball also includes package metadata, README.md, and LICENSE. Repository-only files (test/, .github/) are excluded via the files field in package.json — scripts/ is not shipped with npm, except scripts/check-markdown.sh which is included in the Hermes tap payload (skill install) but not the npm package.


Project files


License

MIT