Skip to content

Repository files navigation

Rust Porting Playbook

A comprehensive, step-by-step agent playbook for automated porting of applications to Rust. It is a layered collection of playbooks, guidelines, references, research, and real-port evidence that guides agents through the process.

I suggest using the playbook with a strong coding model at a high reasoning setting and beads to better automate the porting plans. (I use tbd, my own beads tool, but the original should work too)

Choose Your Starting Point

What are you here to do? Start here
Start a new Rust project New-project route
Improve or review an existing Rust codebase Existing-codebase route
Port an existing project to Rust Python-to-Rust playbook
Synchronize an existing port Port update checklist

Agent Prompts for Rust Work

Start a Rust project Read guidelines/README.md and follow its new-project route. Load only the general Rust guidelines needed for this project, apply them while designing the package, and record any deviation from their defaults with a concrete reason.

Improve or review a Rust codebase Read guidelines/README.md and follow its existing-codebase route. Load the topic guidelines that match the diff before using the Rust review process, then report findings by severity with file and line evidence.

How Does it Work?

This is new! But it seems to work quite well. This Markdown auto-formatter was automatically ported and it’s arguably now the fastest and most full-featured formatter for Markdown.

In addition to guidelines and playbooks, it’s structured with meta-playbooks to self improve as we do more ports. If you do a port, have it track a case study, using my last port as an example, and then the meta playbook will help improve the overall porting playbook!

Notes and caveats:

  • The end-to-end porting workflow is currently focused on Python-to-Rust. The standalone Rust guideline suite is source-language-independent, and an active workstream in the project specification index tracks the TypeScript-to-Rust path.

  • This requires thoroughly testable Python apps where all features can be mapped to Rust. (You don’t need perfect tests to begin with, as long as the agent can add them and write equivalent tests in Rust.)

  • Ports of libraries and CLI applications are great if they can have golden session tests. See my tryscript CLI to make thorough testing scripts easy for CLI apps.

  • Even if you don’t use the whole playbook, you’ll find giving agents these docs will make their coding quality really improve.

Key elements of the approach:

  • Increasing test coverage (if needed) on the original app

  • Systematically mapping tests from the original to the target Rust application’s tests

  • Making heavy use of reusable guidelines to streamline project setup and avoid pitfalls

  • Using case studies from other ports to refine the overall process

  • Codifying the process for ongoing port updates into two kinds: improvements to Rust port (type A) and port synchronization with a new release (type B)

Flowchart

Porting work is organized into phases. Here is a visual overview:

flowchart TD
    BEGIN([Phase 1 gate passed ✓]) --> P2

    subgraph P2["Phase 2: Research & Library Evaluation"]
        P2_fast{Low-dependency<br/>project?}
        P2_fast -->|Yes| P2_quick[Map to standard equivalents<br/>regex, serde_json, clap]
        P2_fast -->|No| P2_1[Evaluate 2-3 candidates<br/>per high-risk dep]
        P2_1 --> P2_2[Create feature matrices]
        P2_2 --> P2_3[Run proof-of-concept<br/>with real inputs]
        P2_3 --> P2_4[Count and categorize diffs]
        P2_4 --> P2_5[Document decisions<br/>rationale + fallback plans]
        P2_quick --> P2_5
        P2_5 --> P2_6[Optional: best-practices<br/>survey for app type]
    end

    P2 --> P3

    subgraph P3["Phase 3: Plan"]
        P3_1[Define architecture<br/>single crate vs workspace]
        P3_2[Create feature parity matrix]
        P3_3[Plan module porting order<br/>leaf → integration → CLI]
        P3_4[Define acceptance criteria]
        P3_5[Budget effort<br/>35-50% for workarounds]
        P3_1 --> P3_2 --> P3_3 --> P3_4 --> P3_5
    end

    P3 --> P4

    subgraph P4["Phase 4: Set Up"]
        P4_1["cargo init project-rs"]
        P4_2[Configure Cargo.toml<br/>edition, MSRV, lints]
        P4_3[Add Python source<br/>as git submodule]
        P4_4[Set up test fixtures<br/>input/ and expected/]
        P4_5[Set up CI<br/>parallel quality gates]
        P4_6[Track version correspondence<br/>in package.metadata]
        P4_1 --> P4_2 --> P4_3 --> P4_4 --> P4_5 --> P4_6
    end

    P4 --> P5

    subgraph P5["Phase 5: Port the Code"]
        P5_loop["For each module (leaf → root):"]
        P5_1[Port tests first]
        P5_2[Implement until tests pass]
        P5_3[Add traceability comments]
        P5_4[Run cross-validation]
        P5_5[Update parity tracking spec]
        P5_loop --> P5_1 --> P5_2 --> P5_3 --> P5_4 --> P5_5
        P5_5 -->|Next module| P5_loop
    end

    P5 --> P6

    subgraph P6["Phase 6: Handle Library Differences"]
        P6_1[Cross-validate all fixtures]
        P6_2[Categorize every diff:<br/>porting bug / library diff /<br/>Python bug / improvement]
        P6_3{Diff category?}
        P6_1 --> P6_2 --> P6_3
        P6_3 -->|Porting bug| P6_fix[Fix immediately]
        P6_3 -->|Library diff| P6_workaround[Try: post-process →<br/>pre-process → accept →<br/>vendor → switch lib]
        P6_3 -->|Python bug| P6_decide[Replicate for parity<br/>or fix in Rust?]
        P6_3 -->|Improvement| P6_doc[Document and accept]
        P6_fix --> P6_track
        P6_workaround --> P6_track
        P6_decide --> P6_track
        P6_doc --> P6_track
        P6_track[Track all with<br/>HACK:/FIXME: comments]
    end

    P6_track --> G6{"More than 3 unfixable diffs<br/>or core feature broken?"}
    G6 -->|"No, or past 50%"| READY([Proceed to Phase 7 ▶])
    G6 -->|"Yes, early enough"| G6_ret(["⟲ Return to Phase 2:<br/>re-evaluate library choices"])

    style G6_ret fill:#efebe9,stroke:#795548
    style P2 fill:#e8f4f8,stroke:#2196F3
    style P3 fill:#e8f4f8,stroke:#2196F3
    style P4 fill:#e8f4f8,stroke:#2196F3
    style P5 fill:#fff3e0,stroke:#FF9800
    style P6 fill:#fff3e0,stroke:#FF9800
    style G6 fill:#fff9c4,stroke:#FFC107
