Skip to main content

kopya

Record your app's real API calls once. Replay them offline, forever.

kopya (Filipino for "copy") is a single static binary that sits between your app and the internet. Run your test suite once against the real API, and every call after that is served from a fixture file — no network, no API bill, no flakes.

$ kopya record -- pytest tests/
...
kopya recorded 47 calls → .kopya/fixtures.json
  Secrets were redacted. Review the file before committing it.

$ kopya replay -- pytest tests/
kopya loaded 47 recorded calls from .kopya/fixtures.json
...
kopya replayed 47 calls · 0 live
  Saved ~128,400 tokens and 94.2s.

Your application code does not change. No mock library, no dependency injection, no monkeypatching.

Why

Tests that hit OpenAI, Anthropic, Stripe or any other third-party API are slow, nondeterministic, and cost real money. The existing answers all have a catch: language -bound mock libraries only cover one runtime, and the proxy-based tools need Python or a JVM in your CI image.

kopya is one ~7MB binary with no runtime. It boots instantly in a container and works the same for Python, Node, Go, Rust, Ruby, Java or curl.

Install

Whichever ecosystem you already have. All three install the same prebuilt binary; nothing is compiled or downloaded at install time. (The npm package is a small Node shim that execs the binary, so npx invocations pay Node's startup once.)

npx @kopya/cli --help     # Node
uvx kopya --help          # Python
cargo install kopya       # Rust

(The npm package is scoped @kopya/cli; the installed command is still kopya.)

Or grab a binary from the releases page. Prebuilt for macOS (Intel and Apple Silicon), Linux (x64 and arm64, statically linked against musl) and Windows x64.

How it works

kopya runs an HTTP/HTTPS proxy on 127.0.0.1 and launches your command with the proxy and CA environment variables already set:

Variable Why
HTTP_PROXY / HTTPS_PROXY Routes traffic through kopya
NODE_USE_ENV_PROXY=1 Node's built-in fetch ignores HTTP_PROXY without it
NODE_EXTRA_CA_CERTS Node uses its own CA bundle, not the system keychain
REQUESTS_CA_BUNDLE Python requests / httpx use certifi
SSL_CERT_FILE, CURL_CA_BUNDLE OpenSSL and curl

This matters: trusting a root CA in the system keychain is not enough for Node, Python or Java. Setting these per-process is what makes "zero code changes" actually true. If you point an already-running process at kopya instead, run kopya ca trust and export the variables it prints.

Commands

kopya record -- <command>     # run <command>, save its outbound calls
kopya replay -- <command>     # run <command> against the saved calls
kopya ca path                 # print the root CA path (creates it on first run)
kopya ca trust                # install the root CA into the system trust store
kopya ca untrust              # remove it

Useful flags:

  • --out / --in — fixture file path (default .kopya/fixtures.json)
  • --port — proxy port (default 8888; 0 picks a free one)
  • --append — keep calls already in the fixture that this run did not re-record
  • --no-proxy — hosts to reach directly (default localhost,127.0.0.1,::1)
  • --allow-live — let unmatched requests reach the network instead of failing
  • --realtime — reproduce the original timing of recorded streams
  • --no-redact — keep credentials in the fixture. Don't.

Loopback is excluded by default, so a local test server, a testcontainer or a WebDriver on 127.0.0.1 is not swept into the fixture. Pass --no-proxy "" to record those too.

Running kopya record or kopya replay with no -- command starts the proxy in the foreground so you can point an existing process at it.

Streaming responses

text/event-stream responses — every streaming LLM API — are recorded frame by frame, with the offset each frame arrived at, and replayed with those boundaries intact. A recording is passed through to your app live as it happens, so the run you record behaves exactly like an unproxied one.

By default replay emits the frames as fast as the client will take them, because the point of replay is to make a slow test fast:

recorded   7 frames over 1015ms
replayed   7 frames over 7ms          # 145x faster, same frames
replayed   7 frames over 1012ms       # with --realtime

Use --realtime when the thing under test is the streaming behaviour itself — time-to-first-token, incremental rendering, or a client-side timeout.

Token usage is parsed out of the stream — OpenAI's usage.total_tokens, Anthropic's split input_tokens/output_tokens, and Gemini's usageMetadata — so the summary can report what a replayed run would have cost.

A stream that never reached its end, because the client hung up or the command exited mid-flight, is recorded with "truncated": true and called out in the summary. It will replay short, so re-record it if a test depends on the end.

Only text/event-stream is streamed. Other chunked responses — NDJSON, long polls, large downloads — are buffered whole before being passed on.

Strict by default

In replay, a request with no recorded match returns 502 and fails the run, even if your test swallowed the error. A green replay run therefore proves the suite is genuinely hermetic. Pass --allow-live when you want the softer behaviour.

Fixtures are meant to be committed

The fixture file is the artifact your team shares, so it is designed to survive code review:

  • Headers are stored in sorted maps and bodies as plain text, so diffs stay readable
  • Credentials are redacted before anything touches disk — Authorization, Cookie, x-api-key and friends, plus bare sk-/ghp_/AKIA-style tokens found in bodies, form fields, and query strings like Google's ?key=
  • Binary payloads are dropped rather than base64-inflating the file

Redaction only ever touches the stored copy. Match keys are always derived from the request as it arrived on the wire, so redacting a request body cannot stop it matching on replay.

Repeat calls to the same endpoint are kept in order and replayed in order, so polling and pagination work. Once a sequence is used up its last response repeats.

Always read a fixture before committing it the first time. Redaction is conservative by design, not a guarantee.

Status

Early. 0.2 covers HTTP/1.1 record and replay, including server-sent event streams, with redaction, response decompression and strict matching.

Fixtures are format version 2. Version 1 files do not load — kopya will say so and ask you to re-record.

Roadmap: HTTP/2, a GitHub Action, Homebrew, request-count assertions, and latency + error injection.

Not planned for 0.1: gRPC, WebSocket, a GUI, declarative YAML rule files.

License

Apache License 2.0 — © 2026 ThinkGrid Labs

Metadata

Release files for kopya 0.2.0

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

Built distributions (wheels)

Table of built distributions (wheels) for kopya 0.2.0
File
kopya-0.2.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
kopya-0.2.0-py3-none-manylinux_2_39_x86_64.whl Python 3 none Linux glibc 2.39+ x86-64 Details
kopya-0.2.0-py3-none-manylinux_2_39_aarch64.whl Python 3 none Linux glibc 2.39+ ARM64 Details
kopya-0.2.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
kopya-0.2.0-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details

Total release size: 17.0 MB

Release files / kopya-0.2.0-py3-none-win_amd64.whl

Download URL kopya-0.2.0-py3-none-win_amd64.whl
Size 3.3 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
2f9a8977bc60a4b50cd61ce7e1604206d4294c9229af06c12fa3bd4eeb16c349
BLAKE2b-256 checksum
How to use checksums
a39ec0d4db88305341bd91f0430b3f4ca43068a6f4e16efdf5f281ac08e4a552
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 6, 2026.

Transparency log

Release files / kopya-0.2.0-py3-none-manylinux_2_39_x86_64.whl

Download URL kopya-0.2.0-py3-none-manylinux_2_39_x86_64.whl
Size 3.6 MB
Tags Linux glibc 2.39+ x86-64 Python 3
SHA-256 checksum
How to use checksums
2c03fbcac59bcc7f763a52f6c5f17cfd715cfaf9e852f1165b4b34e8c2aace21
BLAKE2b-256 checksum
How to use checksums
8dce6270d2942b3fe2f30fac32f65bb91e3c5c9135aa0bb8740290174868b60e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 6, 2026.

Transparency log

Release files / kopya-0.2.0-py3-none-manylinux_2_39_aarch64.whl

Download URL kopya-0.2.0-py3-none-manylinux_2_39_aarch64.whl
Size 3.3 MB
Tags Linux glibc 2.39+ ARM64 Python 3
SHA-256 checksum
How to use checksums
a90013987c7d77031a2969640fa058b072fbcef287258a4d435e2e094e264be6
BLAKE2b-256 checksum
How to use checksums
a1893126d50568ba31b905cd2f0e2514a5c76d0debdbf42e3605719934ff5ec3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 6, 2026.

Transparency log

Release files / kopya-0.2.0-py3-none-macosx_11_0_arm64.whl

Download URL kopya-0.2.0-py3-none-macosx_11_0_arm64.whl
Size 3.2 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f733feee9e29fe6ebe7e1b7c73daf61bcfbbc03f3858bfd02561e8a395c4acd8
BLAKE2b-256 checksum
How to use checksums
df1bf578f9a445782b75ea117b0fcd094333be0a5ab2d7a22932bbb929412a1b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 6, 2026.

Transparency log

Release files / kopya-0.2.0-py3-none-macosx_10_12_x86_64.whl

Download URL kopya-0.2.0-py3-none-macosx_10_12_x86_64.whl
Size 3.5 MB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
6b7e38012b9fa7cd097273e5735a448085946a568625fc03e53d0f9653124bd2
BLAKE2b-256 checksum
How to use checksums
4032e66c6309dadb808d1cf98b4a38d801bec927607e7e52cb4a0fcfcb18a00e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

5 release files

0.1.1

5 release files

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