mq

star 0

Query markdown content like jq (headings, code blocks, tables, links)

jcsaaddupuy By jcsaaddupuy schedule Updated 2/26/2026

name: mq description: "Query markdown content like jq (headings, code blocks, tables, links)"

mq - Markdown Query Language

A jq-like CLI for querying and filtering markdown AST nodes. Repository available at https://github.com/harehare/mq

Core Selectors

Selector Description
.h, .h1.h6 Headings (any level or specific)
.code Fenced code blocks
.code_inline Inline code (backticks)
.link Links
.image Images
.text Text nodes
.strong Bold
.emphasis Italic
.blockquote Blockquotes
.list List items
.table Tables
.yaml YAML frontmatter
.toml TOML frontmatter

Node Attributes

Access with dot notation: selector.attribute

Selector Attributes
.h .depth / .level (1–6), .value
.code .lang, .value, .meta, .fence
.code_inline .value
.link .url, .title, .value
.image .url, .alt, .title
.list .ordered, .checked, .level, .index
.table .row, .column, .align

Basic Usage

# Extract all headings
mq '.h' file.md

# H2 headings only
mq '.h2' file.md

# All code blocks
mq '.code' file.md

# All links
mq '.link' file.md

# Tables
mq '.table' file.md

Output Formats

mq '.code' file.md               # markdown (default)
mq -F text '.code' file.md       # plain text - best for code content
mq -F json '.h' file.md          # JSON - best for parsing/analysis
mq -F html '.h' file.md          # HTML output

Filtering with select()

select() is the primary filter mechanism. When the condition uses a node attribute, the selector is implicit:

# Code blocks by language
mq 'select(.code.lang == "typescript")' file.md
mq 'select(.code.lang == "bash")' file.md
mq 'select(.code.lang != "bash")' file.md   # exclude a language

# Headings by depth
mq 'select(.h.depth <= 2)' file.md          # H1 and H2 only
mq 'select(.h.depth == 3)' file.md          # H3 only

# Filter then extract attribute
mq 'select(.code.lang == "python") | .code.value' file.md
mq 'select(.h.depth == 2) | .h.value' file.md

Filtering with contains() and starts_with()

# Heading containing a word
mq '.h | select(contains("Installation"))' file.md

# Link URL containing a domain
mq '.link | select(contains("github"))' file.md

# Code block containing specific content
mq 'select(.code) | select(contains("TODO"))' file.md

# Heading starting with prefix
mq '.h | select(starts_with("How"))' file.md

Combining Selectors

# H1 or H2 (logical or)
mq 'select(or(.h1, .h2))' file.md

# Node is heading AND level 2 (logical and)
mq 'select(and(.h, .h2))' file.md

Extracting Attribute Values

# Get all heading text
mq '.h.value' file.md

# Get all code languages used
mq '.code.lang' file.md

# Get all link URLs
mq '.link.url' file.md

# Get image alt texts
mq '.image.alt' file.md

# Get raw code content (no fences)
mq '.code.value' file.md
# or equivalently:
mq -F text '.code' file.md

Multi-File Processing

# All headings across files
mq '.h' docs/**/*.md

# H1 from all Pi skills
mq '.h1' ~/.pi/agent/skills/*/SKILL.md

# Aggregate all code into single array
mq -A '.code' examples/*.md

String Functions

mq '.h.value | upcase' file.md
mq '.h.value | downcase' file.md
mq '.code.value | replace("old", "new")' file.md
mq '.link.url | starts_with("https")' file.md
mq '.link.url | ends_with(".org")' file.md
mq '.h.value | split(" ")' file.md

Custom Functions with def

# Define reusable filter
mq 'def is_lang(l): .lang == l; | select(.code) | select(is_lang("typescript"))' file.md

In-place Update with -U

Remove or transform nodes in the file:

# Remove all bash code blocks from file
mq -U 'select(.code.lang != "bash")' file.md

# Keep only H1 and H2 headings
mq -U 'select(or(.h1, .h2))' file.md

Practical Pi Agent Patterns

# Get all section titles (H2) from a skill
mq '.h2.value' ~/.pi/agent/skills/python/SKILL.md

# Get all code examples in a specific language
mq 'select(.code.lang == "bash") | .code.value' SKILL.md

# Extract all external links from docs
mq '.link.url' README.md

# Inspect code block structure
mq -F json '.code' file.md

# Check what languages are used in a doc
mq '.code.lang' file.md

# Find headings matching a topic
mq '.h | select(contains("Docker"))' SKILL.md

# Extract YAML frontmatter
mq '.yaml' SKILL.md

Tips

  • Use select(.node.attr == val) for filtering — the node selector is implicit in the condition
  • Use -F json first to explore node structure when unsure of available attributes
  • Use -F text for clean code extraction without fences
  • Pipe mq output to standard tools: mq '.code.lang' file.md | sort | uniq -c
  • For complex transformations, extract to JSON then pipe to jq
Install via CLI
npx skills add https://github.com/jcsaaddupuy/badrobots --skill mq
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator