Skip to main content

untaped-recipe

Install it as part of untaped: uv tool install 'untaped[recipe]' or pip install 'untaped[recipe]'. To add it to an existing install, see Getting started.

untaped recipe applies the same file changes to many directories: add a config file, bump a version in YAML, remove a stale workflow. A recipe is a list of steps; packs bundle recipes with Python hooks. Every change is planned in memory, previewed, and written only after you confirm, with a backup of every file it touches.

Recipes work on plain directories and never commit, push or open pull requests. No recipe step runs a shell command, but pack hooks are Python code that runs on your machine (see Install and manage packs).

Recipe verbs sit directly under untaped recipe; packs, hooks and backups have their own nouns (recipe packs …, recipe hooks …, recipe backups …). The packaged skill is the full reference: applying, packs, tests and backups and authoring.

Set up

Recipes need no setup beyond installing a pack (below). uv must be on your PATH to run pack hooks. Settings such as recipe.library_root (where packs are installed) and hook timeouts are in the configuration reference.

Apply a recipe

untaped recipe apply acme/editorconfig ~/work/api ~/work/web --dry-run
untaped recipe apply acme/editorconfig ~/work/api ~/work/web --preview diff
untaped recipe apply acme/editorconfig ~/work/api ~/work/web

The recipe argument is a unique recipe name, a pack/recipe ref, or a path. A value is a path only when it starts with ./, ../, / or ~, is . or .., or ends in .yml/.yaml. For a local pack directory, pass its path and --recipe NAME.

--dry-run previews without writing; pack hooks still run, because they compute the plan. A target that fails to plan or write changes nothing and is reported; the other targets still run. Within a target, writes are one transaction.

Check for drift in CI

untaped recipe apply acme/editorconfig ~/work/api --check

--check writes nothing, asks nothing and makes no backup, and exits 3 when any target would change.

Apply to every repo of a workspace

--stdin reads target paths, or records with a target_path:

untaped workspace status NAME --format pipe \
  | untaped recipe apply acme/editorconfig --stdin --dry-run

With --stdin the confirmation reads the terminal. Without one, pass --yes, --dry-run or --check.

Inputs

Recipes declare inputs. Give them values with --var KEY=VALUE or YAML files, the same flags awx test uses for suite variables:

untaped recipe apply acme/codeowners ~/work/api --vars-file base.yml --var owner=@acme/platform
untaped recipe apply acme/readme --stdin --input-from 'service={{ target.name }}' < dirs.txt

--var wins over every file, and a later file over an earlier one. --vars-file values are YAML, so quote version-like strings (python_version: "3.10"). --input-from derives a value per target. A required input still missing is prompted for at a terminal; otherwise the run fails naming it. Sensitive inputs show as *** in rows, previews and backups, and their targets show no diff. The full precedence and prompt rules are in the apply reference.

Install and manage packs

Installing a pack installs code: its hooks run on your machine with no sandbox, including during apply --dry-run and --check, since hooks compute the planned changes. Inspect a pack before you trust it (recipe packs get, recipe validate, recipe test). Hooks get a reduced environment without your tokens, but they run as you with full file access; the environment list says exactly what they can see.

untaped recipe packs add https://git.example.com/acme/untaped-recipes.git --rev v1.2.0
untaped recipe validate acme
untaped recipe packs sync --all --dry-run
  • A pack must contain a uv.lock and no symlinks. Reinstalling needs --force; local edits to the installed copy also need --discard-edits.
  • packs sync re-fetches packs from the source and --rev recorded at install, so a branch or tag moves forward. It lists the packs whose files would change, with the hook code that changes, and confirms first: review that list as you would a dependency upgrade.
  • recipe validate checks the whole library, or one pack, recipe or path, without importing hook code; any failing check exits 1.

Write a pack

untaped recipe packs init acme
untaped recipe init ./acme/editorconfig
untaped recipe hooks init ./acme/pin_python --kind transform

