flowmark

Crates.ioflowmark
lib.rsflowmark
version0.1.3
created_at2025-11-04 06:38:01.760484+00
updated_at2025-11-04 07:14:51.261779+00
descriptionFast, modern Markdown formatter with smart typography and paragraph wrapping
homepagehttps://github.com/jlevy/flowmark
repositoryhttps://github.com/jlevy/flowmark-rs
max_upload_size
id1915845
size1,402,300
Joshua Levy (jlevy)

documentation

README

Flowmark-rs

Port of Flowmark to Rust

Flowmark-rs is a high-performance AI-generated Rust mirror port of the Flowmark Python-based auto-formatter. Flowmark is among the most complete and flexible auto-formatters for Markdown, with optional line wrapping, semantic line breaks, typographic transformations, and full support for GitHub-flavored Markdown. See the [original package]((https://github.com/jlevy/flowmark) for more.

About the Port

This Rust implementation is mirror port with feature parity with the Python Flowmark library.

Output is byte-for-byte identical except a few remaining corner cases due to parser libraries (comrak vs marko): see cross-validation-assessment.md for detailed remaining issues.

Why?

I made this complete port using Claude Code in about a day. I’m completely new to Rust but experienced at Python and agent coding so wanted to see how fully this process could be automated for a relatively complex but still self-contained CLI like Flowmark.

Every line of Rust was written by Claude. A significant amount of the architecture and testing process was organized by me up front and a few of the trickier parts required guidance from me during the bug-fixing phase.

Much of the process was surprisingly smooth it should not be hard to have it continue to mirror features and fixes to the Python version. Because I wanted the result to be correct and usable as a replacement for the Python implementation, I took time to research and document best practices for Rust port.

Comprehensive documentation from the porting process is in the docs/ directory.

The Overall Porting Process

I’ve written notes on the entire process for Claude-based port, and you can also see the Git commits and merged PRs in the repo here.

  1. Background Research: (About an hour.) First, I instructed Claude to do background research on best practices for Rust CLIs and carefully reviewed these, to get the Rust CLI Best Practices doc.

  2. Porting Plan: (About an hour.) Then, I worked with Claude in a separate session to create a Python to Rust Migration Plan. The key thing was to map out libraries and tools and how to ensure exact feature parity, using the fairly complete tests that are in the Python implementation. A key part was encouraging it to look at all libraries and evaluate which are best given the Python system’s use of a highly customized Marko parser.

  3. Additional Plans: (About an hour, in parallel with the previous step.) I also chatted with Claude to get a CI/CD and Publishing Plan, again insisting it carefully research for best modern practices.

    The key thing was to insist that Claude exactly reproduce all tests, as well as write additional tests as it goes. I iterated a little get a generic Port Checklist Template to ensure we covered all the necessary steps and used it as a port checklist.

    As a sanity check, I also used GPT-5 High to review these docs and accepted a few more minor suggestions for improvements.

  4. Initial Implementation: (2-3 hours.) This was nearly the longest part. I had Claude work through the plan piece by piece, each time reminding it to follow exactly all the tests in Python, optionally adding more for test-driven development as it progressed. It required encouragement to continue 8 or 9 times, as there was a lot to implement, but it was basically the same prompt every time, and a couple cases where I insisted it must fix 100% of tests before going to the next phase.

  5. Bug-fixing: (2-3 hours.) This was the most painful part. I did all this in Claude Code cloud, so I could use multiple work trees and not be waiting on the slow parts. For this reason, I had several PRs for these steps, and merged them as I went.

    But at this point I switched to local Claude Code, so I could have it use gh to manage and monitor PRs.

    Many corner cases arose that were only partly covered in the tests, or where Claude got confused by intricacies of line wrapping and Markdown specifics that were different in the Python and Rust libraries. It would keep insisting the results were close enough but I allowed zero tolerance.

    This led to finding about a dozen other corner case issues. A couple were actual bugs in the Python implementation, so I used them to produce a new test doc and extend the tests in Python version and fix them (again with Claude Code). Then update the submodule to use the new Python release.

    Claude took a lot longer here. I had to remind it several times to go read the code carefully and understand a problem, rather than try to work around it. I also had to make it read the code to comrak to identify specific flags and logic. This identified at least one bug in comrak and about a dozen other differences between comrak and Python’s marko library. I had it implement workarounds for bugs we could not fix.

    See cross-validation-assessment.md for comprehensive documentation of all comrak vs marko parser differences found during porting. After a bunch of iteration, Claude finally got most of the key issues corrected. Most are now fixed but a few are remaining as we need to vendor the dependencies to fix them all.

    (I’ll revisit these again soon, after another small bugfix or two to the original Python version related to obscure escaping conventions.)

Installation

Pre-built Binaries (Recommended)

Download pre-built binaries from the Releases page

Binary name: flowmark (matching the Python version).

Supported platforms: Linux x86_64 (glibc and musl/static), Linux ARM64, macOS Intel (x86_64), macOS Apple Silicon (ARM64), Windows x86_64

From Source

git clone --recursive https://github.com/jlevy/flowmark-rs.git
cd flowmark-rs
cargo build --release

Binary will be available at:

  • target/release/flowmark

Using Cargo (When Published)

# Coming soon to crates.io
cargo install flowmark

Usage

# Format a file, print to stdout
flowmark document.md

# Format with semantic line breaks
flowmark --semantic document.md

# Auto mode (all features, editing in place)
flowmark --auto document.md

# Custom line width
flowmark --width 100 document.md

# From stdin
cat document.md | flowmark > output.md

Command-Line Options

flowmark [OPTIONS] [FILE]

Options:
  -w, --width <WIDTH>       Line width to wrap to, or 0 to disable [default: 88]
  -p, --plaintext           Process as plaintext (no Markdown parsing)
  -s, --semantic            Enable semantic (sentence-based) line breaks
  -c, --cleanups            Enable cleanups for common issues
      --smartquotes         Convert straight quotes to typographic quotes
      --ellipses            Convert ... to … character
  -i, --inplace             Edit the file in place
      --nobackup            Do not make a backup when using --inplace
      --auto                Full auto-formatting (all features)
  -j, --json                Output in JSON format (line-delimited)
  -v, --verbose             Increase logging verbosity (-v, -vv, -vvv)
  -h, --help                Print help
  -V, --version             Print version

Architecture

Flowmark is a single Rust package with both library and binary components:

flowmark-rs/
├── src/                   # Source code (library + binary)
├── tests/                 # Integration tests
├── .github/workflows/     # CI/CD pipelines
└── docs/                  # Documentation

Modern tooling:

Development and Testing

See development.md for complete development workflows, testing procedures, release process, and CI/CD documentation.

Commit count: 0

cargo fmt