Skip to main content

Anvil

                  _ _ 
                 (_) |
  __ _ _ ____   ___| |
 / _` | '_ \ \ / / | |
| (_| | | | \ V /| | |
 \__,_|_| |_|\_/ |_|_|

Create isolated multi-repository workspaces for engineering tasks.

Installation

From PyPI (the published package is still named git-anvil):

uv tool install git-anvil

From GitHub:

uv tool install git+https://github.com/felixscherz/anvil

Both methods install the anvil command. The PyPI package keeps its existing distribution name because anvil belongs to another project.

Getting started

Create a workspace

Provide a target directory and one or more repository specifiers. Each specifier can be a local path to an existing Git repository or any remote URL accepted by git clone.

anvil create --target /tmp/workspaces/feature-abc \
  ~/repos/my-service \
  git@github.com:org/other-service.git

To override the inferred branch name, pass --branch (-b):

anvil create --target /tmp/workspaces/feature-abc --branch my-feature \
  ~/repos/my-service

Anvil will:

  1. Infer the branch name from the target directory name (feature-abc), or use the value of --branch when provided.
  2. For local paths — create a git worktree on a new branch at the tip of the default branch.
  3. For remote URLs — clone the repository and check out a new branch.
  4. Write a manifest to /tmp/workspaces/feature-abc/.anvil/manifest.json.
  5. Write an AGENTS.md at the workspace root describing the workspace layout for coding agents. It points to .anvil/manifest.json as the source of truth for the current repositories, and is removed on clean.
  6. Record the workspace in the nearest dedicated .anvil/workspaces.json inventory.

Example output:

Creating Anvil workspace: /tmp/workspaces/feature-abc
Branch: feature-abc
  + my-service -> /tmp/workspaces/feature-abc/my-service
  + other-service -> /tmp/workspaces/feature-abc/other-service

Created Anvil workspace: /tmp/workspaces/feature-abc
Branch: feature-abc
  - my-service -> /tmp/workspaces/feature-abc/my-service
  - other-service -> /tmp/workspaces/feature-abc/other-service

Clean up a workspace

anvil clean /tmp/workspaces/feature-abc

anvil remove is an alias for anvil clean. Both remove the workspace from workspaces.json after cleanup.

If you are inside the workspace (or any subdirectory of it), the path can be omitted - Anvil walks up from the current directory until it finds an .anvil/manifest.json:

cd /tmp/workspaces/feature-abc
anvil clean

Anvil reads the manifest, prints a summary, and prompts for confirmation before removing everything.

Anvil workspace: /tmp/workspaces/feature-abc
Branch: feature-abc
Repositories (2):
  - my-service (worktree) -> /tmp/workspaces/feature-abc/my-service
  - other-service (clone) -> /tmp/workspaces/feature-abc/other-service
Remove Anvil workspace at /tmp/workspaces/feature-abc containing 2 repositories? [y/N]

Skip the prompt with --yes:

anvil clean /tmp/workspaces/feature-abc --yes

Add a repository to an existing workspace

anvil add --target /tmp/workspaces/feature-abc ~/repos/another-service

Or, from anywhere inside the workspace:

cd /tmp/workspaces/feature-abc
anvil add ~/repos/another-service

Anvil reads the branch name from the existing manifest (feature-abc) and creates the new repository on that same branch. The manifest is updated in place with the new entry appended. Rollback applies only to repos added in the current run - existing workspace members are untouched. clean and run likewise discover the workspace from the current directory when the workspace path / --workspace is omitted.

List workspaces

Create a dedicated .anvil directory in a parent of your workspaces, then run anvil list from anywhere beneath it:

mkdir -p /tmp/workspaces/.anvil
anvil list

Anvil walks upward from the current directory to find the nearest dedicated .anvil directory. A workspace's own .anvil/manifest.json directory is skipped. If there is no dedicated directory, Anvil uses ~/.config/anvil/workspaces.json. For create, add, and remove, inventory selection starts at the workspace's parent directory, so explicit workspace paths update the inventory that contains them. The file records each workspace path, branch, and repository names; add refreshes its entry.

Notes

  • The branch name is derived from the basename of --target. /tmp/workspaces/feature-abc → feature-abc. Pass --branch/-b to override it; the value is sanitized the same way as the inferred name.
  • anvil add reads the branch name from the existing manifest - the target directory name is irrelevant.
  • add, clean, and run infer the workspace by walking up from the current directory when the workspace path / --target / --workspace is omitted. create always requires --target because it creates a new workspace.
  • The same branch name is created in every repository in the workspace - this is expected and correct.
  • If any repository fails during create or add, Anvil rolls back only the repos created in that run.
  • Anvil will refuse to proceed if the target is non-empty, if a derived branch already exists, or if two repositories share the same derived name.

Metadata

Release files for git-anvil 0.4.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 git-anvil 0.4.0
File Size Uploaded
git_anvil-0.4.0.tar.gz 46.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for git-anvil 0.4.0
File Interpreter ABI Platform
git_anvil-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 68.2 kB

Release files / git_anvil-0.4.0.tar.gz

Download URL git_anvil-0.4.0.tar.gz
Size 46.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f88b87646933dc5a1c589a8d6e2071575b92d1d880a5a3948f0c40acc959686e
BLAKE2b-256 checksum
How to use checksums
4394edcfd961ce3601e7e83496c1eca70cf67dea885453acd92fe29cb311f6d7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / git_anvil-0.4.0-py3-none-any.whl

Download URL git_anvil-0.4.0-py3-none-any.whl
Size 21.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
75ebb2a9943a70e192ef155eaba2426041bc69babdbbe4dce6c19dab5efc44de
BLAKE2b-256 checksum
How to use checksums
f708c096a0126e243bf6f7c9c0a2278747e793a5a7c83a67826e17d137d045c2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.0

2 release files

0.2.0

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