worktree-switcher
Manages Angular development servers, passing the port via a framework-specific --port argument.
Manages Astro development servers, passing the port via a framework-specific --port argument.
Detects Bun projects with a dev script and manages their development servers.
Discovers Git worktrees for registered repositories and allows switching a project's server to a different worktree without changing its port.
Manages Next.js development servers over HTTP or development HTTPS, passing the port via the PORT environment variable.
Manages Node.js development servers with start, stop, restart, and switch operations; custom servers receive the port via the PORT environment variable.
Detects npm projects with a dev script and manages their development servers.
Manages Nuxt development servers, passing the port via a framework-specific --port argument.
Detects pnpm projects with a dev script and manages their development servers.
Manages Vite development servers, passing the port via a framework-specific --port argument.
Detects Yarn projects with a dev script and manages their development servers.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@worktree-switcherSwitch the frontend server to the bugfix worktree"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Worktree Switcher
One dev server per project. Switch its Git worktree without changing the port.
If you keep the same application checked out on several branches, you probably know the routine: find the terminal that owns the server, stop it, change directories, start it again, then check whether an old process kept the port. Worktree Switcher handles that routine from one local dashboard.
Register each repository once. The controller discovers its worktrees and gives the project a stable port. You can start, stop, restart, or move the server to a different worktree without disturbing the other projects in your stack.
Coding agents can use the same controller through MCP. They can inspect state, claim a worktree, and release it when the task is done instead of starting a second copy behind your back.
This is a working prototype. The CLI and data model may still change. The npm package has not been published yet.
What works
Manage several repositories at once, each on its own port.
Discover worktrees through Git's porcelain output.
Start, stop, restart, and switch Node.js and Django development servers.
Detect
pnpm,npm,yarn, andbunprojects with adevscript.Show the active branch, commit, dirty state, PID, failures, and recent logs.
Keep human locks and expiring agent claims in SQLite.
Let MCP clients inspect projects and manage their own claims.
Run Next.js development servers over HTTP or development HTTPS.
Run the controller in a terminal or as a user service on Linux and macOS.
Optionally cap the number of concurrently running managed servers.
Queue Node.js and Django verification commands per worktree with a configurable global parallel limit.
Monitor aggregate RAM, peak RAM, CPU, and process count for each managed server on Linux.
Track disk usage for every worktree, including
.next,.next/cache, andnode_modules.Use the dashboard in English or Polish. English is the default.
Related MCP server: coordinaut
Quick start
Worktree Switcher is not on npm yet, so run it from a local checkout.
You need Linux or macOS, Node.js 22 or newer, pnpm, and Git.
git clone https://github.com/pioootrek/worktree-switcher.git
cd worktree-switcher
corepack enable
pnpm install --frozen-lockfile
pnpm build
pnpm startThe controller prints a private browser URL. Open that exact URL, select Add project, choose a Git repository, and assign its port. Worktree Switcher will find every worktree attached to that repository.
The dashboard listens on 0.0.0.0:47831 by default, so other devices on the
LAN can reach it if the host firewall allows the connection. MCP stays on
127.0.0.1:47832.
To keep the dashboard on the same machine:
node dist/cli/index.js start --host 127.0.0.1Run it in the background
For daily use, install the built controller as a user service. The installer
uses systemd on Linux and a LaunchAgent on macOS. It does not need sudo, edit
firewall rules, or install a system-wide daemon.
Stop the foreground controller first, then run:
node dist/cli/index.js service install
node dist/cli/index.js service status
node dist/cli/index.js service openservice open reads the current pairing URL from an owner-only file. The URL
does not appear in the system journal or LaunchAgent logs.
See Running Worktree Switcher as a user service for configuration options, upgrades, logs, Linux session behavior, and removal.
A typical workflow
Add your frontend repository and give it port 3000.
Add your API repository and give it port 4000.
Pick a worktree for each project.
Start both servers.
Switch the frontend to another branch. The API keeps running on port 4000.
Each project owns one runtime slot. A switch stops that project's current process tree, starts the selected worktree on the same port, and waits for the port to become ready. Operations for other projects continue independently.
The gauge in the dashboard configures an optional controller-wide capacity. Each starting or running server consumes one slot. A switch retains its current slot, while a failed start releases it. Lowering the limit never stops an already running server; new starts remain blocked until usage falls below the configured limit.
Each project card also shows resource use for the complete process group owned by the controller, including package-manager and Next.js worker processes. The sampler runs every five seconds only while a server is active and retains at most five minutes of RAM history. Stopped servers do not consume sampling work. On unsupported systems, the panel reports that metrics are unavailable without changing the server lifecycle.
The Storage tab measures allocated disk space for every discovered
worktree. It separates .next, .next/cache, node_modules, and other files,
shows the five largest top-level directories, and keeps the first measurement
plus 179 recent samples in SQLite. Scans never follow symlinks, run one at a time, and are scheduled at
first discovery and at most once every six hours. Use the refresh button for an
explicit new sample.
Git administrative data under .git is excluded so linked worktrees remain
comparable with the repository's main checkout.
For detected Next.js projects, the Storage tab can remove the selected
worktree's .next directory after an explicit confirmation. The action is
available only when that worktree is stopped, unlocked, and not being scanned.
The controller derives the directory from an allowlisted cache identifier,
refuses symlinks and non-Next.js projects, records the outcome in the audit
trail, and schedules a fresh disk measurement. It never accepts a deletion
path or removes node_modules.
Dirty worktrees are allowed. The dashboard warns you but does not block the server.
Managed tests
The Tests tab discovers finite verification presets separately for every
worktree. Node.js projects expose test, test:*, check, lint,
typecheck, and build package scripts. Django projects expose
manage.py test and resolve the Python interpreter inside the selected
worktree.
Runs enter one controller-wide FIFO queue. The configured parallel limit
defaults to one, and no more than one run may execute in the same worktree at
once. Each run records its worktree path, branch, commit, dirty state, actor,
command, bounded output tail, exit code, and final state in SQLite. Complete
logs are written under logs/tests/. A graceful controller stop cancels active
runs; after an unexpected stop, unfinished records are marked as interrupted
on the next start.
Commands are discovered by typed Node.js and Django adapters and are spawned without a shell. The browser and MCP select only a discovered preset and an exact Git-discovered worktree; neither accepts arbitrary command text or a working directory.
How it works
flowchart LR
Browser[Web dashboard] --> Controller[Node.js controller]
Agent[MCP client] --> MCP[Loopback MCP listener]
MCP --> Controller
Controller --> Git[Git worktrees]
Controller --> SQLite[(SQLite)]
Controller --> Apps[Development servers]
Controller --> Tests[Test process queue]Next.js builds the dashboard as static files. At runtime, one Node.js controller
serves those files, owns SQLite, reads Git metadata, and manages child
processes. There is no resident next start process behind the dashboard.
Launch commands are stored as an executable and argument array. The controller spawns them without a shell. Neither the browser nor MCP can submit an arbitrary command.
Project commands and ports
When you add a repository, Worktree Switcher detects Node.js from package.json
or Django from a root-level manage.py. You can also select the preset
explicitly. Node.js projects must have a dev script. Angular workspaces are
detected from angular.json plus @angular/cli; they may use either
dev: ng serve or the standard start: ng serve script.
Project type | How the port is passed |
Next.js |
|
Vite, Astro, Nuxt | Framework-specific |
Angular |
|
Other Node.js servers |
|
Django |
|
A custom Node.js server can read the same environment variable:
const port = Number(process.env.PORT ?? 3000);
server.listen(port);For every Django worktree, the resolver prefers .venv/bin/python, then
venv/bin/python, then python3. It does not install dependencies, run
migrations, or manage collectstatic. Custom commands, external virtual
environments, ASGI servers, and Django LAN binding are not supported yet.
Environment profiles
Every managed project has a default environment profile and may define
additional named profiles such as staging, e2e, or fixtures. Profiles are
framework-independent: the selected literal variables are injected into both
Node.js and Django processes and remain selected when the project switches to
another worktree. For Django, a profile can select settings without adding
free-form command text, for example:
DJANGO_SETTINGS_MODULE=config.settings.staging
SWITCHER_TEST_VALUE=stagingPORT and NODE_ENV remain controller-owned. Variable names are validated,
processes are still spawned without a shell, and audit events record variable
names without their values. Editing or selecting a profile for an active server
requires an explicit restart. Literal values are stored in SQLite; do not put
secrets in them. Secret references, .env files, relative working directories,
PATH prefixes, and required runtime directories remain planned work.
MCP for coding agents
MCP is enabled by default at:
http://127.0.0.1:47832/mcpIt uses Streamable HTTP and a persistent bearer token. Print the client configuration with:
node dist/cli/index.js config mcpThe output contains the token. Treat it like a password. Keep it out of source files, issues, logs, and chat.
Available tools:
Tool | What it does |
| Lists registered projects and their runtime placement |
| Reads the global server limit, usage, and slot holders |
| Reads the global test limit and current queue usage |
| Reads runtime, claim, and selected-worktree state |
| Reads cached disk usage and history for project worktrees |
| Lists worktrees discovered for a project |
| Lists safe presets discovered for each project worktree |
| Queues a preset for an exact worktree with an idempotency key |
| Reads one run and its bounded output tail |
| Cancels a run created by the current MCP session |
| Replaces the selected profile's literal variables while the server is stopped |
| Lists named profiles and the selected profile |
| Creates or replaces a literal environment profile |
| Selects a profile while the server is stopped |
| Deletes a non-default, inactive profile |
| Claims a worktree and moves or starts its server |
| Extends a claim owned by the current MCP session |
| Releases a claim without stopping the server |
Claims are exclusive and tied to one discovered worktree. They expire after inactivity and have an eight-hour maximum lifetime. An MCP client cannot run arbitrary commands, choose arbitrary paths, or force-release somebody else's claim.
Read Reservations and MCP integration for the claim model and security boundaries.
Install the agent skill
The repository includes an Agent Skill for clients that work with managed development servers. From this checkout:
codex_skill_dir="${CODEX_HOME:-$HOME/.codex}/skills"
mkdir -p "$codex_skill_dir"
cp -R skills/worktree-switcher "$codex_skill_dir/"Restart the agent session after copying the skill. Configure MCP separately
with the private output of config mcp. The skill contains no credentials.
Add a short rule to each managed project's AGENTS.md or CLAUDE.md:
## Development server
Use the `$worktree-switcher` skill before starting or switching this project's
development server. When the Worktree Switcher MCP tools are available, let the
controller own the server process and honor existing claims.The full agent workflow lives in
skills/worktree-switcher/SKILL.md.
Next.js development HTTPS
Open the shield button on a project card to choose one of these modes:
HTTP
HTTPS with a certificate generated by Next.js
HTTPS with a local private key, certificate, and optional CA file
Stop the project's server before changing this setting. For custom certificates, Worktree Switcher saves canonical file paths. It never sends the private key contents through the dashboard.
This controls the managed Next.js server only. It does not add TLS to the Worktree Switcher dashboard.
Security model
The dashboard can start and stop local processes, so its access URL is a credential.
Every controller start creates a new browser pairing token.
Dashboard API calls, log requests, and events require that token.
Browser mutations from another origin are rejected.
The directory picker stays below the configured browse root.
MCP listens on loopback and uses a separate persistent token.
The controller only stops process trees it started.
An unknown process on a configured port is reported, not killed.
The dashboard currently uses HTTP. Bind it to loopback, use a secure tunnel, or limit access to a trusted LAN. If the host uses UFW, a LAN-only rule can look like this:
sudo ufw allow from 192.168.1.0/24 to any port 47831 proto tcp comment 'Worktree Switcher LAN'Adjust the subnet to match your network. The service installer never changes the firewall.
CLI reference
From a source checkout, replace worktree-switcher in the examples below with
node dist/cli/index.js.
worktree-switcher start [options]
--port <port> Dashboard port. Default: 47831
--host <address> Dashboard bind address. Default: 0.0.0.0
--no-open Do not open a browser
--browse-root <path> Root exposed by the directory picker
--data-dir <path> SQLite database and MCP token directory
--state-dir <path> Lock, access record, and log directory
--mcp-port <port> MCP port. Default: 47832
--no-mcp Disable MCP
--memory-warning-mib N Show a warning when a managed process group reaches N MiBOther commands:
worktree-switcher config path
worktree-switcher config mcp
worktree-switcher project add <path> [--name <name>] [--port <port>] [--preset auto|node|django]
worktree-switcher project list [--json]
worktree-switcher project remove <id>
worktree-switcher doctor
worktree-switcher service install [start options] [--refresh]
worktree-switcher service status
worktree-switcher service start
worktree-switcher service stop
worktree-switcher service restart
worktree-switcher service open
worktree-switcher service url
worktree-switcher service uninstallWhen --port is omitted, project add selects the first available port from
3000 through 3999. Project commands use the authenticated controller API while
the user service is running. With no controller, they acquire the singleton
lock and use the same control services directly; they never write concurrently
to an owned database. doctor verifies Node.js, Git, application state, and
worktree discovery without requiring a browser.
Data and logs
By default, SQLite and the MCP token live here:
$XDG_DATA_HOME/worktree-switcher/state.sqlite3
~/.local/share/worktree-switcher/state.sqlite3Runtime state and logs live here:
$XDG_STATE_HOME/worktree-switcher/controller.lock
$XDG_STATE_HOME/worktree-switcher/service-access.json
$XDG_STATE_HOME/worktree-switcher/logs/controller.log
$XDG_STATE_HOME/worktree-switcher/logs/projects/<project-id>.log
$XDG_STATE_HOME/worktree-switcher/logs/tests/<run-id>.logThe access record, lock, and token are owner-only files. Logs rotate at 5 MiB
and keep one previous copy. Worktree Switcher runs as a normal user and does
not write to /var/log.
Development
pnpm check
pnpm buildUseful focused commands:
pnpm test
pnpm test:watch
pnpm typecheck
pnpm lintRead the product brief before changing product or architecture decisions. Architecture decisions describes the current process, persistence, and security boundaries.
Contributing
Bug reports, focused pull requests, and notes from worktree-heavy setups are welcome. Open an issue before a large change so the ownership and security model can be discussed first.
Keep the controller independent from the repositories it manages. Changes should preserve shell-free process spawning, per-project isolation, and the rule that unrelated processes are never killed.
Current limitations
Node.js projects need a
devscript; Django support currently targets the built-in development server and a root-levelmanage.py.The dashboard uses HTTP and is intended for loopback or a trusted network.
Project registration is available only in the dashboard. Project removal is not implemented yet.
Managed-server resource monitoring currently uses Linux
/proc; macOS shows an explicit unsupported state.The macOS LaunchAgent generator has unit coverage but still needs a real-host lifecycle test.
Windows process-tree and service management are not supported.
The npm package is not published yet.
The next release work is tracked in docs/backlog.
License
Worktree Switcher is available under the MIT License. Third-party attribution is recorded in THIRD_PARTY_NOTICES.md.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
- AxisOAuthdev.useaxis
Coding agents from Claude Code, Cursor and Codex claim jobs and lock files on one shared board.
Shared control plane for AI coding agents — tasks, memory, decisions, file locks. 12 tools.
The team layer for AI coding agents: shared contracts, collision alerts, E2EE sessions.
- ParleyOAuthdev.weldra
Coordination hub for AI coding agents: message teammates, ask humans, audit every event.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenancePrevents AI coding agents from conflicting by coordinating file claims and resolving conflicts in real-time across multiple sessions.3361MIT
- AlicenseNot gradedqualityAmaintenanceCoordinates parallel AI coding agents by providing task ownership, scoped file locks, handoffs, and verification workflows.MIT
- AlicenseNot gradedqualityAmaintenanceLocal coordination for coding agents that share a Git working tree.122MIT
- AlicenseNot gradedqualityBmaintenanceEnables multiple AI coding agents to safely collaborate in the same git working tree by managing file ownership, merging writes, and preventing snapshot races.302MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/pioootrek/worktree-switcher'
If you have feedback or need assistance with the MCP directory API, please join our Discord server