Agent skill

Syrupy

by anam-org in anam-org/metaxy

Use syrupy for pytest snapshot testing to ensure the immutability of computed results, manage snapshots, customize serialization, and handle complex data structures with built-in matchers and filters.

Apache-2.0Auto-check passedTesting & QA

Install Syrupy

skills CLI
$ npx skills add anam-org/metaxy --skill syrupy -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install anam-org/metaxy syrupy --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/anam-org/metaxy.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/syrupy .claude/skills/syrupy && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
syrupy
GitHub stars
124
Token cost
~2.6k tokens
SKILL.md length
795 words
Files
2
Skills in repo
8
Repo updated
First seen
Licence
Apache-2.0

At a glance

Use syrupy for pytest snapshot testing to ensure the immutability of computed results, manage snapshots, customize serialization, and handle complex data structures with built-in matchers and filters.

  • Works in 3 steps: Extensible: Easy to add support for… → Idiomatic: Natural pytest-style… → Sound: Fails tests if snapshots are…
  • Tasks that involve Unit testing
  • SKILL.md covers What is Syrupy?, Core Philosophy, Snapshot Fixture API and Built-in Extensions, plus 6 more sections
  • Calls pytest

What it does

Syrupy is an agent skill from anam-org/metaxy. Use syrupy for pytest snapshot testing to ensure the immutability of computed results, manage snapshots, customize serialization, and handle complex data structures with built-in matchers and filters.

Its SKILL.md is about 2.6k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `EXAMPLES.md`).

It sits in Testing & QA, covering Unit testing. It works with pytest and Python. The repository describes itself as: Pluggable metadata management framework for versioned incremental multimodal data/ML pipelines. The licence is Apache-2.0.

When your agent uses it

  • Tasks that involve Unit testing

Example prompts

  • “/syrupy”

Requirements

  • Python 3

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. Extensible: Easy to add support for custom/unsupported data types
  2. Idiomatic: Natural pytest-style assertions (assert x == snapshot)
  3. Sound: Fails tests if snapshots are missing or different

What it can do on your machine

Read from SKILL.md and the folder at commit 8337842. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • pytest

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • syrupy-project.github.io

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Syrupy loads about 2.6k tokens when it runs. Until then it costs about 52 tokens; SKILL.md has 795 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~52
When it runs · the whole SKILL.md, loaded when a task matches
~2.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from anam-org/metaxy at commit 8337842, republished under its Apache-2.0 licence (© anam-org). 795 words, ~2,607 tokens.

Download SKILL.mdSave it as .claude/skills/syrupy/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
syrupy
description
Use syrupy for pytest snapshot testing to ensure the immutability of computed results, manage snapshots, customize serialization, and handle complex data structures with built-in matchers and filters.

Syrupy - Pytest Snapshot Testing

Syrupy is a zero-dependency pytest snapshot testing plugin that enables asserting the immutability of computed results through simple, idiomatic assertions.

Docs: https://syrupy-project.github.io/syrupy/

What is Syrupy?

Syrupy is a snapshot testing library that:

  • Captures the output/state of code at a point in time
  • Compares future test runs against saved snapshots
  • Automatically manages snapshot files in __snapshots__ directories
  • Integrates naturally with pytest's assertion syntax

Core Philosophy

Three Design Principles:

  1. Extensible: Easy to add support for custom/unsupported data types
  2. Idiomatic: Natural pytest-style assertions (assert x == snapshot)
  3. Sound: Fails tests if snapshots are missing or different

Target Use Case: Testing complex data structures, API responses, UI components, or any computed results that should remain stable over time.

Snapshot Fixture API

Core Methods

The snapshot fixture accepts several options per assertion:

  • matcher: Control how objects are serialized
  • exclude: Filter out properties from snapshots
  • include: Include only specific properties
  • extension_class: Use a different serialization format
  • diff: Capture only differences from a base
  • name: Custom name for the snapshot
Usage with Options
python
assert data == snapshot(matcher=my_matcher, exclude=my_filter, name="custom_name")

Built-in Extensions

Syrupy provides several snapshot extensions for different use cases:

AmberSnapshotExtension (Default)
  • Human-readable format
  • Stores all snapshots in .ambr files
  • Supports all Python built-in types
  • Custom object representation via __repr__
JSONSnapshotExtension
  • Stores snapshots as JSON files (.json extension)
  • Useful for API responses and complex data structures
  • Machine-readable format
  • Import from syrupy.extensions.json

Usage Example:

python
import pytest
from syrupy.extensions.json import JSONSnapshotExtension


@pytest.fixture
def snapshot_json(snapshot):
    return snapshot.use_extension(JSONSnapshotExtension)


