PromptHub
Developer Tools Command Line Utilities

Stop Wrestling with Markdown! Use mq Instead

B

Bright Coding

Author

13 min read
12 views
Stop Wrestling with Markdown! Use mq Instead

Stop Wrestling with Markdown! Use mq Instead

What if I told you that developers waste hours every week copy-pasting between Markdown files, manually extracting code blocks, and writing brittle regex patterns that break on the first nested list? Here's the painful truth: Markdown is the universal language of documentation, LLM prompts, and technical content—yet we've had zero powerful tools to actually query it programmatically.

Until now.

Meet mq—the secret weapon that's making top developers abandon their hacky Python scripts and awk one-liners. Written in blazing-fast Rust, mq brings the legendary jq syntax to Markdown processing. Imagine extracting every Rust code block from 100 README files in under a second. Imagine filtering documentation sections by heading level with a single elegant query. Imagine transforming your entire docs pipeline from a fragile mess into a bulletproof, composable workflow.

This isn't a distant dream. This is mq—and it's about to change how you think about Markdown forever. Ready to see what you've been missing?

What is mq?

mq is a command-line tool that processes Markdown using a syntax similar to jq—the beloved JSON processor that revolutionized how developers work with structured data. Created by harehare and actively developed with rigorous CI/CD practices (including CodeSpeed performance benchmarking), mq fills a critical gap in the developer toolchain.

Built from the ground up in Rust, mq delivers exceptional performance while maintaining an intuitive, declarative query syntax. The project has gained significant traction in the developer community, particularly among teams working with Large Language Model (LLM) workflows, documentation systems, and content pipelines where Markdown serves as the primary data format.

Why is mq trending right now? Three explosive forces have converged:

  1. The LLM Revolution: Markdown is the de facto input format for ChatGPT, Claude, and virtually every major language model. Developers desperately need tools to generate, filter, and transform Markdown at scale.

  2. Documentation-First Culture: Modern development practices—from README-driven development to docs-as-code—have made Markdown the central nervous system of technical projects.

  3. The jq Precedent: Once developers experienced jq's power for JSON, they demanded equivalent capabilities for Markdown. mq answers that call with surgical precision.

The project offers comprehensive tooling beyond the core binary: a web playground for experimentation, a full documentation book, IDE extensions for VSCode/Neovim/Zed, language bindings for Python/Go/Ruby/Java/Elixir, and even an experimental debugger (mq-dbg) for complex query inspection.

Key Features That Make mq Irresistible

mq isn't just another Markdown parser—it's a complete query and transformation engine. Here's what separates it from the pack:

  • Slice and Filter with Surgical Precision: Extract exactly the nodes you need—headings, code blocks, links, tables, lists—using CSS-selector-like syntax combined with jq's powerful filtering expressions. No more regex nightmares.

  • Map and Transform: Apply functions to modify content in-place. Change heading levels, rewrite URLs, reformat code blocks, or convert between Markdown and other formats.

  • Multiple Input/Output Formats: Beyond standard Markdown, mq handles MDX, HTML, plain text, CSV, and even raw binary formats. Output to Markdown, HTML, JSON, tables, or grep-compatible formats.

  • Streaming Mode: Process massive files line-by-line without loading everything into memory. Essential for CI/CD pipelines and log analysis.

  • REPL for Rapid Iteration: Test queries interactively before committing them to scripts. The REPL (mq repl) accelerates query development dramatically.

  • Module System: Import custom functions with include and import-module-names. Build reusable query libraries for your team.

  • External Subcommands: Extend mq infinitely by placing mq-* executables in your PATH. The ecosystem grows without bloating the core.

  • IDE-Grade Tooling: Full Language Server Protocol (LSP) support, VSCode extension with syntax highlighting, and plugins for Neovim and Zed. Write queries with autocomplete and inline errors.

  • Experimental Debugger: Step through complex queries with mq-dbg—a feature virtually unheard of in CLI text processing tools.

Real-World Use Cases Where mq Dominates

1. LLM Prompt Engineering at Scale

Modern AI workflows are Markdown-heavy. You're crafting system prompts, few-shot examples, and output templates—all in Markdown. mq lets you extract, combine, and transform prompt components programmatically:

# Extract all examples from your prompt library
mq '.code("example")' prompts/*.md | mq -A 'join("\n---\n")' > combined_examples.md

2. Documentation Extraction and Reorganization

Need to generate a "Quick Start" from a comprehensive README? Or extract API references into a separate file?

# Pull just the Installation and Usage sections
mq -A 'section::section("Installation", "Usage")' README.md > quickstart.md

3. Code Audit and Dependency Analysis

Scan repositories for security issues, outdated dependencies, or coding patterns:

# Find all code blocks mentioning deprecated APIs
mq '.code | select(contains("deprecated_api"))' docs/**/*.md

4. Content Migration Pipelines

Converting from Confluence, Notion, or Word to a docs-as-code system? mq handles the heavy lifting:

