git-worktree-env (wte)
Per-worktree ports, local secrets, and development environment setup for Git.
wte makes linked worktrees runnable without giving every checkout the same
hard-coded ports or copying secrets into Git. A project profile identifies one
dedicated main worktree; every linked worktree created from it receives a
sticky port block and its declared local configuration.
Features
- Allocates contiguous, machine-wide port blocks with file locking.
- Keeps allocations stable for the lifetime of a worktree path.
- Recognizes linked and agent-created worktrees through their main worktree.
- Symlinks secrets from files outside the repository.
- Generates complete per-worktree configuration files from port templates.
- Starts optional dependency setup tasks after checkout without blocking Git.
- Preserves repository hooks behind a global hook dispatcher.
Requirements
- macOS or Linux
- Python 3.9+
- Git
Windows is not currently supported because wte uses POSIX file locks, symlinks, and Bash hooks.
Installation
With uv (recommended):
uv tool install git-worktree-env
From a source checkout:
uv tool install --editable .
pipx install git-worktree-env is also supported.
Quick start
wte setup
cp ~/.config/wte/project.example.yaml.template ~/.config/wte/my-project.yaml
$EDITOR ~/.config/wte/my-project.yaml
cd /path/to/a/linked-worktree
wte sync
wte doctor
Each project must have a dedicated main worktree:
name: example-fullstack
match:
main_worktree: $HOME/code/example-app
ports:
- id: frontend
- id: backend
secrets:
- source: $HOME/.config/example-app/backend.env
target: apps/backend/.env
writes:
- path: apps/frontend/.env.development
body: |
VITE_PORT=${frontend}
VITE_API_URL=http://127.0.0.1:${backend}
init:
- command: npm install
cwd: .
skip_if: node_modules
See examples/fullstack.yaml for a complete profile.
Commands
wte setup Create config and the project template, then install Git hooks
wte sync Synchronize the current worktree with its project profile
wte list List live worktree port allocations
wte doctor Diagnose config, profiles, registry, secrets, and hooks
wte uninstall Remove Git hooks while preserving config and state
Run wte sync from inside the worktree that needs repair or refresh. It reuses
or allocates ports, recreates secret symlinks, and regenerates declared files;
it does not run dependency initializers.
The dispatcher invokes wte only for post-checkout. Other installed hook names
exist solely to forward an earlier global hook or a repository-local hook.
wte setup refuses to replace an existing global core.hooksPath unless
--force is supplied; forced setup records and chains it. The internal hook
entry point is intentionally omitted from the public CLI and documentation.
Configuration and state
By default all machine-local files are kept together:
~/.config/wte/
├── config.yaml
├── project.example.yaml.template
├── my-project.yaml
├── another-project.yaml
├── hooks/
└── state/
├── ports.json
├── ports.lock
└── hooks-state.json
Set WTE_CONFIG_HOME to override this location. XDG_CONFIG_HOME is respected
when no explicit override is present.
Every root-level YAML file except config.yaml is loaded as a project profile.
The state/ directory is managed by wte and should not be edited or synchronized.
The machine-wide allocation range is configured in config.yaml:
port_range:
start: 20000
end: 29999
The default range is 20000-29999, below common OS ephemeral ranges and the
Kubernetes NodePort range. Deleted worktree paths are reclaimed during
the next synchronization or automatic checkout projection. Registry writes are
atomic, and a corrupt registry is reported rather than silently replaced.
Security model
Profiles are trusted local configuration. Secret contents are never stored in the registry and secret sources remain outside the repository. Write and secret targets are restricted to the matched worktree. Initializer commands are passed to Bash and therefore must not come from untrusted profiles.
Development
uv sync
uv run pytest
License
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file git_worktree_env-0.1.1.tar.gz.
File metadata
- Download URL: git_worktree_env-0.1.1.tar.gz
- Upload date:
- Size: 36.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af28b12cc92c786383a907d00c15ebe06c3daa02c3bfbeab9689d7d778824864
|
|
| MD5 |
1682e595a260b79e670c51b637098892
|
|
| BLAKE2b-256 |
ee1eccf7fda5631dde1fe300d5fcd8cd38c3cc905e39333ba8940f2dadc2addf
|
File details
Details for the file git_worktree_env-0.1.1-py3-none-any.whl.
File metadata
- Download URL: git_worktree_env-0.1.1-py3-none-any.whl
- Upload date:
- Size: 20.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6728cfd046048f8bb50f698803af84dc64d9cf54a8e298c495bab0a97caa1109
|
|
| MD5 |
a6258d269ada3734702eca00ceb198bc
|
|
| BLAKE2b-256 |
f77d2e0044ea6f39cb2e050c8171bba75a5da1a824a3bb4569fe60d902c8ace5
|