Skip to main content

parityrun

Prove that a rewrite of your app behaves exactly like the original. parityrun records what your app does (every page, form answer, redirect, database row and file it writes) and then checks a new version against that recording: a port from PHP to JavaScript, TypeScript or Rust, a framework upgrade, or simply the next release. With your own AI tool, it can do the port too, turn by turn, until the new version matches.

Install

pip install parityrun

That needs Python 3.10 or newer. Without Python, one line installs everything. On Windows (PowerShell):

powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/arttujan/parityrun/main/install.ps1 | iex"

On macOS and Linux:

curl -LsSf https://raw.githubusercontent.com/arttujan/parityrun/main/install.sh | sh

The installer gets uv, which installs parityrun as a command of its own, with its own Python. Run it again to update (or pip install -U parityrun). Your app still needs whatever it needs to run (for a PHP app: php).

Use it

In your app's folder:

parityrun

That's the one command to remember. The first time, it finds how to start your app and every route in its code, and records what the app does. Every time, it shows where you are and the next command to run:

my-app: 1 of 1 scenario recorded
  3/14 routes visited

Next: parityrun capture
      use the app in your browser: 11 routes not visited yet

parityrun capture opens the app in your browser: use it as people do, then press Finish. Every page shows how many of the app's routes you have visited, and http://127.0.0.1:8000/__parityrun lists the ones still to go. Your app's own files are never changed.

When you have a new version of the app (or let your AI tool make one, below), tell parityrun how to start it in parityrun/impls.json:

"node": {"cwd": "../my-app-js", "cmd": ["node", "server.js"]}

(it gets its port in the PORT environment variable) and check it:

parityrun check --impl node      # every difference, and the parity %; exits 0 only at 100 %
parityrun coverage               # the routes and lines of code no scenario has run yet

Let your AI tool port it

parityrun port --to ts      # TypeScript; or js (JavaScript), rs (Rust)

parityrun writes the new app's starting point beside yours (../my-app-ts), adds it to impls.json and gives your AI tool the task in PORTING.md. Then it goes turn by turn: the tool works, parityrun checks, and the differences of one scenario at a time become the next turn's task, until parity is 100 %. A scenario that stays red is reported, never hidden. By default the tool is Claude Code (claude on PATH, your own account); for another one, give its command: --agent "yourtool --message-file {prompt_file}". The tool may not change your app or the recordings: parityrun puts its own folder back after every turn and stops if your app changes.

What "the same" means

Pages are compared as a browser reads them (indentation and attribute order don't count, text and links do), along with status codes, redirects, database rows and written files; with the built-in stubs, also every prompt sent to an LLM and every call to an outside service. Random ids, tokens and times are normalised. A check proves the new version identical on the recorded scenarios, which visit the routes and (for PHP) run the share of the code that parityrun coverage shows; a path no scenario takes is not proven, so capture until coverage is where you want it.

init recognises PHP (plain, Laravel, Symfony, WordPress), Node.js, Python (Django, Flask, FastAPI) and Rust apps, and PHP libraries: code with no pages, whose scenarios call its functions and classes (fn:, new:) instead of visiting pages, and whose port gets a ready-made shim to fill in. Everything else (settings, scenario files, databases, LLM and outside-service stubs, examples): docs/reference.md.

Licence

MIT. Copyright (c) 2026 Arttu Jantunen.

Metadata

Release files for parityrun 0.6.0

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

Source distribution (sdist)

Source distribution for parityrun 0.6.0
File Size Uploaded Provenance Actions
parityrun-0.6.0.tar.gz 118.7 kB With provenance Details for parityrun-0.6.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for parityrun 0.6.0
File Interpreter ABI Platform Actions
parityrun-0.6.0-py3-none-any.whl Python 3 none any Details for parityrun-0.6.0-py3-none-any.whl

Total release size: 207.7 kB

Release files / parityrun-0.6.0.tar.gz

Download URL parityrun-0.6.0.tar.gz
Size 118.7 kB
Tags Source
SHA-256 checksum
How to use checksums
c922694ebd69c71233b1e67ceceb43e5cee64a7dc48e749089d119b7e7c9d90b
BLAKE2b-256 checksum
How to use checksums
7571db9fabf0ad9363525d52b2058480fb9a88aae725d89d36810d6fa3015c16
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / parityrun-0.6.0-py3-none-any.whl

Download URL parityrun-0.6.0-py3-none-any.whl
Size 89.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
626c92911ea13554877fd28016299804a3a19d58bdb7531cd145a47486e2c91c
BLAKE2b-256 checksum
How to use checksums
7200f09fcae4d3e8bce85d91c9b36071b979e6e01019935c980bc1917200459d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Security for parityrun 0.6.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for parityrun-0.6.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

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.

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 release files Full provenance

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