Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Port To Rust

ASecurity

Run a port into Rust without losing behaviour — define the parity contract, sequence the phases, migrate incrementally behind a stable boundary, and prove parity differentially. Use when moving, porting, rewriting, or migrating an existing codebase into Rust from any language, when deciding how to sequence or scope a rewrite, when a port needs to prove it matches its source, or when a partially-ported system needs both implementations running side by side.

2 stars
0 votes
0 copies
1 views
Added 9/19/2026
developmentrustgobashexpresstestingcode-reviewapi

Works with

cliapi

Security Analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned 9/19/2026

$npx -y skills add rewrite-rs/skills --skill port-to-rust --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Port To Rust?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Port To Rust
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/rewrite-rs-port-to-rust/badge)](https://www.skillsdirectory.com/skills/rewrite-rs-port-to-rust)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: port-to-rust
description: Run a port into Rust without losing behaviour — define the parity contract, sequence the phases, migrate incrementally behind a stable boundary, and prove parity differentially. Use when moving, porting, rewriting, or migrating an existing codebase into Rust from any language, when deciding how to sequence or scope a rewrite, when a port needs to prove it matches its source, or when a partially-ported system needs both implementations running side by side.
---

# Port to Rust

## A port is a behaviour-preserving move, and nothing else

The one rule this skill exists to enforce: during a port, behaviour changes
and code improvements are separate commits, separate reviews, and preferably
separate weeks. A port that also fixes bugs cannot be validated — every
difference is ambiguous between the fix and the regression, and the
differential harness reports both identically. Improvements are written down
as a follow-up list and shipped after parity is proven.

## Start from the parity contract, not from the code

Before any Rust is written, the contract answers four questions: what the
unit of parity is (a CLI invocation, a library function, an HTTP response, a
file artifact); which differences are acceptable (log wording, timing, map
iteration order, float formatting); which are not (any observable output a
caller can branch on); and how parity is measured — the full form in
`PARITY-CONTRACT.md`. A port without a written contract does not have a
definition of done, so it finishes when someone gets tired.

## Five phases, in order

| Phase | Ends when |
|---|---|
| 1. Inventory and seam | The boundary the Rust will live behind is named, and the call sites crossing it are counted |
| 2. Characterize | The existing behaviour is captured as executable tests — against the source implementation, not the intended one |
| 3. Port leaf-first | The lowest-dependency module is in Rust, called through the seam, with both implementations still present |
| 4. Run both | Every input reaching the seam goes through both implementations and the outputs are compared |
| 5. Cut over and delete | Traffic goes to Rust only, and the source implementation is deleted rather than left as a dead fallback |

Phase 2 characterizes the behaviour that exists, bugs included — a test that
asserts the intended behaviour is a bug report disguised as a test. Phase 5
is not optional: a source implementation left in place stops being maintained
and starts being a lie about what runs; the depth on each phase is in
`PHASES.md`.

## Decide the end state before the seam

Three end states; the choice governs everything downstream — the seam, the
contract, the verification, whether bindings are deliverable or scaffold:

| End state | What ships | Bindings |
|---|---|---|
| A. Replacement | A standalone Rust binary or crate; the source implementation is deleted | None, ever. The seam is a process, CLI, or network boundary |
| B. Rust core with a language binding as the product | A Rust engine plus a binding layer that stays — the package the existing consumers import is the deliverable | Permanent. The binding surface is public API: it gets semver, error-type mapping, packaging per platform, and its own docs |
| C. Bindings as scaffold | A standalone Rust binary or crate, reached through a binding layer that is deleted at cut-over | Temporary. Built to be thrown away, and phase 5 is not done until it is gone |

B and C are not the same work, and conflating them is the most expensive
mistake here. Scaffold bindings may be crude because they die; product
bindings are a public surface that outlives the port. Ask which one is
wanted — a user porting a CLI to Rust usually wants A, and handing them a
native extension module answers a question nobody asked. The answer goes in
the parity contract, because it changes what the unit of parity is: for A
the unit is an invocation or a request; for B it is the binding signature
the existing callers already call.

## Pick the incremental strategy from the seam, not from taste

| Strategy | Reach for it when |
|---|---|
| In-place FFI — Rust compiled into the existing build and called across a language boundary | The source language has a cheap, stable FFI story and the seam is a function call |
| Strangler at a process boundary — the Rust binary takes traffic for one route, endpoint, or subcommand at a time | The seam is already a process, socket, or CLI boundary; the languages do not interoperate cheaply |
| Whole-unit replacement | The unit is small enough to port and validate in one sitting — a single CLI tool, one library with a narrow surface |

The FFI mechanics — which crate, which build integration, which header
generator — sit in the per-language skills.

## Parity is proven, not asserted

The evidence is both implementations running over the same inputs and
agreeing. Building that harness is `/rust-testing`; this skill decides what
it has to cover — every input class the contract names, including the error
paths, which are the ones a port silently narrows — and the harness runs in
CI from phase 3 onward, not once at the end, because a difference found six
modules later cannot be attributed.

## What is deliberately not ported

Dead code, workarounds for limitations the source language had and Rust does
not, and abstraction layers that existed to work around the source type
system — each a judgment call written down in the contract, not made
silently mid-file. The inverse error is worse and more common: porting the
abstraction rather than the behaviour, so a five-layer class hierarchy
becomes five Rust traits nobody needs.

## Where the target-side judgment goes

This skill never decides what the Rust should look like. Expression shape is
`/idiomatic-rust`; a `clone` added to satisfy the borrow checker mid-port is
`/ownership-not-clone`; what a fallible path returns is `/rust-errors`;
whether a state should be constructible at all is `/type-driven-design`; the
public surface of the new crate is `/rust-api-design`; async and cancellation
are `/async-rust`; any `unsafe` in an FFI shim is `/unsafe-rust`; the review
pass over a ported diff is `/rust-code-review`. The deferral matters most
here: mid-port is exactly when an agent reaches for `clone` and `unwrap` to
make a translation compile, and those two are the signature of a port that
will read like its source forever. Separate the domain aspects from the
language aspects before writing the Rust; a construct that exists only for
a source-language limitation is not ported; structural similarity to the
source is a signal to re-examine — the entry is in `ANTIPATTERNS.md`.

## Anti-patterns

The top three: transliteration, big-bang rewrite, and improving while
porting; the full list, with the tell for each, is in `ANTIPATTERNS.md`.

## Verification

```bash
cargo test --all-features        # includes the differential and characterization tests
cargo clippy --all-targets --all-features   # add -- -D warnings only if the target repo has no lint config
cargo fmt --check
```

Plus the port-specific check the compiler cannot make: run the differential
harness over the recorded corpus and report the count of inputs compared and
the count of differences, not a pass/fail. Zero differences over nine inputs
is not parity, and a report that hides the denominator hides that.

Attribution

rewrite-rsrewrite-rs
View sourceSee grades on GitHubMore from rewrite-rs →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

285172 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

10311 votes
View all in development →