def test_api_call(client, snapshot_json):
    resp = client.post("/endpoint")
    assert resp.status_code == 200
    assert snapshot_json == resp.json()

Handling Dynamic Data in JSON:

python
from datetime import datetime
from syrupy.matchers import path_type


def test_api_call(client, snapshot_json):
    resp = client.post("/user", json={"name": "Jane"})
    matcher = path_type({"id": (int,), "registeredAt": (datetime,)})
    assert snapshot_json(matcher=matcher) == resp.json()
SingleFileSnapshotExtension
  • One file per snapshot
  • Configurable file extensions
  • Useful for binary data or large snapshots
PNGSnapshotExtension
  • For image snapshot testing
  • Compares PNG image data
SVGSnapshotExtension
  • For SVG vector graphics
  • Text-based comparison of SVG content

Matchers

Matchers control how specific values are serialized during snapshot creation.

path_type

Match specific paths in data structures to types:

python
from syrupy.matchers import path_type
import datetime

matcher = path_type({"date_created": (datetime,), "user.id": (int,), "nested.*.timestamp": (datetime,)})
path_value

Match paths and replace with specific values:

python
from syrupy.matchers import path_value

matcher = path_value({"id": "REDACTED_ID", "token": "***"})

Filters

Filters control which properties are included/excluded from snapshots.

Custom Exclude Function

The exclude parameter accepts a custom filter function with this signature:

python
def my_filter(prop, path):
    """
    Args:
        prop: The current property (any hashable value: int, str, object, etc.)
        path: Ordered sequence of traversed locations, e.g.,
              (("a", dict), ("b", dict)) when navigating {"a": {"b": {"c": 1}}}

    Returns:
        True to exclude the property, False to include it
    """
    return should_exclude

Example:

python
def limit_foo_attrs(prop, path):
    allowed_attrs = {"only", "serialize", "these", "attrs"}
    return isinstance(path[-1][1], Foo) and prop in allowed_attrs


def test_bar(snapshot):
    actual = Foo(...)
    assert actual == snapshot(exclude=limit_foo_attrs)
props

Filter by property names (shallow):

python
from syrupy.filters import props

# Exclude specific properties
exclude = props("id", "timestamp", "random_value")

# Include only specific properties
include = props("name", "type", "data")

# Works with indexed iterables
exclude = props("id", "1")  # Excludes "id" and index 1
paths

Filter by full property paths using dot-delimited strings:

python
from syrupy.filters import paths

# Exclude nested paths
exclude = paths("user.password", "response.headers.authorization", "items.*.id")

# Works with list indices
exclude = paths("date", "list.1")

CLI Options

Syrupy adds several pytest command-line options:

  • --snapshot-update: Update snapshots with current values
  • --snapshot-warn-unused: Warn about unused snapshots
  • --snapshot-details: Show detailed snapshot information
  • --snapshot-default-extension: Change default extension class
  • --snapshot-no-colors: Disable colored output

Advanced Configuration

Custom Snapshot Names
python
def test_multiple_cases(snapshot):
    assert case_1 == snapshot(name="case_1")
    assert case_2 == snapshot(name="case_2")

Note: Custom names must be unique within a test function.

Persistent Configuration

Create a snapshot instance with default values:

python
def test_api_responses(snapshot):
    api_snapshot = snapshot.with_defaults(
        extension_class=JSONSnapshotExtension, exclude=props("timestamp", "request_id")
    )

    assert response1 == api_snapshot
    assert response2 == api_snapshot  # Uses same defaults
Custom Extensions

Create custom snapshot serializers by extending AbstractSnapshotExtension:

python
from syrupy.extensions.base import AbstractSnapshotExtension


class MyExtension(AbstractSnapshotExtension):
    def serialize(self, data, **kwargs):
        # Custom serialization logic
        return str(data)

    def matches(self, *, serialized_data, snapshot_data):
        # Custom comparison logic
        return serialized_data == snapshot_data

Snapshot Lifecycle

Creation Flow
  1. Run test without existing snapshot
  2. Test fails with "snapshot does not exist"
  3. Run with --snapshot-update to create
  4. Snapshot file created in __snapshots__/
  5. Commit snapshot to version control
Update Flow
  1. Code changes cause snapshot mismatch
  2. Test fails showing difference
  3. Review changes to ensure correctness
  4. Run with --snapshot-update if changes are expected
  5. Commit updated snapshot
Cleanup

Remove unused snapshots:

bash
pytest --snapshot-update --snapshot-warn-unused

Data Type Support

Show full SKILL.md (323 more words)Show less
Built-in Types

All Python built-in types are supported:

  • Primitives: int, float, str, bool, None
  • Collections: list, tuple, set, dict
  • Complex: datetime, bytes, custom objects (via __repr__)
Custom Objects