Each init refreshes the pack's uv.lock, which needs access to a package index. --no-lock skips that, but hooks cannot run until uv lock succeeds.

A pack is a Python project. Its pyproject.toml lists recipes and hooks under [tool.untaped_recipe.recipes] and [tool.untaped_recipe.hooks].

Recipe file

version: 1
description: Add a standard .editorconfig and pin the Python version
inputs:
  python_version:
    type: str
    default: "3.14"
steps:
  - type: template
    template: templates/editorconfig
    dest: .editorconfig
    if_absent: true
  - type: transform
    hook: yaml_edit
    file: .pre-commit-config.yaml
    optional: true
    args:
      edits:
        - op: set
          path: [default_language_version, python]
          value: "python{{ python_version }}"
  - type: remove
    file: .travis.yml

A validate step runs a hook that passes, fails or skips the target; transform rewrites file content through a hook; template, copy and remove render, copy and delete files. Step fields are in the authoring reference. globs has no implicit excludes: add exclude: [".git/**"] when the targets are Git clones.

Hooks

A hook module exports transform(), validate(), or both. hooks init writes a typed stub and a pytest for it. For YAML files, use the built-in yaml_edit hook shown above. Debug one hook without a recipe:

untaped recipe hooks run acme/pin_python --target ~/work/api --file pyproject.toml \
  --var python_version=3.14 --diff

Hooks compute the plan, so they must only read the target tree and their own pack: no writes, no network.

Golden tests

recipe init also creates a test case under tests/RECIPE/CASE/: given/ is the starting directory, expected/ the full expected result (omit it to assert no change), and an optional case.yml sets inputs and expectations.

untaped recipe test ./acme
untaped recipe test acme/editorconfig --update

--update rewrites expected/ from the current plan.

Backups

Each apply writes one backup bundle unless you pass --no-backup.

untaped recipe backups restore latest --dry-run
untaped recipe backups restore latest
untaped recipe backups prune --keep 20 --dry-run

restore refuses to overwrite a file that changed after the backup unless you pass --force. Backups hold file content only, not modes or times.

Output

apply prints one recipe.apply_outcome row per target, with action planned, applied, unchanged, skipped, cancelled or failed; the preview goes to stderr. See Scripting and Exit codes.

See also

Metadata

Release files for untaped-recipe 10.0.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 untaped-recipe 10.0.0
File Size Uploaded Provenance Actions
untaped_recipe-10.0.0.tar.gz 96.4 kB With provenance Details for untaped_recipe-10.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for untaped-recipe 10.0.0
File Interpreter ABI Platform Actions
untaped_recipe-10.0.0-py3-none-any.whl Python 3 none any Details for untaped_recipe-10.0.0-py3-none-any.whl

Total release size: 224.8 kB

Release files / untaped_recipe-10.0.0.tar.gz

Download URL untaped_recipe-10.0.0.tar.gz
Size 96.4 kB
Tags Source
SHA-256 checksum
How to use checksums
e5dda6dbdd7f0dae3c548076f037d3d518661efb237d791f984cd344543d3a2c
BLAKE2b-256 checksum
How to use checksums
c444a4c02407bad4c5f92d72e089de103d74830466b5853f6e6710ea968e4b29
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 2, 2026.

Transparency log

Release files / untaped_recipe-10.0.0-py3-none-any.whl

Download URL untaped_recipe-10.0.0-py3-none-any.whl
Size 128.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b8c88abd72b9186e7d7a8cfb73b2dae123f55e1bfd8c709290debf115e7a7f77
BLAKE2b-256 checksum
How to use checksums
cb2a1448955d8c43fd1fd7068693b1e042f0a922a6c690c310c7163cf1bee4ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Oct 2, 2026.

Transparency log

Security for untaped-recipe 10.0.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 untaped_recipe-10.0.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 Oct 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.

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