Stop copy-pasting code into documentation. Keep your markdown examples automatically synchronized with real source files.
Your documentation has code examples, but they get outdated:
- You update your source code but forget to update the docs
- Code examples in README/docs become stale and misleading
- Copy-paste errors introduce bugs in documentation
- Code examples can't be validated, linted, or tested like real source code
- Maintaining multiple copies of the same code is painful
markdown-code keeps your documentation in sync automatically:
- Single source of truth: Code examples come from real files
- Always accurate: Documentation updates when code changes
- Validated code: Snippets can be linted, type-checked, and tested like any source file
- Zero maintenance: Sync happens automatically in CI/CD
- Extract existing: Migrate current docs with one command
```js
function greet(name) {
return 'Hello ' + name; // Oops, code changed but docs didn't!
}
``````js snippet=src/utils/greet.js
function greet(name) {
return `Hello, ${name}! Welcome to our app.`; // Always current!
}
```Result: Your documentation stays accurate as your code evolves.
Install the markdown-code skill to give your AI coding agent knowledge of this tool's workflows and commands:
npx skills add scalvert/markdown-codeWorks with any agent that supports the skills ecosystem.
No installation required - use it directly:
npx markdown-code --help
npx markdown-code init --extractOr install once, then use the shorter md-code command:
npm install -g markdown-codeNow you can use the convenient md-code binary:
md-code --help
md-code init --extractNote: All examples in this README show both
npx markdown-codeandmd-codevariants.
Use the snippet= directive in your fenced code blocks:
```ts snippet=path/to/file.ts
// This content will be replaced
```
```ts snippet=path/to/file.ts#L10-L20
// This will include lines 10-20 only
```
```ts snippet=path/to/file.ts#L5
// This will include only line 5
```
```ts snippet=path/to/file.ts#L5-
// This will include from line 5 to end of file
```markdown-code provides two powerful workflows for keeping your documentation in sync with your code:
- Extract from existing docs - Convert unmanaged code blocks into manageable snippets
- Reference source files - Keep documentation in sync with your actual codebase
Perfect for projects with existing markdown documentation that contains code blocks.
Use this when:
- You have markdown files with unmanaged code blocks
- You want to extract code examples into separate files
- You need to start managing existing documentation
How it works:
- Run
npx markdown-code check(ormd-code check) to discover manageable code blocks - Run
npx markdown-code init --extract(ormd-code init --extract) to extract them into snippet files - Your markdown is updated to reference the new snippet files
- Future changes to snippets automatically sync to documentation
Perfect for keeping documentation in sync with your actual project source code.
Use this when:
- You want documentation to reference your actual source files
- You need line-range extraction from existing code
- You want living documentation that stays current with code changes
How it works:
- Add snippet directives to reference source files with line ranges
- Run
npx markdown-code sync(ormd-code sync) to populate markdown with current source content - When source files change,
npx markdown-code check(ormd-code check) detects drift - Run
npx markdown-code sync(ormd-code sync) to update documentation with latest changes
.mdx files (Docusaurus, Nextra, etc.) are fully supported. Point the glob at
them:
{
"markdownGlob": "docs/**/*.{md,mdx}"
}MDX files are parsed with remark-mdx + remark-frontmatter, so fences nested
inside JSX components are found, JSX indentation never produces phantom code
blocks, and {...} inside YAML frontmatter parses cleanly. Snippet directives
coexist with other fence meta (e.g. ```ts title="app.ts" snippet=app.ts).
Two guarantees worth knowing:
- Non-destructive extraction:
extractonly insertssnippet=<ref>into opening fence lines (offset-addressed, never regex-matched) — stripping the annotations reproduces your original file byte-for-byte. - Fail-safe parsing: a file that isn't valid MDX (e.g. HTML
<!-- -->comments, which MDX forbids) is reported and left untouched.
Note: framework-specific MDX extensions (like Docusaurus {#heading-id}
anchors) are not part of the MDX grammar and will be reported as parse errors;
those files are skipped safely.
- Automatic Sync: Replace fenced code blocks with contents from real files
- MDX Support: Parse
.mdxfiles, including fences nested in JSX - Extract Mode: Create snippet files from existing code blocks in markdown
- Line Range Support: Extract specific line ranges using
#Lx-Lysyntax - Check Mode: Verify documentation is in sync without making changes
- Multi-language: Support for any programming language
- Configurable: Flexible configuration via
.markdown-coderc.json
| Command | Description | Example |
|---|---|---|
npx markdown-code / md-code |
Update markdown with snippet content (default) | npx markdown-code or md-code |
npx markdown-code sync / md-code sync |
Same as above, explicit | npx markdown-code sync or md-code sync |
npx markdown-code check / md-code check |
Verify files are in sync (CI-friendly) | npx markdown-code check or md-code check |
npx markdown-code init / md-code init |
Create config and snippets directory | npx markdown-code init or md-code init |
npx markdown-code extract / md-code extract |
Extract code blocks to snippet files | npx markdown-code extract or md-code extract |
npx markdown-code init --extract / md-code init --extract |
Setup + extract in one step | npx markdown-code init --extract or md-code init --extract |
| Option | Description | Example |
|---|---|---|
--config |
Custom configuration file | npx markdown-code --config custom.json or md-code --config custom.json |
--snippet-root |
Override snippet directory | npx markdown-code --snippet-root ./src or md-code --snippet-root ./src |
--markdown-glob |
Override markdown file pattern | npx markdown-code --markdown-glob "docs/**/*.md" or md-code --markdown-glob "docs/**/*.md" |
--exclude-glob |
Override exclusion patterns | npx markdown-code --exclude-glob "node_modules/**,dist/**" or md-code --exclude-glob "node_modules/**,dist/**" |
--include-extensions |
Override file extensions | npx markdown-code --include-extensions .ts,.js,.py or md-code --include-extensions .ts,.js,.py |
Create a .markdown-coderc.json file in your project root:
{
"snippetRoot": "./snippets",
"markdownGlob": "**/*.md",
"excludeGlob": [
"node_modules/**",
".git/**",
"dist/**",
"build/**",
"coverage/**",
".next/**",
".nuxt/**",
"out/**",
"target/**",
"vendor/**"
],
"includeExtensions": [
".ts",
".js",
".py",
".java",
".cpp",
".c",
".go",
".rs",
".php",
".rb",
".swift",
".kt"
]
}| Option | Description | Default |
|---|---|---|
| snippetRoot | Base directory for resolving snippet paths | "." |
| markdownGlob | Glob pattern to find Markdown files | "**/*.md" |
| excludeGlob | Array of glob patterns to exclude from processing | Common build/dependency directories |
| includeExtensions | File extensions to consider for snippets and extraction | [".ts", ".js", ".tsx", ".jsx", ".py", ".rb", ".go", ".rs", ".java", ".cpp", ".c", ".cs", ".php", ".sh", ".bash", ".zsh", ".fish", ".json", ".yaml", ".yml", ".toml", ".xml", ".html", ".css", ".scss", ".less", ".sql", ".md", ".txt"] |
See CONTRIBUTING.md for development setup and contribution guidelines.
MIT License - see the LICENSE file for details.
