Skip to main content

MOFF CLI

Markdown Opinionated File Formatter

A command-line tool for validating and maintaining clean, organized documentation. Designed to work seamlessly with Large Language Models (LLMs) in modern IDEs like Cursor, VSCode, and Zed.

Python Version License: MIT

🎯 Purpose

MOFF helps maintain consistent documentation structure across projects by:

  • Validating markdown files against configurable rules
  • Enforcing location constraints for different document types
  • Checking frontmatter schemas and required fields
  • Ensuring headers follow specified patterns and order
  • Providing visual feedback through tree visualization

Perfect for projects where documentation quality and consistency matter, especially when working with AI assistants that write markdown documentation.

✨ Features

  • 📁 Smart Root Detection: Automatically finds documentation root via project_*.md files
  • 🔍 Comprehensive Validation: Check frontmatter, headers, and file locations
  • 🌳 Tree Visualization: See your documentation structure with error highlighting
  • ⚙️ Configurable Rules: Define custom prefixes, patterns, and validation rules
  • 💾 Result Persistence: Save validation results for CI/CD integration
  • 🎨 Rich Terminal Output: Beautiful, colored output using Rich library
  • 📚 Verbose Mode: Shows expected file structure templates when validation fails
  • 🔧 Auto-fix: Automatically fix common issues like missing frontmatter and headers

📦 Installation

Using pip

pip install moff-cli
uv add moff-cli

🚀 Quick Start

  1. Check your documentation (creates settings.json automatically if not present):
moff check
  1. Visualize documentation structure:
moff tree

📖 Usage

Commands Overview

moff --help                    # Show help information
moff --version                 # Show version

moff check                     # Run validation checks
moff check --verbose          # Show expected structure for files with errors
moff check --fix              # Automatically fix fixable issues
moff check --save             # Run checks and save results to moff_results.txt
moff check --save --verbose   # Save results with expected structure templates
moff check --path ./docs      # Check specific directory

moff tree                      # Display documentation tree
moff tree --errors-only       # Show only files with errors
moff tree --no-check          # Skip validation (faster)

Example: Setting Up a Project

  1. Create a project file (project_myapp.md):
---
project: myapp
---

# Overview

This is my application's main documentation.

## Requirements

- Python 3.12+
- Rich library
  1. Create feature documentation (features/feature_auth.md):
---
project: myapp
feature: authentication
linked_features: ["users", "sessions"]
---

# Overview

Authentication system for the application.

## Requirements

