Anvil
█████╗ ███╗ ██╗██╗ ██╗██╗██╗
██╔══██╗████╗ ██║██║ ██║██║██║
███████║██╔██╗ ██║██║ ██║██║██║
██╔══██║██║╚██╗██║╚██╗ ██╔╝██║██║
██║ ██║██║ ╚████║ ╚████╔╝ ██║███████╗
╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═══╝ ╚═╝╚══════╝
Create isolated multi-repository workspaces for engineering tasks.
Installation
From PyPI:
uv tool install git-anvil
From github:
uv tool install git+https://github.com/felixscherz/git-anvil
This installs a git-anvil executable, which Git exposes as the git anvil subcommand. The examples below use git anvil; you can also invoke git-anvil directly.
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.
git 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):
git anvil create --target /tmp/workspaces/feature-abc --branch my-feature \
~/repos/my-service
Anvil will:
- Infer the branch name from the target directory name (
feature-abc), or use the value of--branchwhen provided. - For local paths — create a
git worktreeon a new branch at the tip of the default branch. - For remote URLs — clone the repository and check out a new branch.
- Write a manifest to
/tmp/workspaces/feature-abc/.anvil/manifest.json. - Write an
AGENTS.mdat the workspace root describing the workspace layout for coding agents. It points to.anvil/manifest.jsonas the source of truth for the current repositories, and is removed onclean.
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
git anvil clean /tmp/workspaces/feature-abc
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
git 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:
git anvil clean /tmp/workspaces/feature-abc --yes
Add a repository to an existing workspace
git anvil add --target /tmp/workspaces/feature-abc ~/repos/another-service
Or, from anywhere inside the workspace:
cd /tmp/workspaces/feature-abc
git 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.
Notes
- The branch name is derived from the basename of
--target./tmp/workspaces/feature-abc→feature-abc. Pass--branch/-bto override it; the value is sanitized the same way as the inferred name. git anvil addreads the branch name from the existing manifest - the target directory name is irrelevant.add,clean, andruninfer the workspace by walking up from the current directory when the workspace path /--target/--workspaceis omitted.createalways requires--targetbecause 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
createoradd, 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.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| git_anvil-0.3.0.tar.gz | 43.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| git_anvil-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 63.0 kB
Release files / git_anvil-0.3.0.tar.gz
| Download URL | git_anvil-0.3.0.tar.gz |
|---|---|
| Size | 43.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8fdd22d724574400f7bfd0b90aa74471281e5d2594f72d33f8a09d349a625b24
|
|
BLAKE2b-256 checksum How to use checksums |
bbcb21b27577f9af2741e02ecd1149fc9b2e647865a6d4c27d73edba88a5ae61
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","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.3.0-py3-none-any.whl
| Download URL | git_anvil-0.3.0-py3-none-any.whl |
|---|---|
| Size | 19.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8caeb15e723b06f846b2e0cb5018fc3b160dabd19113b7dff462519158c11bb6
|
|
BLAKE2b-256 checksum How to use checksums |
57290e106f5642ad44d2a1f2da40c3d8cceaf8f001f9b147be926272bbd30e53
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","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}
|