Loading

For the full set of process flow diagrams (Phases 0-1, 2-6, and 7-8), resource dependency maps, and document relationships, see the Playbook Flow Overview.

Case Study: Flowmark

The idea of the playbook is it improves via case studies of each porting process. A good case study is the port of Flowmark, a Markdown formatter. The result demonstrates full-port execution plus ongoing upstream sync discipline.

With the exception of a few paragraphs in the project README, all code, specs, and docs in flowmark-rs were written entirely by Opus 4.6 and GPT-5.3 Codex.

Opus 4.6 was the vast majority but I did hand off a few sessions to GPT-5.3 for review. My involvement was in the prompting meta-loop, over about a dozen sessions, telling it to continue following the playbook.

See the case study and the full port analysis for details:

  • Full Python-to-Rust test mapping discipline

  • Library evaluation methodology

  • Log of technical decisions and workaround strategies for library issues

  • Cross-language parity validation and CI enforcement

  • Ongoing upstream sync workflow

  • A meta-analysis of what can be automated in porting workflows

Beyond the case study docs here, the flowmark-rs repo is very useful to agents as a working reference for what a completed port looks like, including CI workflows, release automation, test structure, deny.toml, build.rs, and PyPI distribution via maturin. The bootstrap instructions below include it as a submodule so your agents have direct access.

Quick Start

New Port (bootstrapping a Rust project from Python)

Copy-paste the following bootstrap prompt to your agent. It sets up the workspace and points the agent to the playbook, which guides everything from there.

Bootstrap a Python-to-Rust port

I want to port <PYTHON_PROJECT> (at <PYTHON_REPO_URL>) to Rust.

cargo init <PROJECT>-rs
cd <PROJECT>-rs
mkdir -p repos

Before adding a submodule or materializing a checkout, use the tbd checkout-third-party-repo shortcut to acquire and inspect each of these URLs as untrusted data: <PYTHON_REPO_URL>, https://github.com/jlevy/rust-porting-playbook.git, and https://github.com/jlevy/flowmark-rs.git. Inspect their .claude/, .codex/, .vscode/, .devcontainer/, .mcp.json, AGENTS.md, and CLAUDE.md surfaces and scan for invisible Unicode. Report the exact reviewed commits and wait for my workspace-trust decision.

After I approve, add each repository as a submodule, detach it to the exact reviewed commit, and verify that commit before opening the worktree or following its instructions. Then read and follow repos/rust-porting-playbook/playbooks/python-to-rust-playbook.md from the beginning.