Options for custom object snapshots:

  1. Override __repr__ method
  2. Use custom matcher
  3. Create custom extension
  4. Use exclude/include filters

Best Practices

DO
  1. Commit snapshots to version control: They're part of your test suite
  2. Review snapshot changes carefully: Ensure changes are intentional
  3. Use meaningful test names: Helps identify snapshot purpose
  4. Keep snapshots focused: Test one thing per snapshot
  5. Use matchers for non-deterministic data: Dates, IDs, timestamps
DON'T
  1. Don't snapshot entire responses blindly: Filter out volatile data
  2. Don't ignore snapshot changes: They indicate behavior changes
  3. Don't use generic test names: Makes debugging harder
  4. Don't snapshot huge data structures: Use filters or separate tests
  5. Don't update snapshots without review: Verify changes are correct

Common Patterns

API Response Testing

Use JSON extension with filters:

python
@pytest.fixture
def api_snapshot(snapshot):
    return snapshot.use_extension(JSONSnapshotExtension).with_defaults(
        exclude=props("timestamp", "request_id", "session")
    )
Dynamic Data Handling

Use matchers for non-deterministic values:

python
from syrupy.matchers import path_type
import uuid
import datetime

assert response == snapshot(
    matcher=path_type(
        {
            "id": (uuid.UUID,),
            "created_at": (datetime.datetime,),
            "*.timestamp": (datetime.datetime,),
        }
    )
)
Diff-Based Snapshots

Capture only changes from a baseline:

python
def test_incremental_changes(snapshot):
    baseline = {"config": {...}}
    modified = apply_changes(baseline)

    assert modified == snapshot(diff=baseline)

Important Constraints

  1. Python/pytest versions: Requires Python 3.10+ and pytest 8+
  2. Snapshot immutability: Never edit snapshot files manually
  3. Name uniqueness: Custom snapshot names must be unique per test
  4. Path separators: Use dots for nested paths in filters/matchers
  5. Zero dependencies: Syrupy has no external dependencies

Troubleshooting

Common Issues
  1. Snapshot not found: Run with --snapshot-update
  2. Unexpected differences: Check for non-deterministic data
  3. Large diffs: Use filters to focus on relevant data
  4. Flaky tests: Use matchers for dynamic values
  5. Merge conflicts: Update snapshots after resolving
Debug Options
  • Use --snapshot-details for verbose output
  • Check __snapshots__/ directory for actual files
  • Use exclude to isolate problematic fields
  • Test with smaller data sets first

Migration from Other Libraries

From pytest-snapshot
  • Similar API, minimal changes needed
  • Update import statements
  • Regenerate snapshots
From snapshottest
  • Change snapshot.assert_match() to assert x == snapshot
  • Update fixture name if customized
  • Regenerate all snapshots

© anam-org, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file in .claude/skills/syrupy of anam-org/metaxy.

  • SKILL.md
  • EXAMPLES.md

Open the folder on GitHubat commit 8337842

Compare with similar skills

Syrupy next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Syrupy compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Syrupy this skillanam-org/metaxy124—~2.6kAutomated safety check: PassApache-2.0
Adk Verify Snippetsgoogle/adk-python22k—~1.4kAutomated safety check: PassApache-2.0
Hermetic Python Unit TestsdimensionalOS/dimos4.6k—~1.4kAutomated safety check: PassCustom licence
ONNX Runtime Test Runnermicrosoft/onnxruntime22k—~1.8kAutomated safety check: PassMIT
Simple Modern Uvjlevy/simple-modern-uv301—~1.9kAutomated safety check: PassMIT
Test Coverage Reviewareed1192/finance-news-aggregator149—~2.6kAutomated safety check: PassMIT

Similar skills

  • Adk Verify Snippets

    google/adk-python

    Official

    Checks that every Python code block in a Markdown file actually compiles and runs, by extracting each block to a temporary file, executing it in an isolated subprocess, and writing a pass/fail…

    22k GitHub stars~1.4k tokensUpdated today
    Testing & QAAuto-check passed
  • Hermetic Python Unit Tests

    dimensionalOS/dimos

    Rules for writing, fixing and reviewing pytest unit tests that are hermetic: behavior-focused, deterministic, isolated and cheap to run.

    4.6k GitHub stars~1.4k tokensUpdated today
    Testing & QAAuto-check passed
  • ONNX Runtime Test Runner

    microsoft/onnxruntime

    Official

    Runs and debugs ONNX Runtime tests: Google Test executables for C++ and unittest or pytest for Python, with filters and build-directory guidance.

    22k GitHub stars~1.8k tokensUpdated today
    Testing & QAAuto-check passed
  • Simple Modern Uv

    jlevy/simple-modern-uv

    Start, selectively modernize, fully migrate, or update Python projects using simple-modern-uv practices: uv, ruff, BasedPyright, pytest, GitHub Actions CI, and tag-driven PyPI publishing.

    301 GitHub stars~1.9k tokensUpdated 1 mo ago
    Testing & QAAuto-check passed
  • Test Coverage Review

    areed1192/finance-news-aggregator

    Audit, plan, write, and verify unit tests for Python projects using pytest.

    149 GitHub stars~2.6k tokensUpdated 5 mo ago
    Testing & QAAuto-check passed
  • Official

    Runs the ONNX Runtime transformers Python tests against a GPU wheel and proves the cuDNN flash attention path was used rather than a silent fallback.

    22k GitHub stars~2.9k tokensUpdated today
    Testing & QAAuto-check passed

