| weight | 10 |
|---|---|
| summary | CLI commands, flags, exit codes, and output format. |
mdsmith <command> [flags] [files...]
| Command | Description |
|---|---|
check |
Lint Markdown files for style issues. |
deps |
List a file's dependency-graph edges (includes, links, catalogs, builds). |
export |
Write a portable, directive-free copy of a Markdown file. |
extract |
Emit a schema-conformant Markdown file as a JSON/YAML/msgpack data tree. |
fix |
Auto-fix lint issues in Markdown files in place. |
help |
Show built-in documentation for rules, metrics, and concept pages. |
init |
Generate a default .mdsmith.yml config in the current directory. |
kinds |
Inspect declared file kinds and resolve effective rule config per file. |
list |
Selection-style commands that walk the workspace and emit matches. |
list backlinks |
List workspace links that point at a file. |
list query |
Select Markdown files by a CUE expression on front matter. |
lsp |
Run a Language Server Protocol server on stdio for editor integrations. |
merge-driver |
Git merge driver that resolves conflicts inside generated sections. |
metrics |
List and rank shared Markdown metrics (file length, token estimate, readability, …). |
pre-merge-commit |
Install / manage a pre-merge-commit hook that runs mdsmith fix after a merge. |
rename |
Rename a heading or link-reference label and rewrite every dependent edit. |
version |
Print the mdsmith build version and exit. |
The check, fix, and query commands accept file
paths, directories, and glob patterns as positional
arguments. check and query also accept - to read
from stdin.
With no file arguments:
checkandfixdiscover files usingfiles:from.mdsmith.yml(default:["**/*.md", "**/*.markdown"]).queryandmetrics rankdefault to the current directory (.) and walk it recursively.
| Flag | Short | Description |
|---|---|---|
--help |
-h |
Show help |
Use -- to separate flags from filenames starting with -.
Sets the byte-size cap for any input file read by commands
that support the flag (check, fix, query,
metrics rank). Behavior on oversize input:
check/fix: file is skipped and reported as a runtime error on stderr. Exit code follows the usual precedence —1when lint diagnostics are found (even if some files were skipped),2when only runtime errors occur.query: file is skipped; the per-file error prints on stderr only when--verboseis set. Exit code1if no files matched,0on a match.metrics rank: the whole run fails with exit code2on the first oversize file.
An invalid --max-input-size value always exits 2.
Accepts KB, MB, GB suffixes (binary: 1 MB =
1,048,576 bytes), bare integers (bytes), or 0 to disable
the limit. Default: 2MB. The CLI flag overrides the
max-input-size: key in .mdsmith.yml.
Rule settings come from a chain of layers. The chain
starts with the built-in defaults. Then every kinds:
block whose name matches the file applies. Front-matter
kinds: come first; kind-assignment: entries follow in
config order. Last, every overrides: block whose
glob: matches the file applies.
Each layer deep-merges onto the accumulator:
- Maps are merged key by key; nested maps recurse on shared keys.
- Scalars at a leaf are replaced by the later layer.
- Lists are replaced wholesale by default. Selected
list settings opt into append so a later kind or
override extends the inherited list rather than
replacing it. The placeholder vocabulary
(
placeholders:onfirst-line-heading,required-structure,paragraph-structure,paragraph-readability,heading-increment,no-emphasis-as-heading, andcross-file-reference-integrity) appends. - A bool-only layer (e.g.
line-length: false) togglesenabledfor that rule but preserves the inherited settings. A later layer that re-enables the rule sees the original settings still in place.
A layer that fully restates a rule's body still wins on
every key, so the previous block-replacement behavior is a
special case of deep-merge. Use mdsmith kinds why
to see the full chain on a single rule.
| Code | Meaning |
|---|---|
| 0 | No lint issues found |
| 1 | Lint issues found |
| 2 | Runtime or configuration error |
Per-command exits may vary; see the per-command pages.
Lint output goes to stderr. Format:
text (default):
README.md:10:81 MDS001 line too long (120 > 80)
8 | Previous line of context.
9 | Another context line.
10 | This very long line exceeds the configured 80 character limit and keeps going...
·····················································································^
11 | Next line of context.
12 | Another context line.
Each diagnostic prints a header line
(file:line:col rule message). When source context is
available, up to 5 surrounding lines appear with a dot
path (····^) pointing to the exact column.
json:
[
{
"file": "README.md",
"line": 10,
"column": 81,
"rule": "MDS001",
"name": "line-length",
"severity": "error",
"message": "line too long (120 > 80)",
"source_lines": ["Previous line.", "Another context.", "The long line...", "Next.", "Another."],
"source_start_line": 8
}
]The source_lines and source_start_line fields are
omitted when source context is unavailable (e.g., empty
diagnostics). With --explain, each diag also gains an
explanation field — see mdsmith check.
- Configuration globs — pattern syntax across config, directives, and CLI args
- Conventions — built-in rule presets