Skip to main content

skivvy

Try it out in the browser

Declarative integration testing for HTTP APIs.

Skivvy is a tiny, opinionated CLI tool that lets you write API tests as plain JSON files and run them from the terminal. No JS hooks. No GUI. No snapshots. You declare what you expect, and skivvy tells you if reality disagrees — with readable diffs when it does.

It works with REST, GraphQL, and anything else that speaks HTTP. It's built for CI/CD pipelines but just as useful on your local machine.

The core idea

Most API testing tools push you toward one of two bad patterns: writing imperative code in a language you didn't ask for, or snapshot-testing entire responses so every unrelated field change breaks your suite. Skivvy takes a different approach — assert only what you care about. Check the status code, a single field, a subset of a nested object, or the length of a list. Ignore the rest.

{ "url": "/api/items", "response": { "results": [{ "name": "Widget42" }] } }

That's it. That's a test.

▶ Try it in the playground

This works especially well with deeply nested responses like GraphQL, where you can match subsets without caring about the full envelope:

{
  "url": "/graphql",
  "method": "post",
  "body": { "query": "{ posts { id title author { name } tags } }" },
  "match_subsets": true,
  "match_every_entry": true,
  "response": {
    "errors": null,
    "data": {
      "posts": [{ "author": { "name": "$text" }, "tags": "$len_gt 0" }],
      "totalCount": "$gt 0"
    }
  }
}

Every post must have a named author and at least one tag. No GraphQL errors. You don't have to spell out the full response shape.

▶ Try it in the playground

Matchers can reach beyond string comparison — they can enforce constraints across entire collections:

{
  "url": "/users/all",
  "match_every_entry": true,
  "response": {
    "images": [{ "thumbnail": "$valid_url", "id": "$unique" }]
  }
}

Every user's thumbnail is a live, reachable URL. Every ID is unique across the whole list. Two invariants over an arbitrarily large dataset, in a few lines of JSON.

▶ Try it in the playground

What you get

  • All the HTTP plumbing you'd expect — every verb, headers, cookies, file uploads, form data, response chaining via variables and brace expansion
  • Subset matching — assert against deeply nested fields without specifying the full path
  • Built-in matchers$contains, $regexp, $len, $gt, $between, $valid_url, $date, $store/$fetch, approximate values with $~, and more — plus automatic negation ($!contains) for all of them (full list)
  • Custom matchers — drop a Python file with a match(expected, actual) function into a directory and it just works
  • Readable diffs — when a test fails, you see exactly what went wrong in a human-friendly format, with multiple diff styles to choose from
  • Flexible configuration — per-test overrides, environment configs, CLI flags, env vars, with a clear precedence order and sane defaults (full list)
  • Setup & teardown — use directory naming and include/exclude filters to control execution order
  • Deterministic execution — serial by default, predictable every time

Check out the playground for trying it from the comfort of your browser. It provides a basic unix shell, and allows you to edit and run test suites that examplify the list above. It also contains a running server, with responses you can edit as well.

Install

uvx skivvy --version                     # no install needed with uv
pipx run skivvy --version                # or pipx
pip install skivvy                       # or plain pip
docker run --rm hyrfilm/skivvy:examples  # or docker

Reference

  • Settings — all configuration options with defaults and descriptions
  • Matchers — all built-in matchers with usage examples
  • CLI help also includes skivvy --help-settings and skivvy --help-matchers if you want to explore available knobs before enabling more logging

MIT license.

Release files for skivvy 0.811

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

Source distribution (sdist)

Source distribution for skivvy 0.811
File Size Uploaded
skivvy-0.811.tar.gz 31.0 kB Details

Built distribution (wheel)

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

Total release size: 68.9 kB

Release files / skivvy-0.811.tar.gz

Download URL skivvy-0.811.tar.gz
Size 31.0 kB
Tags Source
SHA-256 checksum
How to use checksums
dc0a31a2183d1f9108d16dbed93a60c92a832d5e08f3d183efa79add3cdf7413
BLAKE2b-256 checksum
How to use checksums
ed8a43aebf355c9b231a1b97808871317e399de7504b4f9f81624f27de692f97
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Mar 16, 2026.

Transparency log

Release files / skivvy-0.811-py3-none-any.whl

Download URL skivvy-0.811-py3-none-any.whl
Size 37.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0da2b539655fb568fdab72812fab0cc19c8a321faf41350d1a325001ab189234
BLAKE2b-256 checksum
How to use checksums
01360070a486ac2c64ff2bd6ed85a3835135328c1ca3e2816b61e95c3c6b73e3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Mar 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.811 This release

2 release files

0.810

2 release files

0.802

2 release files

0.801

2 release files

0.800

2 release files

0.710

2 release files

0.709

2 release files

0.708

2 release files

0.707

2 release files

0.706

2 release files

0.705

2 release files

0.704

2 release files

0.702

2 release files

0.701

2 release files

0.620

2 release files

0.517

2 release files

0.516

2 release files

0.512

2 release files

0.510

2 release files

0.509

2 release files

0.504

2 release files

0.402

2 release files

0.401

2 release files

0.400

2 release files

0.300

2 release files

0.234

2 release files

0.233

2 release files

0.232

2 release files

0.231

2 release files

0.61

2 release files

0.60

2 release files

0.23

2 release files

0.22

2 release files

0.21

2 release files

0.20

2 release files

0.19

2 release files

0.18

2 release files

0.17

1 release file

0.16

1 release file

0.15

1 release file

0.14

1 release file

0.13

1 release file

0.12

1 release file

0.11

1 release file

0.5.3

2 release files

0.3.1

2 release files

0.3

2 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