More from anam-org/metaxy

All 8 skills in this repo
  • Metaxy

    anam-org/metaxy

    This skill should be used when the user asks to "define a feature", "create a BaseFeature class", "track feature versions", "set up metadata store", "field-level lineage", "FieldSpec", "FeatureDep"…

    124 GitHub stars~1.5k tokensUpdated 9 days ago
    Auto-check passed
  • Tach

    anam-org/metaxy

    This skill should be used when the user asks to "add a tach module", "configure tach layers", "define module boundaries", "set up interfaces", "run tach check", "check module boundaries", "tach…

    124 GitHub stars~1.2k tokensUpdated 9 days ago
    Auto-check passed
  • Claude Improve Config

    anam-org/metaxy

    Self-reflect on the current session to identify mistakes and propose improvements to .claude configuration (CLAUDE.md, hooks, skills).

    124 GitHub stars~1k tokensUpdated 9 days ago
    Auto-check passed
  • Docs Page Frontmatter

    anam-org/metaxy

    Write YAML front matter for documentation pages with appropriate titles and descriptions for social cards.

    124 GitHub stars~948 tokensUpdated 9 days ago
    Auto-check passed
  • Hypothesis

    anam-org/metaxy

    Use Hypothesis for property-based testing to automatically generate comprehensive test cases, find edge cases, and write more robust tests with minimal example shrinking.

    124 GitHub stars~1.7k tokensUpdated 9 days ago
    Auto-check passed
  • Narwhals

    anam-org/metaxy

    Effectively use Narwhals to write dataframe-agnostic code that works seamlessly across multiple Python dataframe libraries.

    124 GitHub stars~3.3k tokensUpdated 9 days ago
    Auto-check passed

Works with

Categories

Questions about Syrupy

What does Syrupy do?

Use syrupy for pytest snapshot testing to ensure the immutability of computed results, manage snapshots, customize serialization, and handle complex data structures with built-in matchers and filters. Syrupy is an agent skill from anam-org/metaxy. Use syrupy for pytest snapshot testing to ensure the immutability of computed results, manage snapshots, customize serialization, and handle complex data structures with built-in matchers and filters.

When should I use Syrupy?

Syrupy fits situations like: tasks that involve Unit testing.

How do I install Syrupy in Claude Code?

Run `npx skills add anam-org/metaxy --skill syrupy -a claude-code`. Or copy the skill folder (.claude/skills/syrupy in anam-org/metaxy) into .claude/skills/syrupy in your project. Claude Code loads it when a task matches its description.

How do I install Syrupy in Codex?

Run `npx skills add anam-org/metaxy --skill syrupy -a codex`. Or copy the skill folder (.claude/skills/syrupy in anam-org/metaxy) into .agents/skills/syrupy in your project. Codex loads it when a task matches its description.

Can I use Syrupy in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add anam-org/metaxy --skill syrupy -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/syrupy, .gemini/skills/syrupy, .github/skills/syrupy and .opencode/skills/syrupy in your project.

What does Syrupy need to run?

Going by SKILL.md and its folder, Syrupy needs the command-line tools its instructions call (pytest). Our summary lists: Python 3.

Does Syrupy access the network?

SKILL.md names 1 domain. As links in the text: syrupy-project.github.io. This is read from the text; nothing was executed.

Is Syrupy safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Syrupy use?

Syrupy is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Syrupy use?

About 2.6k tokens (SKILL.md is roughly 10k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Syrupy?

Skills that share tags, products or a category with Syrupy: Adk Verify Snippets (google/adk-python, 22k stars), Hermetic Python Unit Tests (dimensionalOS/dimos, 4.6k stars), ONNX Runtime Test Runner (microsoft/onnxruntime, 22k stars) and Simple Modern Uv (jlevy/simple-modern-uv, 301 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Syrupy?

anam-org (a GitHub organization) maintains it in anam-org/metaxy, which has 124 GitHub stars. The repository holds 8 skills in this directory. The repository was last updated on September 30, 2026.

Source: anam-org/metaxy on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.