{
  "markdown": "<p align=\"center\">\n  <img src=\"assets/kml-icon.png\" width=\"128\" alt=\"katana-markdown-linter icon\">\n</p>\n\n<h1 align=\"center\">katana-markdown-linter</h1>\n\n<p align=\"center\">\n  A markdownlint-compatible Rust engine, <code>kml</code> CLI, formatter,\n  safe fixer, editor server, and agent-ready MCP server.\n</p>\n\n<p align=\"center\">\n  <strong><a href=\"#installation\">Installation</a></strong> |\n  <strong><a href=\"#cli-usage\">CLI Usage</a></strong> |\n  <strong><a href=\"#library-api\">Library API</a></strong> |\n  <strong><a href=\"docs/editor-integration.md\">Editor Integration</a></strong> |\n  <strong><a href=\"docs/mcp-server.md\">MCP Server</a></strong>\n</p>\n\n<p align=\"center\">\n  <a href=\"LICENSE\"><img src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License: MIT\"></a>\n  <a href=\"https://github.com/HiroyukiFuruno/katana-markdown-linter/actions/workflows/test-and-build.yml\"><img src=\"https://github.com/HiroyukiFuruno/katana-markdown-linter/actions/workflows/test-and-build.yml/badge.svg\" alt=\"CI\"></a>\n  <a href=\"https://github.com/HiroyukiFuruno/katana-markdown-linter/releases/latest\"><img src=\"https://img.shields.io/github/v/release/HiroyukiFuruno/katana-markdown-linter\" alt=\"Latest Release\"></a>\n  <a href=\"https://crates.io/crates/katana-markdown-linter\"><img src=\"https://img.shields.io/crates/v/katana-markdown-linter.svg\" alt=\"crates.io\"></a>\n  <a href=\"https://www.npmjs.com/package/katana-markdown-linter\"><img src=\"https://img.shields.io/npm/v/katana-markdown-linter.svg\" alt=\"npm\"></a>\n  <a href=\"https://pypi.org/project/katana-markdown-linter/\"><img src=\"https://img.shields.io/pypi/v/katana-markdown-linter.svg\" alt=\"PyPI\"></a>\n</p>\n\n---\n\n## What is kml\n\n`katana-markdown-linter` is a fast Markdown lint engine for technical writing,\nspecification documents, and AI-agent-assisted documentation workflows.\n\nThe project shares the KatanA visual identity, but keeps a standalone boundary:\nthe crate, CLI, wrappers, editor server, and MCP server do not depend on KatanA\nDesktop.\n\n## Features\n\n- **markdownlint-compatible checks** for the active upstream rule catalog\n- **Safe fixes** for low-risk rule violations and explicit opt-in unsafe fixes\n- **Formatter mode** for layout normalization without changing author intent\n- **Embeddable Rust API** for applications that need linting or fixing in-process\n- **`kml` CLI** with JSON output, stdin support, ignore handling, and statistics\n- **Editor integration** through a stdio Language Server Protocol server\n- **MCP server** for agents and tools that need structured lint access\n- **Multi-channel distribution** through Cargo, GitHub Releases, npm, PyPI, and Homebrew\n\n## Library API\n\nUse the crate directly when embedding linting into another Rust application.\n\n- `lint(content, options)`\n- `fix(content, options)`\n- `available_rules()`\n- `localized_available_rules(language_code)`\n- `implemented_rules()`\n- `missing_rules()`\n- `rule_catalog()`\n- `localized_rule_catalog(language_code)`\n- `resolve_locale_code(language_code)`\n- `resolve_locale_code_or(language_code, fallback)`\n- `localized_rule_description(rule_id, fallback_description, language_code)`\n- `supported_locales()`\n- `upstream::get_rule_documentation(rule_id, locale)`\n- `MarkdownLintConfig`\n- `MarkdownLintConfig::schema()`\n- `MarkdownLintConfig::to_lint_options()`\n\n`available_rules()` returns canonical English metadata. For user-facing rule\ncatalogs, call `localized_available_rules(language_code)`,\n`localized_rule_catalog(language_code)`, `RuleMeta::localized_description(...)`,\nor `localized_rule_description(...)` so applications can pass UI language codes\nwithout reimplementing kml's fallback policy.\n\n`Locale` is `#[non_exhaustive]` from v0.6.0. Consumers that match on `Locale`\nshould include a wildcard arm and prefer `resolve_locale_code(...)` or\n`resolve_locale_code_or(...)` for UI language strings. Rule descriptions and\nrule Markdown documentation are localized for `en`, `ja`, `zh-CN`, `zh-TW`,\n`ko`, `pt`, `fr`, `de`, `es`, and `it`.\n\nMinimal embedding examples are available under [`examples/`](examples/):\n\n- `embedding.rs`: string checks, file tree checks, string fixes, config loading and config-to-options conversion\n\n## Installation\n\n### Cargo\n\n~~~bash\ncargo install katana-markdown-linter\n~~~\n\nThe binary target is `kml`. Use Cargo when you want the Rust crate and CLI from\nthe same channel.\n\n### npm\n\nThe npm package is a thin launcher that downloads the matching GitHub Release\narchive for `kml`, `kml-mcp`, or `kml-mcp-remote` on first use:\n\n~~~bash\nnpm install -g katana-markdown-linter\nkml version\n~~~\n\nUse `npx` for one-off runs:\n\n~~~bash\nnpx --yes katana-markdown-linter@0.19.4 check README.md\nnpx --yes katana-markdown-linter@0.19.4 kml-mcp --workspace-root /absolute/path/to/workspace\nbunx --package katana-markdown-linter@0.19.4 kml-mcp --workspace-root /absolute/path/to/workspace\n~~~\n\n### PyPI\n\nThe PyPI package is a thin Python launcher that downloads the matching GitHub\nRelease archive for `kml`, `kml-mcp`, or `kml-mcp-remote` on first use:\n\n~~~bash\npipx install katana-markdown-linter\nkml version\n~~~\n\nIf you do not use `pipx`, install with your normal Python environment manager.\n\nUse `uvx` for one-off runs without installing the launcher into your active\nenvironment:\n\n~~~bash\nuvx --from katana-markdown-linter==0.19.4 kml check README.md\nuvx --from katana-markdown-linter==0.19.4 kml-mcp --workspace-root /absolute/path/to/workspace\n~~~\n\n### GitHub Releases\n\nStandalone `kml` archives are attached to GitHub Releases. Choose the archive\nthat matches your Rust target triple:\n\n~~~bash\ncurl -LO https://github.com/HiroyukiFuruno/katana-markdown-linter/releases/download/v0.19.4/kml-v0.19.4-aarch64-apple-darwin.tar.gz\ncurl -LO https://github.com/HiroyukiFuruno/katana-markdown-linter/releases/download/v0.19.4/kml-v0.19.4-aarch64-apple-darwin.tar.gz.sha256\nshasum -a 256 -c kml-v0.19.4-aarch64-apple-darwin.tar.gz.sha256\ntar -xzf kml-v0.19.4-aarch64-apple-darwin.tar.gz\n~~~\n\n### Homebrew\n\nHomebrew formula publication is part of the release flow. Install with:\n\n~~~bash\nbrew install HiroyukiFuruno/katana/kml\n~~~\n\n### VS Code\n\nInstall the **KatanA Markdown Linter** extension from the VS Code Marketplace\nor sideload the local package. The extension acts as a thin wrapper around\nthe `kml lsp` server and verifies version compatibility on startup.\n\n~~~bash\n# Sideload for MVP testing\ncd editors/vscode\nnpm install\nnpm run compile\ncode --extensionDevelopmentPath=$PWD\n~~~\n\n### Zed\n\nInstall the **KatanA Markdown Linter** extension from the Zed extension registry\nor sideload from the repository. The extension registers `kml lsp` as a\nMarkdown language server and supports custom binary paths.\n\n~~~bash\n# Sideload for MVP testing\n# Use the \"zed: install dev extension\" action in Zed\n# and select the 'editors/zed' directory.\n~~~\n\n## GitHub Actions\n\nUse the repository action to run `kml` in CI without writing install steps:\n\n~~~yaml\n- uses: actions/checkout@v5\n- uses: HiroyukiFuruno/katana-markdown-linter@v0.18.0\n  with: { version: \"0.18.0\", command: check, paths: \"README.md\\ndocs\", config: .markdownlint.json }\n~~~\n\nPin the action tag and `version` together for reproducible runs. The action\ninstalls `kml` from crates.io by default. Repository-local smoke tests can set\n`install-source: path` and `path: .`.\n\n`extra-args` accepts one argument per line, so flags that take values must use\nseparate lines.\n\n## CLI Usage\n\n~~~bash\nkml check\nkml check --locale en\nkml check -l ja\nkml --locale ja help\nkml fix\nkml fmt\nkml check --fix\nkml fix --unsafe --yes README.md\nkml check --fix --unsafe --yes README.md\nkml check README.md\nkml check --file README.md\nkml check --output json \"docs/**/*.md\"\nkml check --format json \"docs/**/*.md\"\nkml check --ignore-config-errors README.md\nkml check --stdin\nkml fix --stdin\nkml check --include \"**/*.md\" --exclude \"target/**\"\nkml check --include-reserved node_modules\nkml check --no-ignore --force-exclude --exclude \"vendor/**\" vendor/README.md\nkml check --statistics --quiet\nkml fix --diff README.md\nkml rule\nkml rule --locale ja\nkml rule --locale fr\nkml rule MD013\nkml rule MD013 --locale ja --output json\nkml config file\nkml config get --output json\nkml config schema\nkml --help\nkml -h\nkml help\nkml check --help\nkml check -h\nkml version\nkml --version\nkml -v\nkml fix --config .markdownlint.json README.md\nkml init-config\n~~~\n\nWhen no files are provided, `kml check`, `kml fix`, and `kml fmt` recursively process Markdown files under the current directory. Use `--file` to make single-file intent explicit.\n\n`check` reports diagnostics and exits with `1` when lint violations are found.\n`fix` and `check --fix` apply safe lint-driven fixes and exit with `1` if\nviolations remain after rewriting. `fmt` is a layout formatter for indentation\nand newline normalization; it exits with `0` after successful formatting even\nwhen unrelated lint diagnostics would still be reported by `check`. Filesystem\nor configuration errors exit with `2`.\n\n`fmt` currently normalizes CRLF/CR line endings to LF, final newlines, repeated\nblank lines, blank lines around headings/fences/lists/tables, and safe list\nindentation/list-marker spacing. It does not reflow paragraphs, change heading\nor emphasis style, change URL/table style, remove trailing spaces, or apply\nunsafe fixes by default.\n\nUnsafe fixes require explicit opt-in for `fix` and `check --fix`.\nInteractive use prompts with `[Y/n]`; non-interactive use must pass\n`--unsafe --yes`.\n\n`--output json` is the preferred JSON output flag. `--format json` remains a compatibility alias.\nFix-mode JSON includes per-file `fix_details` so applied rules can be compared\nwith pre-fix diagnostics and rewritten file diffs.\n\n`--stdin` reads Markdown from standard input. `check --stdin` reports diagnostics against `<stdin>`; `fix --stdin` writes fixed Markdown to stdout; `fmt --stdin` writes formatted Markdown only to stdout.\n\nDirectory scans respect gitignore files by default. Use `--no-ignore` to include ignored paths everywhere, or `--include-ignored` to include ignored paths only under explicit directory inputs such as `.agents`. Reserved directories such as `.git`, `node_modules`, `target`, `dist`, `build`, and `coverage` are skipped by default even without gitignore entries; use `--include-reserved` only when you intentionally want to scan them. Project-specific generated or agent directories should be covered by gitignore or `--exclude`. `--exclude` filters discovered files; explicit files are kept unless `--force-exclude` is also set.\n\nInvoking `kml` without a command prints global help. `kml help`, `kml --help`,\n`kml -h`, and `kml <command> --help` print help without scanning files.\n\n`--locale <locale>` and `-l <locale>` select user-facing CLI message and help\ntext locale.\nSupported values resolve to `en`, `ja`, `zh-CN`, `zh-TW`, `ko`, `pt`, `fr`,\n`de`, `es`, and `it`, including common region forms such as `fr-FR`,\n`pt-BR`, or `ko-KR`. When omitted, `kml` reads OS locale environment variables\nand falls back to English if the locale is unavailable or unsupported. Explicit\nunsupported locales fail with a CLI error. `--local` is accepted as a\nbackward-compatible alias for v0.4.0 users.\n\n`kml rule` and `kml rule <id>` also honor `--locale`. Text output uses localized\nrule descriptions, and JSON output includes both `description` (localized) and\n`english_description` (canonical English).\n\n## Rule Map\n\nkml ships lint checks for the active markdownlint rule catalog. The rule IDs\nbelow match the public catalog returned by `available_rules()` and\n`kml rule --output json`; state columns describe fixture-backed implementation\nstatus. Run `kml rule MD013` to inspect one rule with its upstream documentation\nURL.\n\nThe short version:\n\n| Capability | Status |\n| --- | --- |\n| Check coverage | `Implemented` for all 53 active rules |\n| Safe fix coverage | Safe fix available for 38 rules; diagnostic-only for 15 rules |\n| Unsafe fix coverage | Explicit opt-in unsafe subset for 1 rule; remaining rules are not applicable or need manual intent |\n| Deleted upstream IDs | 7 historical IDs shown as `Deleted` with `-` fix states |\n\nSafe fixes are intentionally conservative. `Implemented subset` means kml\nrewrites fixture-locked, low-risk violation forms for that rule. `Diagnostic\nonly` means checks are implemented, but safe fixes are not provided.\n`Manual intent required` means an automatic rewrite would choose author intent.\n`Not applicable` means no separate unsafe candidate is currently identified\nbeyond the safe-fix policy. `Deleted` rows are historical markdownlint IDs that\nare not part of the active upstream rule catalog.\n\n<details>\n<summary>Full fixture-backed rule matrix</summary>\n\n| Rule | Check | Fix (safe) | Fix (unsafe) |\n| --- | --- | --- | --- |\n| `MD001` | Implemented | Diagnostic only | Manual intent required |\n| `MD002` | Deleted | - | - |\n| `MD003` | Implemented | Implemented subset | Not applicable |\n| `MD004` | Implemented | Implemented subset | Not applicable |\n| `MD005` | Implemented | Implemented subset | Not applicable |\n| `MD006` | Deleted | - | - |\n| `MD007` | Implemented | Implemented subset | Not applicable |\n| `MD008` | Deleted | - | - |\n| `MD009` | Implemented | Implemented subset | Not applicable |\n| `MD010` | Implemented | Implemented subset | Not applicable |\n| `MD011` | Implemented | Implemented subset | Not applicable |\n| `MD012` | Implemented | Implemented subset | Not applicable |\n| `MD013` | Implemented | Diagnostic only | Manual intent required |\n| `MD014` | Implemented | Implemented subset | Not applicable |\n| `MD015` | Deleted | - | - |\n| `MD016` | Deleted | - | - |\n| `MD017` | Deleted | - | - |\n| `MD018` | Implemented | Implemented subset | Not applicable |\n| `MD019` | Implemented | Implemented subset | Not applicable |\n| `MD020` | Implemented | Implemented subset | Not applicable |\n| `MD021` | Implemented | Implemented subset | Not applicable |\n| `MD022` | Implemented | Implemented subset | Not applicable |\n| `MD023` | Implemented | Implemented subset | Not applicable |\n| `MD024` | Implemented | Diagnostic only | Manual intent required |\n| `MD025` | Implemented | Implemented subset | Not applicable |\n| `MD026` | Implemented | Implemented subset | Not applicable |\n| `MD027` | Implemented | Implemented subset | Not applicable |\n| `MD028` | Implemented | Diagnostic only | Manual intent required |\n| `MD029` | Implemented | Implemented subset | Not applicable |\n| `MD030` | Implemented | Implemented subset | Not applicable |\n| `MD031` | Implemented | Implemented subset | Not applicable |\n| `MD032` | Implemented | Implemented subset | Not applicable |\n| `MD033` | Implemented | Diagnostic only | Manual intent required |\n| `MD034` | Implemented | Implemented subset | Not applicable |\n| `MD035` | Implemented | Implemented subset | Not applicable |\n| `MD036` | Implemented | Diagnostic only | Implemented subset |\n| `MD037` | Implemented | Implemented subset | Not applicable |\n| `MD038` | Implemented | Implemented subset | Not applicable |\n| `MD039` | Implemented | Implemented subset | Not applicable |\n| `MD040` | Implemented | Implemented subset | Not applicable |\n| `MD041` | Implemented | Diagnostic only | Manual intent required |\n| `MD042` | Implemented | Diagnostic only | Manual intent required |\n| `MD043` | Implemented | Diagnostic only | Manual intent required |\n| `MD044` | Implemented | Implemented subset | Not applicable |\n| `MD045` | Implemented | Diagnostic only | Manual intent required |\n| `MD046` | Implemented | Implemented subset | Not applicable |\n| `MD047` | Implemented | Implemented subset | Not applicable |\n| `MD048` | Implemented | Implemented subset | Not applicable |\n| `MD049` | Implemented | Implemented subset | Not applicable |\n| `MD050` | Implemented | Implemented subset | Not applicable |\n| `MD051` | Implemented | Implemented subset | Not applicable |\n| `MD052` | Implemented | Diagnostic only | Manual intent required |\n| `MD053` | Implemented | Implemented subset | Not applicable |\n| `MD054` | Implemented | Implemented subset | Not applicable |\n| `MD055` | Implemented | Implemented subset | Not applicable |\n| `MD056` | Implemented | Implemented (pads short rows; overflow rows remain diagnostic-only) | Not applicable |\n| `MD057` | Deleted | - | - |\n| `MD058` | Implemented | Implemented subset | Not applicable |\n| `MD059` | Implemented | Diagnostic only | Manual intent required |\n| `MD060` | Implemented | Implemented subset | Not applicable |\n\n</details>\n\n## Configuration\n\nThe crate reads and writes markdownlint-compatible JSON and JSONC configuration files:\n\n- `.markdownlint.json`\n- `.markdownlint.jsonc`\n\nUse `kml init-config` to create a default `.markdownlint.json`.\n\nUse `kml config schema` to print the JSON Schema used by editor integration and\nconfiguration validation. The stable schema ID is\n`https://schemas.katana.tools/kml/markdownlint.schema.json`.\n\nConfiguration errors stop `check`, `fix`, and `fmt` before file diagnostics are\nreported. Fix the config first, or pass `--ignore-config-errors` when you\nexplicitly want invalid config entries ignored for that run. Official\nmarkdownlint aliases such as `first-line-h1`, `first-line-heading`,\n`no-duplicate-heading`, and `no-inline-html` are accepted.\n\n## Editor Integration\n\n`kml lsp` starts a stdio Language Server Protocol server for Markdown\ndiagnostics, formatting, range formatting, and safe quick fixes. VS Code, Zed,\nand Neovim setup examples are documented in\n[`docs/editor-integration.md`](docs/editor-integration.md).\n\n## Quality Gates\n\nUse `just check` for the default local gate. It runs format, Clippy, AST lint, and tests.\n\nUse `just dogfood` to run `kml` against this repository's Markdown documentation without modifying files. Use `just dogfood-fix` only when you intend to apply safe Markdown fixes. Archived OpenSpec documents are excluded from the default dogfood targets; run `just dogfood-archive` to check them explicitly.\n\nUse `just examples` to compile the public Rust embedding examples.\n\nQuality gate details, CI required checks, coverage modes, and release readiness are documented in [`docs/quality-gates.md`](docs/quality-gates.md).\n\nDistribution channel status and deferral notes are documented in\n[`docs/distribution.md`](docs/distribution.md).\n\n## MCP Server\n\n`kml-mcp` is an optional MCP server for agents and editors that want structured\nlibrary access over stdio while keeping the core crate independent from MCP\ndependencies.\n\nBuild or install it with the `mcp` feature:\n\n~~~bash\ncargo build --bin kml-mcp --features mcp --locked\ncargo install katana-markdown-linter --locked --features mcp --bin kml-mcp\n~~~\n\nAfter `v0.19.3`, the npm and PyPI wrappers can launch the same stdio server\nwithout a Rust toolchain:\n\n~~~bash\nnpx --yes katana-markdown-linter@0.19.4 kml-mcp --workspace-root /absolute/path/to/workspace\nbunx --package katana-markdown-linter@0.19.4 kml-mcp --workspace-root /absolute/path/to/workspace\nuvx --from katana-markdown-linter==0.19.4 kml-mcp --workspace-root /absolute/path/to/workspace\n~~~\n\nThe server exposes text, config, rule metadata, and workspace-safe file tools:\n\n- `check_text`\n- `fix_text`\n- `config_validate`\n- `rule_list`\n- `rule_get`\n- `check_file`\n- `check_directory`\n- `fix_file_preview`\n- `fix_file_apply`\n\nWorkspace paths must stay under the configured `--workspace-root`. File writes\nare limited to `fix_file_apply` and require `apply: true`; no directory apply\ntool is exposed.\n\nRun `just mcp-stdio-smoke` to exercise the installed MCP server through\nJSON-RPC stdio calls.\n\n`kml-mcp-remote` is a separate self-hosted Streamable HTTP server for API-hosted\nLLM clients that cannot launch a stdio subprocess. It exposes text-only tools\nby default and does not expose workspace file tools:\n\n~~~bash\ncargo build --bin kml-mcp-remote --features mcp-remote --locked\nKML_MCP_REMOTE_TOKEN=change-me target/debug/kml-mcp-remote\n~~~\n\nWrapper entrypoints are available for self-hosted remote MCP as well:\n\n~~~bash\nKML_MCP_REMOTE_TOKEN=change-me \\\n  npx --yes --package katana-markdown-linter@0.19.4 kml-mcp-remote\nKML_MCP_REMOTE_TOKEN=change-me \\\n  uvx --from katana-markdown-linter==0.19.4 kml-mcp-remote\n~~~\n\nRun `just mcp-remote-smoke` to verify bearer authentication, text-only tool\ncapabilities, text diagnostics, and the request body limit.\n\n`v0.14.0` introduced a Linux MCPB bundle from GitHub Releases and MCP\nRegistry metadata for the local stdio server. Build the bundle and exercise the\nbundled `kml-mcp` binary before publication:\n\n~~~bash\njust VERSION=v0.19.4 mcpb-smoke\n~~~\n\nSee [MCP server documentation](docs/mcp-server.md), the\n[remote MCP deployment guide](docs/remote-mcp-transport.md), the\n[MCP distribution plan](docs/mcp-distribution-plan.md), and the earlier\n[MCP integration evaluation](docs/mcp-integration-evaluation.md).\n\n## Release Policy\n\n- The library API is the primary contract.\n- The CLI is a thin wrapper over the library.\n- `Cargo.toml` package version is the release version source of truth.\n- Run `just VERSION=vX.Y.Z release-check` before publication.\n- Run `just VERSION=vX.Y.Z release-github` to create or update only the GitHub Release.\n- Run `just VERSION=vX.Y.Z release` only when registry publication is intended.\n- Run `just VERSION=vX.Y.Z release-verify` after publication to compare the tag target, GitHub Release target, crates.io, npm, PyPI, wrapper launch, Homebrew formula, and binary release assets.\n- GitHub Releases require a signed annotated `vX.Y.Z` tag that GitHub reports as `Verified`.\n- `just release` stops before dispatch when the requested version already exists on crates.io.\n- crates.io publication requires the `CARGO_REGISTRY_TOKEN` GitHub secret.\n",
  "bytes": 21666,
  "sha": "095bfe730821f2edeb42f9ee4b17aff6bd9e05d771a2f57d73e14d6c0030200c",
  "repo_slug": "hiroyukifuruno/katana-markdown-linter",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_hiroyukifuruno_kml_9ec46794/readme"
}