name: mq
description: Query markdown, HTML, and PDF files with mq CLI. Triggers on: exploring doc structure, extracting sections from large .md/.html/.pdf files, 'use mq', or when reading full documents wastes tokens.
mq Skill: Efficient Document Querying
mq doesn't compute answers - it externalizes document structure into your context so you can reason to answers yourself.
Documents → mq query → Structure enters your context → You reason → Results
The Pattern
1. See structure → mq <path> .tree → Map enters your context
2. Find relevant → mq <path> ".search('x')" → Locations enter your context
3. Extract content → mq <path> ".section('Y') | .text" → Content enters your context
mq <path> ".search('x') | .text" → Flatten matched structured results
mq <path> ".search('x') | .nth(0)" → Show one raw matched result
mq <path> ".search('x') | .nth(0) | .raw" → Explicit raw record
4. Reason → You compute the answer from what's now in your context
Your context accumulates structure. You do the final reasoning.
Quick Reference
mq file.md .tree
mq dir/ .tree
mq file.md ".search('term')"
mq dir/ ".search('term')"
mq log.jsonl ".search('error')"
mq file.md ".section('Name') | .text"
mq file.md ".code('python')"
mq file.md .links
mq file.md .metadata
mq log.jsonl ".search('error') | .text"
mq log.jsonl ".search('error') | .nth(0)"
mq log.jsonl ".search('error') | .nth(0) | .raw"
Efficient Workflow
Starting: Get the Map
mq README.md .tree
mq docs/ .tree
Output shows you the territory:
docs/ (7 files, 42 sections)
├── API.md (234 lines, 12 sections)
│ ├── # API Reference
│ │ "Complete reference for all REST endpoints..."
│ ├── ## Authentication
│ │ "All requests require Bearer token..."
Now you know: API.md has auth info, 234 lines, section called "Authentication".
Finding: Narrow Down
If you need something specific but don't know where:
mq docs/ ".search('OAuth')"
Output points you to exact locations:
Found 3 matches for "OAuth":
docs/auth.md:
## Authentication (lines 34-89)
"...OAuth 2.0 authentication flow..."
## OAuth Flow (lines 45-67)
Now you know: auth.md, section "OAuth Flow", lines 45-67.
Extracting: Get Only What You Need
Don't read the whole file. Extract the section:
mq docs/auth.md ".section('OAuth Flow') | .text"
This returns just that section's content.
Anti-Patterns
Bad: Reading entire files
cat docs/auth.md
Good: Query then extract
mq docs/auth.md .tree
mq docs/auth.md ".section('OAuth Flow') | .text"
Bad: Re-querying structure you already have
mq docs/ .tree
mq docs/ .tree
Good: Use what's in your context
mq docs/ .tree
mq docs/auth.md ".section('OAuth') | .text"
Context as Working Memory
Every mq output enters your context. Your context becomes a working index that grows as you explore:
Query 1: mq docs/ .tree
→ You now see: file list, line counts, section counts
→ You can reason: "auth.md looks relevant to my question"
Query 2: mq docs/auth.md .tree
→ You now see: auth.md's full section hierarchy
→ You can reason: "OAuth Flow section has what I need"
Query 3: mq docs/auth.md ".section('OAuth Flow') | .text"
→ You now have: the actual content
→ You can reason: compute the final answer
mq externalizes structure. You do the thinking. Don't re-query what you already see.
Format Casts
Cast operators reinterpret a string value as a different document format mid-pipeline.
Use when structured content (markdown, HTML, JSON, YAML) is embedded inside another format.
.text | .md | .headings
.text | .html | .links
.raw | .json | .section("key")
.text | .yaml | .tree
Cast reference:
| Operator | Parses as | Use when field contains |
|---|
.md | Markdown | # Headings, - lists, `code` |
.html | HTML | <h1>, <a href>, <table> |
.json | JSON | {"key": "value"} |
.yaml | YAML | key: value |
Casts work on string, []string (joined with newlines), and nested structures
(recursively extracts text/content fields from arrays of objects).
Examples by Task
"Find something in a JSONL session file"
mq session.jsonl ".search('deploy')"
mq session.jsonl ".search('deploy') | .text"
mq session.jsonl ".search('deploy') | .nth(1)"
mq session.jsonl ".search('deploy') | .nth(1) | .raw"
"Query Claude session files"
Claude stores conversations as JSONL at ~/.claude/projects/{project-id}/{session-id}.jsonl.
Each line is a JSON record with type, message.role, message.content, timestamp.
mq ~/.claude/projects/-Users-you-project/ '.search("auth")'
mq session.jsonl '.search("REPORT") | .nth(0) | .raw | .json | .section("content") | .text | .md | .headings'
mq session.jsonl '.search("REPORT") | .nth(0) | .raw | .json | .section("content") | .text | .md | .section("Recommendations") | .text'
mq session.jsonl '.search("impl") | .nth(0) | .raw | .json | .section("content") | .text | .md | .code("go")'
The pipeline pattern for nested content:
.search("term") → find JSONL record
| .nth(0) → pick one result
| .raw → get raw JSON line
| .json → parse as JSON document
| .section("key") → navigate to a field
| .text → extract string value
| .md → cast to markdown
| .headings → structural query on inner content
"Find how authentication works"
mq docs/ ".search('auth')"
mq docs/auth.md ".section('Overview') | .text"
"Get all Python examples"
mq docs/ .tree
mq docs/examples.md ".code('python')"
"Understand the API structure"
mq docs/api.md .tree
mq docs/api.md ".section('Endpoints') | .tree"
mq docs/api.md ".section('POST /users') | .text"
"Find configuration options"
mq . ".search('config')"
mq config.md ".section('Options') | .text"