Skip to content

Linting & formatting

This page documents the lint configuration choices that are non-obvious or whose rationale would otherwise be lost.

treefmt formatters

Wired in treefmt.nix. Run via nix fmt or just fmt. Pre-commit hook treefmt runs the same set.

Formatter Scope
nixfmt *.nix
prettier JSON and YAML only
mdformat *.md (with gfm + frontmatter + mkdocs + footnote plugins)
shfmt shell scripts, 2-space indent
taplo TOML

Prettier rewrites single-quoted YAML scalars to double-quoted. Use double quotes from the start in workflow files.

Pre-commit hooks

Configured via cachix/git-hooks.nix (input pinned in flake.nix). The .pre-commit-config.yaml symlink is generated by nix develop into the Nix store and is .gitignored. Edits go in flake.nix's pre-commit.settings.hooks block, not the symlink target.

Hooks: actionlint, check-jsonschema, commitizen (commit-msg), deadnix, editorconfig-checker, markdownlint, nixfmt-rfc-style, statix, typos, yamllint, shellcheck (skipping justfile), treefmt, zizmor (--min-severity=low), readme-flake-show-fresh, uses-sha-pinned.

markdownlint rule disables

.markdownlint.json disables eight rules. Rationale per rule:

Rule Name Reason
MD007 Unordered list indentation mdformat's nested-list output uses 4-space indent, conflicting with the default 2-space expectation
MD013 Line length Docs site is MkDocs-Material with prose paragraphs; hard-wrapping at 80/100 chars fights table cells and admonitions
MD024 Multiple headings same content Dashboard and release-notes pages have repeated section headers per release / per artifact
MD032 Lists surrounded by blank lines Common false positives around mkdocs-material admonition trees
MD033 Inline HTML MkDocs-Material relies on <details>, <span> for admonitions and badges
MD038 Spaces inside code-span markers False positives on Mermaid edge-syntax (-->, ---)
MD041 First line top-level heading Some pages (release notes, dashboard) open with a macros / yaml block before the H1
MD060 Hard tabs Source files include intentional tab characters (justfile rules); markdownlint should not police that

Adding or removing a disable: update .markdownlint.json and this table in the same PR so the rationale stays discoverable.

lychee.toml accepts 200, 204, 206, 302. 429 (rate-limited) is not accepted — relying on lychee's built-in retry is preferable to silently letting bot-blocked links pass. If a specific upstream consistently rate-limits anonymous GETs and is known-good, add it to the exclude regex list with a comment rather than expanding accept.

include_verbatim = false skips fenced-code-block content so command examples are not crawled.

Typos

_typos.toml excludes tests/fixtures/** because fixtures contain intentionally malformed content (bad versions, malformed renovate configs); future fixtures may include realistic prose that would otherwise trigger typo flags.

Zizmor

Workflow-security linter; --min-severity=low to catch everything. Suppressions live in zizmor.yml with documented rationale per suppressed rule + workflow. Do not raise --min-severity above low without a security-review entry in .claude/CLAUDE.md.

Treefmt YAML quote gotcha

Prettier rewrites single-quoted YAML scalars to double-quoted. Run nix fmt before push, or use double quotes from the start.

README flake-show auto-block

scripts/refresh-flake-show.sh regenerates the auto-block. Pre-commit hook readme-flake-show-fresh has NIX_BUILD_TOP sandbox guard.