# Convert Word doc, extract h2 sections as separate files
mq conv legacy.docx | mq -A 'section::sections() | section::by_level(2)' | \
  mq --stream '.[] | tofile("section_\(.h.text).md")'

5. Automated Changelog Generation

Parse commit messages, PR descriptions, or issue comments formatted in Markdown:

# Extract all breaking changes from release notes
mq '.h(2) | select(contains("Breaking")) | ..' releases/*.md

Step-by-Step Installation & Setup Guide

Getting mq running takes under 60 seconds. Choose your preferred method:

Quick Install (Recommended)

The official installer handles everything automatically:

# One-liner installation
curl -sSL https://mqlang.org/install.sh | bash

This downloads the correct binary for your platform, installs to ~/.local/bin/, and updates your shell profile. Restart your terminal or run source ~/.bashrc (or equivalent) to activate.

Cargo (Rust Ecosystem)

# Latest stable from crates.io
cargo install mq-run

# Specific version from GitHub
cargo install --git https://github.com/harehare/mq.git mq-run --tag v0.5.29

# Bleeding edge
cargo install --git https://github.com/harehare/mq.git mq-run --bin mq

# With debugger support
cargo install --git https://github.com/harehare/mq.git mq-run --bin mq-dbg --features="debugger"

Pre-built Binaries

# macOS Apple Silicon
curl -L https://github.com/harehare/mq/releases/download/v0.5.29/mq-aarch64-apple-darwin \
  -o /usr/local/bin/mq && chmod +x /usr/local/bin/mq

# Linux x86_64
curl -L https://github.com/harehare/mq/releases/download/v0.5.29/mq-x86_64-unknown-linux-gnu \
  -o /usr/local/bin/mq && chmod +x /usr/local/bin/mq

# Linux ARM64
curl -L https://github.com/harehare/mq/releases/download/v0.5.29/mq-aarch64-unknown-linux-gnu \
  -o /usr/local/bin/mq && chmod +x /usr/local/bin/mq

Homebrew

brew install mq

Docker

docker run --rm ghcr.io/harehare/mq:0.5.29

IDE Setup

Verify Installation

mq --version
mq repl  # Start interactive mode to test queries

REAL Code Examples from mq

Let's dive into actual mq queries from the official documentation. These aren't toy examples—they're production-ready patterns you can use immediately.

Example 1: Extracting Headings with Precision

The most common Markdown operation is extracting structure. mq makes this effortless:

# Extract ALL headings from a document
mq '.h' README.md

# Extract only h1 headings (single level)
mq '.h(1)' README.md

# Extract h1 AND h2 headings (multiple specific levels)
mq '.h(1, 2)' README.md

# Extract headings from level 1 to 3 using a RANGE (inclusive)
mq '.h(1..3)' README.md

What's happening here? The .h selector targets heading nodes in the Markdown AST. The optional parentheses allow filtering by level—single integer for exact match, comma-separated for multiple levels, and .. range syntax for continuous spans. This produces clean, structured output without any regex gymnastics.

Example 2: Code Block Intelligence

Code blocks are the lifeblood of technical documentation. mq treats them as first-class queryable objects:

# Extract only Rust code blocks (filter by language)
mq '.code("rust")' example.md

# Extract code blocks containing specific text
mq '.code | select(contains("name"))' example.md

# Extract just the code VALUES (strip fences and language tags)
mq -A 'pluck(.code.value)' example.md

# Extract language identifiers for audit purposes
mq '.code.lang' documentation.md

# EXCLUDE JavaScript code blocks (negative filtering)
mq '.code | select(.code.lang != "js")' examples.md

The power move: Notice how .code returns an object with .lang and .value properties? This structured access means you can filter, transform, and extract with semantic understanding—not brittle pattern matching.

Example 3: Advanced Table and Link Processing

Markdown tables and links hold structured data that mq can unlock:

# Extract URLs from all links (flat list of destinations)
mq '.link.url' README.md

# Filter table cells containing specific text (2D traversal)
mq '.[][] | select(contains("name"))' data.md

# Complex boolean logic: select lists OR headers containing text
mq 'select(.[] || .h) | select(contains("name"))' docs.md

Critical insight: The .[][] syntax navigates table rows and cells—jq veterans will recognize this immediately. The select(.[] || .h) pattern demonstrates mq's support for boolean logic across node types, enabling sophisticated content detection.

Example 4: Section-Aware Document Surgery

This is where mq transcends simple extraction and enters document manipulation territory:

# Extract a complete section by its heading title
mq -A 'section::section("Installation")' README.md

# Get all top-level sections, then filter by heading level
mq -A 'section::sections() | section::by_level(2)' README.md

# Same approach with a RANGE of levels
mq -A 'section::sections() | section::by_level(1..2)' README.md

Why this matters: The section:: namespace provides document-structure-aware operations. Unlike naive text splitting, this respects Markdown's hierarchical nature—nested sections, code blocks within sections, and complex content boundaries are handled correctly.

Example 5: Composable Workflows with Pipes

mq shines in Unix pipelines, composing with itself and other tools:

# Convert Excel to Markdown, then extract all headings
mq conv report.xlsx | mq '.h'

# Convert Word document, extract specific section
mq conv document.docx | mq -A 'section::section("Summary")'

# Convert PDF slides and preview in terminal
mq conv slides.pdf | mq view

The philosophy: Each mq subcommand does one thing well. conv handles format conversion, then standard mq queries process the Markdown. This composability mirrors jq's design and the Unix philosophy—small, focused tools that combine into powerful workflows.

Example 6: CSV to Markdown Transformation

mq even bridges tabular data formats:

# Parse CSV with header row, convert to Markdown table
mq 'include "csv" | csv_parse(true) | csv_to_markdown_table()' example.csv

The include system loads external modules, extending mq's capabilities without bloating the core. The csv_parse(true) function enables header-aware parsing, and csv_to_markdown_table() handles alignment and formatting automatically.

Advanced Usage & Best Practices

Ready to level up? Here are pro strategies from the mq ecosystem:

Use -A for Aggregate Operations: When processing multiple files, -A collects all results into a single array—essential for cross-document analysis and pluck() operations.

Leverage Streaming for Massive Files: The --stream flag processes input line-by-line. Combine with --parallel-threshold (default: 10 files) for automatic parallelization across large file sets.

Build External Subcommands: Place mq-* executables in ~/.local/bin/ to extend functionality. mq --list reveals all available subcommands—built-in and custom.

Master Output Formats: Use -F json for API integration, -F html for web publishing, -F grep for integration with existing toolchains, and -F table for terminal-friendly display.

In-Place Editing with -U: The -U (update) flag modifies files directly—perfect for automated refactoring scripts. Alias carefully; this is powerful but irreversible.

Environment Variables via --args: Pass runtime configuration without hardcoding: mq --args version "1.2.3" '$version'.

Comparison with Alternatives

Tool Syntax Speed Markdown-Aware LLM-Ready IDE Support
mq jq-like, declarative ⚡ Rust-native, extremely fast ✅ Full AST parsing ✅ Designed for it ✅ LSP + 3 editors
sed/awk Imperative regex Fast ❌ Fragile pattern matching ❌ Manual extraction ❌ None
pandoc Filters in Lua/Haskell Moderate ✅ Conversion-focused ⚠️ Possible with filters ⚠️ Limited
Python markdown Python code Slow ⚠️ Extension-dependent ⚠️ Requires coding ❌ None
jq + conversion jq (after conversion) Fast ❌ Requires pre-conversion ⚠️ Indirect workflow ❌ None

The verdict: mq is the only tool that combines jq's query elegance with native Markdown semantics, Rust performance, and modern developer experience. For LLM workflows and documentation pipelines, there's simply no comparison.

FAQ

Q: Is mq stable for production use? A: The project is under active development with comprehensive CI/CD, CodeSpeed benchmarking, and regular releases. The core query syntax is stable; check release notes for breaking changes.

Q: Can mq handle MDX (Markdown + JSX)? A: Yes! Use -I mdx to enable MDX parsing mode. mq understands JSX component syntax within Markdown documents.

Q: How does mq compare to using pandoc with custom filters? A: pandoc excels at format conversion; mq excels at querying and transformation. For complex extraction and filtering operations, mq's declarative syntax is significantly more concise and maintainable than Lua or Haskell filters.

Q: Is there a JavaScript/TypeScript API? A: Use mq-web via npm for browser and Node.js environments. It's a WebAssembly build with the full mq engine.

Q: Can I use mq in GitHub Actions? A: Absolutely. The official harehare/setup-mq@v1 action installs mq in your workflow in seconds.

Q: How do I debug complex queries? A: Install mq-dbg with --features="debugger" and use it to step through queries interactively, inspecting the AST at each stage.

Q: Does mq support custom functions? A: Yes, via the module system (include, import-module-names) and external subcommands (mq-* executables). The LSP provides autocomplete for custom functions.

Conclusion

Markdown has been the unchallenged king of developer documentation for two decades. Yet until mq, we've lacked a tool worthy of its dominance—something that treats Markdown as queryable, transformable, composable data rather than plain text to be regex-mangled.

mq changes everything. It brings the ergonomic power of jq to the format that powers our READMEs, our LLM prompts, our documentation sites, and our technical content pipelines. Written in Rust for blazing performance. Designed with modern developer experience in mind—REPL, debugger, LSP, IDE extensions. Extensible through modules and external subcommands. Ready for the LLM era where Markdown isn't just documentation, but data.

The developers who master mq today will build documentation pipelines, content workflows, and AI integrations that leave others struggling with Python scripts and broken regex. The question isn't whether you'll adopt mq—it's whether you'll be ahead of the curve or catching up.

⭐ Star mq on GitHub and start transforming your Markdown workflow today. Your future self will thank you.

Try it instantly in the browser — no installation required.

Comments (0)

Comments are moderated before appearing.

No comments yet. Be the first to share your thoughts!

Support us! ☕