A Python CLI tool for extracting structured information from Markdown files, optimized for AI-agent usage with clear status messages and structured output formats.
- Heading Extraction: Extract headings at specified levels (1-6) with hierarchy preservation
- Emphasized Text Extraction: Extract bold and italic text, optionally filtered by heading context
- Text Search: Find text patterns (with regex support) and extract surrounding context
- Section-Limited Search: Limit searches to content within specific heading sections
- Multiple Output Formats: Markdown, plain text, or JSON output
- AI-Agent Optimized: Status messages to stderr, structured JSON output, clear error handling
This project uses UV for fast package management and builds.
- Python 3.8 or higher
- UV (install from https://github.com/astral-sh/uv)
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"Best for: CLI tools, system-wide access, isolated tool management
cd mdparser
uv tool install -e .
uv tool update-shell- ✅ Changes to code are immediately reflected (no reinstall needed)
- ✅ Isolated tool environment
- ✅ System-wide
mdparsercommand
cd mdparser
uv tool install .
uv tool update-shell- ✅ Makes a copy of the code (works independently of source location)
- ✅ Good for stable/production versions
Verify installation:
uv tool list # Should show mdparser
which mdparser # Should show path in UV tools dir
mdparser --help # Should work from anywhereUninstall:
uv tool uninstall mdparserFor more installation options and details, see INSTALLATION.md.
cd mdparser
uv pip install -e .This will make the mdparser command available system-wide in your Python environment.
mdparser <file> [OPTIONS]Extract all level 1 and 2 headings:
mdparser document.md --headings 2Extract headings up to level 3 and save to file:
mdparser document.md --headings 3 --output headings.txtExtract headings in JSON format:
mdparser document.md --headings 3 --format jsonExtract headings with content included:
# Include 1 line of content after each level 3 heading
mdparser document.md --headings 3 --include-content-lines 1
# Include 2 lines of content after each level 3 heading
mdparser document.md --headings 3 --include-content-lines 2
# Include 100 characters of content after each level 3 heading
mdparser document.md --headings 3 --include-content-chars 100Extract all emphasized text (bold and italic):
mdparser document.md --emphasizedExtract only bold text:
mdparser document.md --emphasized-boldExtract only italic text:
mdparser document.md --emphasized-italicExtract emphasized text under a specific heading:
mdparser document.md --emphasized-bold --emphasized-under "1. FOUNDATION OF RELATIONSHIP"Find text pattern and extract context:
mdparser document.md --find "### 1.1"Find pattern and extract 5 lines after:
mdparser document.md --find "### 1.1" --lines-after 5Find pattern with context before and after:
mdparser document.md --find "Fabricator" --lines-before 2 --lines-after 3Case-sensitive search:
mdparser document.md --find "Fabricator" --case-sensitiveSearch within a specific section:
Limit search to content under a specific heading:
# Find "CIF" only within the Definitions section
mdparser document.md --find "\"CIF\"" --within-section "6. DEFINITIONS" --lines-after 1
# Find "Deliverables" only within Definitions section
mdparser document.md --find "\"Deliverables\"" --within-section "6. DEFINITIONS" --lines-after 1
# Find all occurrences of a term within a specific section
mdparser document.md --find "Fabricator" --within-section "6. DEFINITIONS"This is particularly useful for extracting definitions or finding terms that appear multiple times but you only want matches from a specific section.
Write output to file:
mdparser document.md --headings 3 --output headings.txtOutput in JSON format:
mdparser document.md --headings 3 --format jsonOutput in plain text format:
mdparser document.md --headings 3 --format textShow detailed operation messages:
mdparser document.md --headings 3 --verboseSuppress status messages (only show results):
mdparser document.md --headings 3 --quietPreserves original markdown formatting:
# ATTACHMENT B: TERMS AND CONDITIONS
## 1. FOUNDATION OF RELATIONSHIP
### 1.1 Mutual Understanding and Professional StandardsClean, parseable plain text:
ATTACHMENT B: TERMS AND CONDITIONS
1. FOUNDATION OF RELATIONSHIP
1.1 Mutual Understanding and Professional Standards
Structured JSON with metadata (AI-agent friendly):
{
"operation": "extract_headings",
"file": "document.md",
"parameters": {
"max_level": 3
},
"results": [
{
"level": 1,
"text": "ATTACHMENT B: TERMS AND CONDITIONS",
"raw": "# ATTACHMENT B: TERMS AND CONDITIONS"
}
],
"count": 25,
"status": "success"
}All status messages are printed to stderr, ensuring stdout contains only results. This makes the tool ideal for AI agents and scripting.
Message formats:
[STATUS] <message>- Operation status[SUCCESS] <message>- Success messages[ERROR] <message>- Error messages[PROGRESS] <message>- Progress indicators[VERBOSE] <message>- Verbose details (only with --verbose)
0- Success1- Error (file not found, invalid parameters, etc.)2- No matches found
# Extract all level 1 and 2 headings as a table of contents
mdparser document.md --headings 2 --format text > toc.txt
# Extract with JSON format for programmatic processing
mdparser document.md --headings 2 --format json > toc.json# Extract all bold text
mdparser document.md --emphasized-bold --format json > bold_terms.json
# Extract bold text only from a specific section
mdparser document.md --emphasized-bold --emphasized-under "6. DEFINITIONS" > definitions_bold.json# Find a subsection and extract context
mdparser document.md --find "### 1.1" --lines-after 10 --format markdown
# Extract entire section with heading
mdparser document.md --find "## 6. DEFINITIONS" --lines-after 20# Find a specific definition within the Definitions section
mdparser document.md --find "\"CIF\"" --within-section "6. DEFINITIONS" --lines-after 1
# Find multiple definitions
mdparser document.md --find "\"Deliverables\"" --within-section "6. DEFINITIONS" --lines-after 1
mdparser document.md --find "\"Fabricator\"" --within-section "6. DEFINITIONS" --lines-after 1# Extract all level 2 headings with one line of context after each
mdparser document.md --find "^## " --lines-after 1
# Extract all level 3 headings with context
mdparser document.md --find "^### " --lines-after 1# Get structured JSON output for AI processing
mdparser document.md --headings 3 --format json --quiet > headings.json
# Extract all emphasized text with context
mdparser document.md --emphasized --format json --quiet > emphasized.json
# Search for specific terms with structured output
mdparser document.md --find "Fabricator" --within-section "6. DEFINITIONS" --format json --quiet > fabricator_def.json# Extract all definitions from a document
mdparser document.md --find "^## 6. DEFINITIONS" --lines-after 25 > all_definitions.md
# Find all section headings with their first paragraph
mdparser document.md --find "^## " --lines-after 3 > sections_with_intro.md
# Extract specific terms from multiple sections
mdparser document.md --find "Fabricator" --within-section "1. SCOPE OF AGREEMENT" > fabricator_in_scope.md
mdparser document.md --find "Fabricator" --within-section "6. DEFINITIONS" > fabricator_definition.mdmdparser <file> [OPTIONS]
Heading Extraction:
--headings LEVELS Extract headings up to level N (1-6)
Example: --headings 3 extracts levels 1, 2, 3
--include-content-lines N Include N lines of content after headings at the deepest extracted level
Example: --headings 3 --include-content-lines 2 includes 2 lines for level 3 headings
--include-content-chars N Include N characters of content after headings at the deepest extracted level
Example: --headings 3 --include-content-chars 100 includes 100 chars for level 3 headings
Note: If both --include-content-lines and --include-content-chars are specified, lines takes precedence
Emphasized Text Extraction:
--emphasized Extract all emphasized text (bold/italic)
--emphasized-bold Extract only bold text (**text**)
--emphasized-italic Extract only italic text (*text* or _text_)
--emphasized-under HEADING Extract emphasized text under specific heading
Text Search:
--find TEXT Find text pattern and extract context (supports regex)
--lines-after N Number of lines to extract after match (default: 0)
--lines-before N Number of lines to extract before match (default: 0)
--case-sensitive Case-sensitive search (default: case-insensitive)
--within-section HEADING Limit search to content under a specific heading
(e.g., "6. DEFINITIONS")
Output Options:
-o, --output FILE Write output to file instead of stdout
--format FORMAT Output format: markdown, text, json (default: markdown)
Verbosity:
-v, --verbose Show detailed operation messages and progress
-q, --quiet Suppress status messages (only show results)
-h, --help Show help message with examples# Get all headings as table of contents
mdparser document.md --headings 3 --format text
# Get headings with JSON for programmatic processing
mdparser document.md --headings 3 --format json --quiet > structure.json# Find a term anywhere in document
mdparser document.md --find "Fabricator"
# Find a term only in a specific section
mdparser document.md --find "Fabricator" --within-section "6. DEFINITIONS"
# Find with context (3 lines before, 5 lines after)
mdparser document.md --find "Fabricator" --lines-before 3 --lines-after 5# Extract all definitions from Definitions section
mdparser document.md --find "^## 6. DEFINITIONS" --lines-after 25
# Extract specific definition
mdparser document.md --find "\"CIF\"" --within-section "6. DEFINITIONS" --lines-after 1
# Extract multiple definitions
for term in "CIF" "Deliverables" "Fabricator"; do
mdparser document.md --find "\"$term\"" --within-section "6. DEFINITIONS" --lines-after 1
done# All bold text
mdparser document.md --emphasized-bold
# Bold text from specific section
mdparser document.md --emphasized-bold --emphasized-under "6. DEFINITIONS"
# All emphasized (bold + italic) with JSON output
mdparser document.md --emphasized --format json --quiet > emphasized.json# All level 2 headings with first paragraph
mdparser document.md --find "^## " --lines-after 3
# All level 3 subsections with content
mdparser document.md --find "^### " --lines-after 2
# Specific section with full content
mdparser document.md --find "## 1. SCOPE OF AGREEMENT" --lines-after 50# Extract document structure
mdparser document.md --headings 3 --format json --quiet > doc_structure.json
# Extract all definitions
mdparser document.md --find "^## 6. DEFINITIONS" --lines-after 25 --format json --quiet > definitions.json
# Extract key terms from specific sections
mdparser document.md --find "Fabricator" --within-section "1. SCOPE OF AGREEMENT" --format json --quiet > fabricator_scope.json
mdparser document.md --find "Fabricator" --within-section "6. DEFINITIONS" --format json --quiet > fabricator_def.jsonThe tool provides clear error messages:
$ mdparser nonexistent.md --headings 2
[ERROR] File not found: nonexistent.md$ mdparser document.md --headings 10
[ERROR] Invalid parameter: Heading level must be between 1 and 6, got 10$ mdparser document.md --find "[invalid(regex" --within-section "6. DEFINITIONS"
[ERROR] Invalid parameter: Invalid regex pattern: [invalid(regex. Error: ...mdparser/
├── mdparser/
│ ├── __init__.py
│ ├── cli.py # Main CLI entry point
│ ├── parser.py # Markdown parsing logic
│ ├── extractors.py # Extraction functions
│ └── utils.py # Utility functions
├── tests/
│ └── test_extractors.py
├── pyproject.toml # UV project configuration
├── PLAN.md # Implementation plan
└── README.md
# Install test dependencies
uv sync --dev
# Run tests
pytest tests/uv build- mistletoe: Fast, CommonMark-compliant Markdown parser
- argparse: Built-in CLI framework (no external dependencies)
See LICENSE file for details.
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
For issues and questions, please open an issue on the project repository.