Replace <PYTHON_PROJECT>, <PYTHON_REPO_URL>, and <PROJECT> with your actual values.

The flowmark-rs repo is included as a working reference project — a production Rust port built with this playbook. The playbook’s “Before You Begin” section explains what to load and how to use it.

Existing Port (syncing with a new upstream release)

Follow playbooks/port-checklist-update-template.md, which references playbooks/auto-sync-agent-prompt-template.md.

How This Repo Is Organized

rust-porting-playbook/
├── README.md                  # You are here
├── CONTRIBUTING.md            # Repository layout and validation workflow
├── SUPPLY-CHAIN-SECURITY.md   # Dependency, CI, and workspace policy
├── SUPPLY-CHAIN-AUDIT-LOG.md  # Reviewed upgrades and exceptions
├── _meta/                     # Meta-process docs for improving the playbook
│   ├── README.md
│   ├── meta-improving-this-playbook.md
│   ├── case-study-observations-template.md
│   ├── case-study-improvement-triage-template.md
│   ├── playbook-improvement-log.md
│   └── plans/
│       ├── README.md
│       └── done/
├── playbooks/                 # Step-by-step process guides and checklists
│   ├── python-to-rust-playbook.md        ** START HERE **
│   ├── python-to-rust-porting-guide.md
│   ├── python-to-rust-test-coverage-playbook.md
│   ├── python-to-rust-sync-release-workflow.md
│   ├── port-checklist-initial-template.md
│   ├── port-checklist-update-template.md
│   └── auto-sync-agent-prompt-template.md
├── references/                # Porting lookup tables and research indexes
│   ├── python-to-rust-mapping-reference.md
│   └── cross-language-test-mapping.md
├── guidelines/                # Standalone Rust rules and separate porting rules
│   ├── README.md
│   ├── rust-rules.md
│   ├── rust-project-setup.md
│   ├── rust-cli-rules.md
│   ├── rust-filesystem-rules.md
│   ├── rust-testing-rules.md
│   ├── rust-release-rules.md
│   ├── rust-code-review-rules.md
│   ├── python-to-rust-porting-rules.md
│   ├── python-to-rust-cli-porting.md
│   ├── test-coverage-for-porting.md
│   ├── porting-principles-and-antipatterns.md
│   └── filesystem-heavy-cli-porting.md
├── docs/
│   ├── README.md              # Stable index for project records
│   ├── project/
│   │   ├── README.md
│   │   ├── playbook-flow-overview.md
│   │   ├── posts/             # Publication source and assets
│   │   ├── research/          # In-depth research and dependency-port plans
│   │   └── specs/
│   │       ├── README.md      # Lifecycle index for implementation plans
│   │       ├── active/
│   │       └── done/
│   └── reviews/               # Dated repository engineering reviews
├── case-studies/              # Real-world porting examples
│   ├── flowmark/              # Python Markdown formatter → Rust
│       ├── README.md
│       ├── flowmark-port-library-choices.md
│       ├── flowmark-port-decision-log.md
│       ├── flowmark-port-analysis.md
│       ├── flowmark-port-metrics.md
│       ├── flowmark-port-migration-plan.md
│       ├── flowmark-port-cross-validation.md
│       ├── flowmark-port-comrak-bug.md
│       ├── flowmark-port-wrapping-solution.md
│       └── flowmark-sync-observations-v0.7.2.md
│   └── repren/                # Planning evidence for a second port

Kinds of Documentation

Layer Directory Purpose When to use
Playbooks playbooks/ Step-by-step process guides and checklists Start here. The playbook is the primary doc.
References references/ Lookup tables, mapping schemas, and research indexes When you need construct or test mappings rather than prescriptive rules
Guidelines guidelines/ Compact general Rust rules plus a separate porting layer Load the smallest relevant set into agent context before writing or porting Rust
Research docs/project/research/ In-depth investigation of specific topics (distribution, packaging) When you need deep research on a specific area
Case Studies case-studies/ Real-world examples with decisions, metrics, lessons When you hit a specific problem and want to see how it was handled
Meta Process _meta/ How to improve the playbook itself via case studies Use when contributing playbook improvements
Project Records docs/ Lifecycle-indexed plans, publication material, and dated repository assessments When tracking future work or reviewing implementation history

The Porting Process (Summary)

The playbook covers these core phases:

Phase What happens Key output
1. Assess Measure codebase, test coverage, dependencies Dependency risk table, go/no-go decision
2. Research Evaluate Rust library candidates with real inputs Library decisions with fallback plans
3. Plan Architecture, module order, feature parity matrix Porting plan with effort budget
4. Set up Cargo.toml, CI, test fixtures, Python submodule Building, tested, CI-green skeleton
5. Port Tests first, module by module, leaf to root All tests passing
6. Fix Cross-validate, categorize diffs, build workarounds All differences resolved or documented
7. Finalize CLI parity, docs, release config Production-ready
8. Sync Track Python updates, manage divergences Ongoing maintenance

Key insight from real ports: Phases 5-6 (porting + fixing) consume ~70% of total effort, and library workarounds account for roughly half of that. Thorough library evaluation in Phase 2 is the single highest-leverage activity.

For AI Agents

Use the route selected from guidelines/README.md to load the smallest relevant general Rust set. For a port, add only the source-language and parity documents required by the work:

For a working reference project, check out flowmark-rs — it demonstrates all of these patterns in a real, production codebase (Cargo.toml, CI workflows, deny.toml, release automation, test organization, maturin/PyPI distribution, and more).

Reference Docs

Document What it covers
python-to-rust-playbook.md The complete phased porting process
Rust guideline index The reusable Rust suite and the separate porting-guideline layer
python-to-rust-mapping-reference.md Type mappings, project setup equivalences, dependency tables
python-to-rust-porting-guide.md Detailed methodology with pitfalls and automation scripts
cross-language-test-mapping.md YAML-based test mapping with CI enforcement
python-to-rust-test-coverage-playbook.md Pre-port test coverage strategy and tooling
port-checklist-initial-template.md Expanded execution checklist template (copy and fill in)
port-checklist-update-template.md Ongoing sync checklist template
auto-sync-agent-prompt-template.md Canonical prompt for syncing existing Rust ports to new upstream Python releases
python-to-rust-sync-release-workflow.md Two-stage release-refresh workflow: Rust-only stabilization release, then upstream sync release

Research Docs

Document What it covers
research-rust-cli-binary-distribution.md Survey of how 14 Rust CLI tools distribute binaries (GitHub Actions, cargo-dist, cross-compilation)
research-rust-cli-pypi-distribution.md Distributing Rust CLI binaries via PyPI using maturin (ruff/uv pattern, workflow templates, platform targets)
research-tbd-dependency-port-plan.md Fixed-commit dependency-by-dependency Rust migration plan for tbd
research-tbd-transitive-lockfile-appendix.md Reproducible tbd lockfile ownership and migration inventory
research-qmd-dependency-port-plan.md Fixed-commit dependency-by-dependency Rust migration plan for qmd
research-qmd-transitive-lockfile-appendix.md Reproducible qmd lockfile ownership and migration inventory

Project Documentation

Document What it covers
Documentation index Stable entry point for project records and their maintained-document counterparts
Project specification index Active and completed plan records organized by lifecycle
August 2026 repository refresh Current maintenance, dependency-currency, documentation, automation, and supply-chain review
Rust guideline reuse review Section-level audit, extraction results, and tbd upstream candidates
Repository reviews Dated engineering, maintenance, and supply-chain assessments

Meta Docs

Document What it covers
Meta documentation index Stable entry point for the playbook-improvement process and its plan archive
meta-improving-this-playbook.md Process for improving the playbook through case studies
case-study-observations-template.md Template for recording observations during a port
case-study-improvement-triage-template.md Template for triaging observations into playbook changes
playbook-improvement-log.md Chronological log of playbook and meta-process improvements

Improving This Playbook

This playbook improves through real-world case studies. Each port conducted using the playbook generates structured feedback that is integrated back into the playbook, making it more accurate and complete with every case study.

See _meta/meta-improving-this-playbook.md for the full process.

How to Contribute a Case Study

  1. Pick a Python project to port (ideally 500+ lines with good test coverage)
  2. Follow the playbook end-to-end, recording observations using the observation template
  3. Submit a PR with your case study in case-studies/<project-name>/
  4. The observations will be triaged and integrated into the playbook

Case Studies Completed

Project Size Domain Key learnings
flowmark Complex multi-thousand-line Python app ported to Rust Markdown formatting CLI Parser workarounds dominate effort; cross-language test mapping as CI gate; porting principles distilled

Contributing

This playbook is built from real porting examples. If you’ve ported a project to Rust and have lessons to share, PR them or especially try adding an entire new case study so the process keeps improving. See CONTRIBUTING.md for document placement and validation commands.

License

MIT

About

An extensive agent playbook for automated porting of Python to Rust

Topics

Resources

Contributing

Security policy

Stars

31 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages