Skip to main content

worktree-env (wte)

中文文档

Automatically prepare an isolated, runnable local development environment for every Git worktree. Lightweight, minimal, no magic.

The problem

Git worktrees are widely used for parallel development and task isolation. However, a new worktree usually contains only code, not a development environment that is ready to run:

  • The frontend, backend, database, and debugger still use the same fixed ports, preventing multiple worktrees from running at the same time.
  • .env files, private keys, and other local secrets must be copied repeatedly and can easily be committed by mistake.
  • URLs and port settings shared by services within a project must be kept in sync manually.

Common solutions often require adding extra scripts to the project, changing how it is started, modifying AGENTS.md or CLAUDE.md, or creating skills. These approaches are intrusive to some degree: they must either be adopted across the team or affect how other team members work.

wte uses a Git post-checkout hook to assign stable, conflict-free ports to a project's worktrees, link environment variables, and generate local configuration. The hook is not committed to the repository. It is available globally on the local machine and does not modify any project code.

Comparison with existing tools

  • Portless: Requires applications to be started through portless, introducing a reverse proxy, a local CA, and a background service.
  • devports: Wraps worktree creation and removal in devports commands; worktrees created directly by an agent or IDE are not handled automatically.
  • Worktrunk: Replaces the native Git workflow with wt, does not participate in environment setup, and does not automatically handle worktrees created directly by an agent or IDE.
  • workz: Uses .workz.toml, workz sync/workz start, or separately configured hooks for Cursor, Claude Code, and Worktrunk.
  • Hyve: Adopts a hyve create/hyve run workflow and depends on Docker, database containers, and service orchestration.

wte does not take over how worktrees are created or how a project is started. Instead, it automatically projects a complete local development environment after a worktree is created. It requires no changes to project code, start commands, or agent prompts; no scripts need to be added to the project, and no traffic proxy or resident process is required. Worktrees created by Git, an IDE, or a coding agent can all be handled automatically.

All rules are declared explicitly in profiles stored outside the repository. For each worktree, wte assigns stable ports, mounts secrets, generates local configuration, and can initialize dependencies in the background, making the worktree ready immediately after creation.

Features

  • Allocates contiguous port blocks from a machine-wide shared pool and keeps them stable for the lifetime of the worktree path.
  • Mounts secrets stored outside the repository into the worktree as symlinks, preserving a single source of truth and avoiding copy and paste.
  • Organizes configuration by repository rather than by service. Supports monorepos and multiple port requests.
  • Optionally monitors host directories to discover newly added linked worktrees, including those created within coding agent sandboxes.
  • Preserves the project's own Git hooks. After the post-checkout hook for wte finishes, it invokes the project's own executable Git hook.
  • Zero intrusion: no wrapper, no skill, and no changes to coding agent prompts or project start commands.

Requirements

  • macOS or Linux
  • Python 3.9+
  • Git
  • Bash

Installation

uv tool install worktree-env

Upgrading

uv tool upgrade worktree-env

Getting started

wte init

This command:

  • Initializes the personal configuration directory at ~/.config/wte/.
  • Runs git config --global core.hooksPath ~/.config/wte/hooks to install the global Git hook dispatcher.

If the global core.hooksPath already points somewhere else, wte displays the current value and refuses to change it. Confirm its purpose and migrate or remove it as appropriate before retrying wte init.

~/.config/wte/

Personal profiles, hooks, and runtime state are stored together in:

~/.config/wte/
├── config.yaml                       # Machine-wide port pool
├── project_a.yaml                    # Project A profile
├── project_b.yaml                    # Project B profile
├── hooks/                            # Global Git hook dispatcher
└── state/                            # Managed by wte; do not edit manually.
    ├── ports.json                    # Port registry
    ├── ports.lock                    # Concurrency lock
    ├── hooks-state.json              # Hook installation state
    └── reconciler.log                # Monitor log (present only when the optional Monitor is enabled; see the Monitor section)

Every root-level *.yaml file except config.yaml is loaded as a project profile.

Set WTE_CONFIG_HOME to change this directory. When it is not set, XDG_CONFIG_HOME is respected.

Configuration examples

Port range

The machine-wide port range is configured in ~/.config/wte/config.yaml:

port-range:
  start: 20000
  end: 29999

The default range is 20000-29999. You can change it manually; new worktrees will be allocated from the new range, while existing allocations remain unchanged.

Project profile

Copy the configuration template:

cp ~/.config/wte/project.example.yaml.template \
   ~/.config/wte/example-project.yaml

The following profile describes a project with separate frontend and backend services:

name: example-project

match:
  # Points to the project's main worktree directory.
  main-worktree: $HOME/code/example-app

port-claims:
  # Names of the ports to request. Add as many as the project needs;
  # each id must be unique within the profile.
  - id: frontend_port
  - id: backend_port

link-files:
  # Environment files shared through symlinks.
  # source points to the original environment file, while target is a path
  # relative to the worktree root.
  - source: $HOME/path/to/your/frontend.env
    target: frontend-dir/.env
  - source: $HOME/path/to/your/backend.env
    target: backend-dir/.env

write-files:
  # Frontend configuration:
  - target: frontend-dir/.env.development
    body: |
      VITE_PORT=${frontend_port}
      SERVER_URL=http://127.0.0.1:${backend_port}

  # Backend configuration:
  - target: backend-dir/.env.development
    body: |
      PORT=${backend_port}

This example applies when both the frontend and backend can load .env.{env name} files. Adjust it to match how your project loads environment variables.

After a worktree directory is deleted, its ports are reclaimed the next time wte is triggered.

Monitor

Some coding agents create worktrees inside a sandbox, which can prevent the wte hook from running. To support these tools, enable the Monitor:

wte monitor enable

It watches the profile directory and the .git/worktrees/ metadata directory associated with each configured main worktree:

  • macOS uses LaunchAgents with WatchPaths.
  • Linux uses systemd user path units.

When a watched directory changes, the operating system starts a short-lived Reconciler. It is not a resident daemon and does not poll on a timer, so its resource usage is minimal.

The Reconciler:

  1. Runs git worktree list --porcelain to retrieve the actual list of worktrees.
  2. Compares it with ports.json, then assigns ports, mounts secrets, generates files, and starts configured initializers for unregistered worktrees.

When profiles are added, removed, or pointed to a different main-worktree, the Monitor automatically refreshes its repository watch paths. After upgrading an existing installation to this version, run wte monitor enable once to activate automatic profile monitoring; subsequent profile changes require no manual refresh.

To disable the Monitor, run:

wte monitor disable

Afterward, filesystem changes will no longer be monitored.

Asynchronous initialization

wte can automatically run commands after a worktree is created, allowing the environment to be initialized in the background:

setup-commands:
  - command: [npm]
    args: [install]
    cwd: frontend-dir  # Use "." to run from the worktree root.
    skip-if: node_modules  # Skip this command if the file or directory exists.

  - command: [uv]
    args: [sync]
    cwd: backend-dir  # Use "." to run from the worktree root.
    skip-if: .venv  # Skip this command if the file or directory exists.

A typical timeline looks like this:

Create a worktree
  → wte projects the environment and starts npm install in the background
  → The user describes the task; the AI reads, analyzes, and modifies the code
  → By the time the user or AI starts the project, dependencies are usually ready

Asynchronous initialization is started by the normal post-checkout hook, by the Monitor Reconciler when it discovers an unregistered worktree, or by wte sync. Configure an appropriate skip-if for each command in setup-commands to avoid rerunning completed initialization during a later sync.

Commands supported by wte

wte init              Create personal configuration and templates, and install core Git hooks
wte sync              Synchronize the environment and start configured setup commands
wte list              List port allocations for worktrees that still exist
wte doctor            Diagnose configuration, profiles, registry, secrets, hooks, and Monitor
wte monitor enable    Install or refresh optional host monitoring
wte monitor disable   Remove host monitoring only, preserving Git hooks
wte uninstall         Remove hooks and the Monitor, preserving configuration and runtime state

wte normally keeps worktrees synchronized automatically, so manual syncs are not necessary. Only after updating a profile, if the latest configuration needs to be projected again, run wte sync from the root of the target worktree.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

worktree_env-0.6.0.tar.gz (50.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

worktree_env-0.6.0-py3-none-any.whl (29.8 kB view details)

Uploaded Python 3

File details

Details for the file worktree_env-0.6.0.tar.gz.

File metadata

  • Download URL: worktree_env-0.6.0.tar.gz
  • Upload date:
  • Size: 50.6 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

Hashes for worktree_env-0.6.0.tar.gz
Algorithm Hash digest
SHA256 ca10d66ff543c30b26ad3db5b1b0bfd72a4b550a1285f38819beb75d7e330a91
MD5 bad07a65a6833a8a1af811d576a6a195
BLAKE2b-256 0e6627b79320ed0c8504c05c2e28b266bc57b775e7996eb12f692107d18a8c4a

See more details on using hashes here.

File details

Details for the file worktree_env-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: worktree_env-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 29.8 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

Hashes for worktree_env-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3d153e6d27f9ca8eccd132ad9e34f627fa8cb201fccd4bf98364fa0aec783b34
MD5 ed90749f1cdf6aa5eeb860c7b8f11533
BLAKE2b-256 dfcfd1e942a89f689a60560b2ce65d4a656caf205bca4416552ad506442e992f

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 files

0.5.0

2 files

0.4.0

2 files

0.3.1

2 files

0.3.0

2 files

0.2.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page