harehare/mq: a jq-style query language for Markdown files
A jq-like Markdown query language for command-line processing
At a glance
- What is it?
- mq turns Markdown into something you can slice and filter from the shell, using a syntax modelled on jq. It is aimed at documentation pipelines and LLM prompt tooling, and it is still labelled as under active development.
- Who is it for?
- Adopt mq if you already think in jq and your inputs are Markdown files or LLM prompt bodies that need slicing in a shell pipeline. Do not adopt it if you need a stable, frozen query language across a long-lived build, or if your documents are prose you want to edit rather than data you want to extract.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap mq is trying to fill between jq and Markdown
jq assumes structured input. Give it JSON and you can address fields by name, filter arrays, and reshape objects with predictable results. Markdown has no such addressability. A heading is a line that starts with a hash, a list is a run of lines with a common prefix, and a code fence is a pair of backtick runs. Every tool that wants to work on Markdown has to re-derive that structure, and most shell tools do it with grep and sed patterns that break the moment a document changes shape.
mq's premise is that Markdown is structured enough to deserve its own query language, and that the jq syntax is a reasonable model to copy. The README states the goal directly: process Markdown using a syntax similar to jq, so you can slice, filter, map, and transform structured data. The stated audience is narrower than "anyone who writes Markdown". The README lists LLM workflows first, then LLM input generation, documentation management, content analysis, and batch processing. The reasoning given is that Markdown is the primary input format for most language models, so tooling that generates and reshapes Markdown has a direct use in prompt construction.
That framing is honest about the project's centre of gravity. If your problem is extracting a section from a README, or normalising a directory of docs before feeding it somewhere else, mq is aimed at you. If your problem is writing prose, it is not.
What the interpreter does with a Markdown document
The repository is written in Rust and the README describes the tool as an interpreter with a REPL, a language server, and an experimental debugger. The published crate on crates.io is named mq-markdown, while the installable binary crate is mq-run. That split is visible in the installation commands: cargo install mq-run installs the CLI, and the badge for the library points at mq-markdown.
The README does not lay out the grammar or the full selector list. What it does say is that the language provides "built-in functions and selectors" for filtering and transforming content, and that custom functions can be added. The demo is a GIF, so the exact surface syntax is not verifiable from the README text alone. Anyone evaluating mq should read the book at mqlang.org/book or open the playground rather than infer the syntax from this summary.
What can be said from the repository layout is that the project ships more than one binary. mq-dbg is described as an experimental debugger for inspecting and stepping through queries interactively, and it is installed with a feature flag: cargo install --git https://github.com/harehare/mq.git mq-run --bin mq-dbg --features="debugger". The presence of a step debugger suggests the authors expect queries to grow past one-liners, which is a reasonable signal for a language that borrows jq's pipeline model.
Installation paths and the subcommand extension mechanism
The quickest route is the install script: curl -sSL https://mqlang.org/install.sh | bash. According to the README, it downloads the latest binary for your platform, places it in ~/.local/bin/, and edits your shell profile to add that directory to PATH. That last step is worth noting before you run it, because it modifies a file outside the project directory.
Package managers are covered for the usual targets. Homebrew on macOS and Linux takes brew install mq. Arch users have yay -S mq-bin. Cargo users get cargo install mq-run. There is a container image at ghcr.io/harehare/mq:latest runnable with docker run --rm. The README also documents cargo binstall mq-run@0.8.5 and a tagged git install, cargo install --git https://github.com/harehare/mq.git mq-run --tag v0.8.5, plus pre-built binaries on the releases page for macOS, Linux, and Windows.
One mechanism deserves attention because it shapes how you would fit mq into an existing toolchain. The README states that mq supports external subcommands: place an executable whose name starts with mq- in ~/.local/bin/, and mq will pick it up as a subcommand. That is the same convention git uses, and it means local extensions do not require forking the interpreter. The trade-off is implicit. Anything in that directory with the right prefix becomes part of your mq surface, so name collisions and PATH hygiene become your problem rather than the project's.
Editor integrations and what the language server implies
mq ships a Visual Studio Code extension listed on both the Visual Studio Marketplace and Open VSX, a Chrome extension, and editor support documented for Neovim, Zed, and JetBrains IDEs. The README also advertises LSP support, described as being for custom function development.
That last phrase is the interesting part. An LSP for a query language normally means completion and diagnostics over the query itself. The README scopes it to custom function development, which suggests the intended workflow is: write a function once, register it, and get editor assistance while doing so. Whether the language server also assists with ordinary query authoring is not stated in the material available here, and it should not be assumed.
The Chrome extension is a separate surface entirely. The README gives no description of what it does beyond the name "mq for Markdown", so treat it as unverified until you check the store listing. The same caution applies to the Neovim, Zed, and JetBrains entries: the README links to per-editor README files rather than describing the integration, which means the quality and completeness of each varies by editor and is maintained separately.
The development-status warning is the most important line in the README
The README carries a callout: "This project is under active development." That is not boilerplate. The release history shows three releases in roughly three weeks: v0.8.3 on 2026-08-18, v0.8.4 on 2026-08-26, and v0.8.5 on 2026-09-08. A version series still in the 0.8 range with that cadence means the surface syntax and the selector set are both plausibly still moving.
For a tool you invoke interactively, that is fine. For a tool embedded in a CI job that runs on every pull request, it is a real cost. A query written against v0.8.3 may need review at v0.9.0, and the project has not published a stability commitment in the material available here. If you adopt mq, pin the version explicitly. The README already shows how: cargo install mq-run@0.8.5, or the tagged git install with --tag v0.8.5. Using the install script or the :latest container tag gives you whatever shipped most recently, which is the opposite of what a reproducible pipeline needs.
There is a second limitation worth stating plainly. mq is a query and transformation tool for Markdown, not a Markdown formatter or a prose editor. If your goal is to reflow paragraphs, fix heading levels across a manual, or enforce a style guide, a formatter is the right category of tool. mq's README frames it around slicing, filtering, mapping, and transforming, which is extraction and reshaping, not editorial cleanup. Reaching for mq to do formatting work would mean writing queries that emulate a formatter, and you would own that emulation.
How mq differs from pandoc and from a plain awk pipeline
The obvious comparison for anyone who already processes Markdown on the command line is pandoc. The two tools sit at different points in the same pipeline. Pandoc converts between formats: Markdown in, HTML or LaTeX or docx out, with a filter mechanism for programmatic edits. Its unit of work is the whole document and its output is another document. mq's unit of work is a selection. You point a query at a document and get back the matching portion, in the shell, without a conversion step in between.
That difference matters in practice. If you want every section under a given heading as HTML, pandoc is the direct route. If you want to know which of forty README files contain a deprecated flag, mq's filtering model is closer to the shape of the question, and pandoc would be an awkward detour through a full parse and render.
The other comparison is the one most engineers already have in their shell: awk and sed. Those tools operate on lines and regular expressions with no notion of a heading or a list. They are fast and universally available, and for a single well-known pattern they are often the correct answer. Their failure mode is structural drift. A document that changes indentation, or switches from setext to ATX headings, or gains a code fence containing text that looks like a heading, will break a line-oriented pattern. mq's value proposition is that it parses the document first, so queries address Markdown constructs rather than line shapes. Whether that holds for every construct you care about is something to check against your own corpus, since the README does not enumerate the supported selector set.
Licence, maintenance, and what to check before you commit
mq is MIT licensed. That is a permissive licence, and it means you can embed the mq-markdown crate in a larger application, including a commercial one, subject to the usual requirement to preserve the copyright notice and licence text. This is a description of the licence identifier, not legal advice. If you are distributing mq inside a product, have your own counsel read the LICENSE file rather than relying on the identifier alone.
The maintenance picture from the supplied material is a single active repository with frequent patch releases and a documented install path through crates.io, Homebrew, Arch, Docker, and pre-built binaries. That is a reasonable distribution footprint for a project at this stage. What is not in the material is any statement about long-term support, a deprecation policy, or a compatibility guarantee between minor versions. The 0.8.x series and the "under active development" callout both point the same way: assume breakage is possible on upgrade.
Before adopting mq in anything automated, do three concrete things. Run the queries you plan to depend on in the REPL against a representative sample of your own Markdown, including files with nested lists, code fences, and HTML blocks, since those are the constructs most likely to expose gaps. Check the crates.io page for mq-run to confirm the version you intend to pin is published and that the release notes for it mention no breaking changes. And if you plan to use external subcommands, decide now where those executables live and how they are versioned alongside the pinned interpreter, because the ~/.local/bin/mq-* convention couples your extensions to a directory rather than to a package.
Editorial conclusion
Adopt mq if you already think in jq and your inputs are Markdown files or LLM prompt bodies that need slicing in a shell pipeline. Do not adopt it if you need a stable, frozen query language across a long-lived build, or if your documents are prose you want to edit rather than data you want to extract. Before committing, verify the current selector set against your own files using the REPL, check the release cadence on crates.io for mq-run, and confirm that the version you pin is the one whose syntax your scripts were written against.
Community notes