- Secure password hashing
- JWT token support
- Session management
  1. Validate your documentation (this will create settings.json if it doesn't exist):
moff check

Example Output

Check Command

Collecting documentation files...
Root directory: /Users/you/project/docs

✓ All checks passed!

No validation issues found.

Or with errors:

Validation Summary:
  Total issues: 2
  Errors: 2

Issues found:

features/feature_broken.md:
  error [feature] headers.missing: Missing required header level=2 text='Requirements' (line 10)

tech_database.md:
  error [tech] location.subdirs_only: File must be in a subdirectory, not in root

Or with verbose mode to see expected structure:

features/feature_broken.md:
  error [feature] frontmatter.missing: Required frontmatter is missing (line 1)
  error [feature] headers.missing: Missing required header level=1 text='Overview'
  error [feature] headers.missing: Missing required header level=2 text='Requirements'

  Expected structure for this file type (feature):
  ---
  project:
  feature:
  linked_features: []
  ---

  # Overview

  ## Requirements

Fix Command

When running moff check, you can use the --fix flag to automatically fix certain issues:

moff check --fix

Fixable issues include:

  • Missing frontmatter blocks
  • Missing required frontmatter fields
  • Missing required headers

Example output:

Applying 3 automatic fixes...
Fixed features/feature_broken.md:
  • Added missing frontmatter block
  • Added missing header: Overview
  • Added missing header: Requirements

Fixes applied successfully!

Note: Some issues cannot be automatically fixed, such as:

  • File location constraints (files in wrong directories)
  • Header ordering issues
  • Type mismatches in frontmatter values

Tree Command

📁 docs (documentation root)
├── 📁 features
│   ├── ⚡ feature_auth.md ✓
│   └── ⚡ feature_users.md ✓
├── 📁 technical
│   └── 🔧 tech_database.md ✓
└── 📋 project_myapp.md ✓

Summary:
  Total markdown files: 4
  Files with errors: 0
  Files with warnings: 0

✓ All files passed validation!

🐍 Programmatic Usage

When installed via pip, moff-cli can also be used as a Python library. Import it as moff_cli:

Basic Validation

from pathlib import Path
from moff_cli import Settings, Collector, Checker

# Load settings and collect documentation
settings = Settings()
collector = Collector(settings, start_path=Path.cwd())
collected_data = collector.collect()

# Run validation
checker = Checker(settings)
diagnostics = checker.check(collected_data)

# Process results
if not diagnostics:
    print("✓ All documentation is valid!")
else:
    for diag in diagnostics:
        print(f"{diag.path}: {diag.message}")

Custom Configuration

from moff_cli import (
    Settings,
    PrefixConfig,
    LocationConstraint,
    HeaderRule,
    HeaderMatch
)

# Create custom settings
settings = Settings()

# Add a custom prefix for API documentation
settings.prefixes["api"] = PrefixConfig(
    filename_pattern="api_*.md",
    location=LocationConstraint.SUBDIRS_ONLY,
    frontmatter_required={
        "endpoint": "string",
        "method": "string",
        "version": "string"
    },
    headers_required=[
        HeaderRule(level=1, text="Endpoint"),
        HeaderRule(level=2, text="Request"),
        HeaderRule(level=2, text="Response"),
    ]
)

# Save custom settings
settings.save_to_file(Path("settings.json"))

Tree Visualization

from moff_cli import Settings, Collector, Checker, TreeVisualizer
from rich.console import Console

console = Console()
settings = Settings()

# Collect and check
collector = Collector(settings)
collected_data = collector.collect()
checker = Checker(settings)
diagnostics = checker.check(collected_data)

# Display tree with error highlighting
visualizer = TreeVisualizer(settings, console)
visualizer.show_tree(collected_data, diagnostics)

CI/CD Integration

from pathlib import Path
from moff_cli import Settings, Collector, Checker, Severity

def validate_docs(project_path: Path) -> bool:
    """Validate documentation for CI/CD pipeline."""
    settings = Settings()
    collector = Collector(settings, start_path=project_path)
    checker = Checker(settings)

    # Collect and check
    collected = collector.collect()
    if collected.get("error"):
        print(f"ERROR: {collected['error']}")
        return False

    diagnostics = checker.check(collected)

    # Filter to only errors (ignore warnings)
    errors = [d for d in diagnostics if d.severity == Severity.ERROR]

    if errors:
        print(f"Validation failed with {len(errors)} errors")
        for error in errors:
            print(f"  ✗ {error.path}: {error.message}")
        return False

    return True

# Use in CI/CD
if not validate_docs(Path(".")):
    exit(1)

Available Classes and Functions

  • Settings: Configuration management
  • Collector: File discovery and parsing
  • Checker: Validation engine
  • TreeVisualizer: Tree visualization
  • Diagnostic: Validation issue representation
  • Severity: Error, Warning, Info levels
  • LocationConstraint: ROOT_ONLY, SUBDIRS_ONLY, ANY
  • HeaderOrder: STRICT, IN_ORDER, ANY
  • HeaderMatch: EXACT, REGEX

⚙️ Configuration

MOFF uses settings.json for configuration. The default configuration supports three document prefixes:

Default Prefixes

Prefix Pattern Location Purpose
project project_*.md Root only Main project documentation
feature feature_*.md Any Feature specifications
tech tech_*.md Subdirs only Technical implementation details

Custom Configuration Example

{
  "version": 1,
  "root": {
    "detect": {
      "method": "project_file",
      "pattern": "project_*.md"
    },
    "override_path": null,
    "ignore": [
      "**/.git/**",
      "**/.venv/**",
      "**/node_modules/**",
      "**/archive/**"
    ]
  },
  "prefixes": {
    "api": {
      "filename": {
        "pattern": "api_*.md"
      },
      "location": "subdirs_only",
      "frontmatter": {
        "required": {
          "project": "string",
          "endpoint": "string",
          "method": "string"
        },
        "optional": {
          "deprecated": "boolean"
        }
      },
      "headers": {
        "required": [
          {
            "level": 1,
            "text": "Endpoint",
            "match": "exact"
          },
          {
            "level": 2,
            "text": "Request",
            "match": "exact"
          },
          {
            "level": 2,
            "text": "Response",
            "match": "exact"
          }
        ],
        "optional": [],
        "order": "in-order"
      }
    }
  }
}

Configuration Options

Root Detection

  • detect.method: Currently supports "project_file"
  • detect.pattern: Glob pattern for root detection (default: "project_*.md")
  • override_path: Bypass auto-detection with explicit path
  • ignore: List of glob patterns to exclude

Location Constraints

  • "root_only": File must be in root directory
  • "subdirs_only": File must be in a subdirectory
  • "any": File can be anywhere

Frontmatter Types

  • "string": Text values
  • "number": Numeric values (int or float)
  • "boolean": True/false values
  • "list": Array values
  • "object": Dictionary/object values

Header Order

  • "strict": Headers must appear in exact order
  • "in-order": Headers must be in order but others can appear between
  • "any": No order enforcement

📝 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • Built with Rich for beautiful terminal output
  • Uses markdown-to-data for parsing
  • Inspired by the need for better documentation tooling in AI-assisted development

Metadata

Release files for moff-cli 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for moff-cli 0.3.1
File Size Uploaded Provenance Actions
moff_cli-0.3.1.tar.gz 84.5 kB Without provenance Details for moff_cli-0.3.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for moff-cli 0.3.1
File Interpreter ABI Platform Actions
moff_cli-0.3.1-py3-none-any.whl Python 3 none any Details for moff_cli-0.3.1-py3-none-any.whl

Total release size: 116.8 kB

Release files / moff_cli-0.3.1.tar.gz

Download URL moff_cli-0.3.1.tar.gz
Size 84.5 kB
Tags Source
SHA-256 checksum
How to use checksums
e34c9e22467e57ccc0684d6b90404e2a69cb9108b026f47ddb11009740aaac9e
BLAKE2b-256 checksum
How to use checksums
300e96277da101255769ffa25f1572047f2808aba4069b3054fd1e9e8622c03c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.20

Release files / moff_cli-0.3.1-py3-none-any.whl

Download URL moff_cli-0.3.1-py3-none-any.whl
Size 32.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9c464a8578a15a3ff78cf2299444e454c6d5ff3fb550e77862a551f684814da9
BLAKE2b-256 checksum
How to use checksums
85237ff82be1589dd05802b95207eddad22ffff1f227ccad5865f1d6b2d87125
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.20

Security for moff-cli 0.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page