Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,44 @@
# Devtree

Run the same Vite+ app in multiple git worktrees without local-dev collisions.
Run the same Vite app in multiple git worktrees without local-dev collisions.

Devtree gives each worktree its own public URL, managed env block, scoped dependency names, setup hooks, and garbage collection for orphaned local resources.

## Use

### 1. Install

Devtree assumes your app already uses `vite-plus`. It is a required peer dependency, but this README does not install it for you.
Devtree can launch either `vite-plus` or plain `vite`. It defaults to `vite-plus` for compatibility with existing projects.

Install Devtree itself:

```bash
vp add -D devtree
pnpm add -D devtree
```

Dependencies you may also need:

- `vite-plus` - required. Your app should already have it installed and be using it.
- `vite-plus` or `vite` - required. Devtree runs `vp dev` by default, or `vite dev` when `dev_server.runner` is `"vite"`.
- `portless` - required unless you disable it with `portless.enabled: false` or `PORTLESS=0`. The `portless` command must be available on `PATH`.
- `tailscale` - optional, only needed when `tailscale.enabled` is `true`.
- `varlock` and `@varlock/vite-integration` - required only when `env.provider` is set to `"varlock"`.

Install `portless` in the repo so `vp devtree ...` can find it:
Install `portless` in the repo so `devtree` can find it:

```bash
vp add -D portless
pnpm add -D portless
```

If you want `portless` available outside pnpm-managed scripts too, install it globally:

```bash
vp add -g portless
pnpm add -g portless
```

If you use `varlock`, install both pieces together:

```bash
vp add -D varlock @varlock/vite-integration
pnpm add -D varlock @varlock/vite-integration
```

That gives you the `varlock` CLI plus the Vite integration Devtree expects.
Expand All @@ -55,6 +55,9 @@ import { define_devtree_config } from "devtree";

export default define_devtree_config({
app_name: "my-app",
dev_server: {
runner: "vite-plus",
},
tailscale: {
enabled: true,
},
Expand All @@ -78,12 +81,16 @@ export default define_devtree_config({

By default Devtree manages a block inside `.env.local`. Set `env.file_path` if you want a different file.

Set `dev_server.runner` to `"vite"` if the app uses plain Vite and should launch with `vite dev`.

If you enable `tailscale`, Devtree checks for the `tailscale` CLI, reads the machine's MagicDNS hostname, starts Vite on `0.0.0.0`, and adds that hostname to Vite's allowed hosts so the dev server can be reached over Tailscale.

### 3. Register the Vite plugin

Use your app's existing config helper. Plain Vite apps import from `vite`; VitePlus apps can keep importing from `vite-plus`.

```ts
import { defineConfig } from "vite-plus";
import { defineConfig } from "vite";
import { devtree_vite_plugins } from "devtree/vite";

import devtree_config from "./devtree.config.ts";
Expand Down Expand Up @@ -135,6 +142,7 @@ Examples:

```bash
pnpm devtree config tailscale.enabled true
pnpm devtree config dev_server.runner vite
pnpm devtree config portless.https "inherit"
pnpm devtree config namespace personal-dev
pnpm devtree config tailscale.enabled
Expand Down
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@mdulghier/devtree",
"version": "0.1.6",
"description": "Worktree-aware multi-instance dev orchestration for Vite+ apps.",
"description": "Worktree-aware multi-instance dev orchestration for Vite apps.",
"keywords": [
"devtree",
"portless",
Expand Down Expand Up @@ -60,19 +60,27 @@
"@types/node": "^24.5.2",
"@tanstack/intent": "^0.0.23",
"typescript": "^5.7.2",
"vite": "8.0.1",
"vite-plus": "latest"
},
"peerDependencies": {
"@varlock/vite-integration": "*",
"vite": "*",
"varlock": "*",
"vite-plus": "*"
},
"peerDependenciesMeta": {
"@varlock/vite-integration": {
"optional": true
},
"vite": {
"optional": true
},
"varlock": {
"optional": true
},
"vite-plus": {
"optional": true
}
},
"engines": {
Expand Down
73 changes: 43 additions & 30 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions skills/devtree-set-up-devtree/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: devtree-set-up-devtree
description: >
Set up devtree in a Vite+ repository: install `devtree`, create
Set up devtree in a Vite repository: install `devtree`, create
`devtree.config.ts`, define `env.entries`, choose `dotenv` or `varlock`,
register `devtree_vite_plugins`, and configure optional `dependencies`
and `hooks`. Load this when an agent needs to bootstrap worktree-aware
Expand All @@ -22,17 +22,22 @@ sources:

## Setup

Install `devtree` and register both the config file and the Vite plugin.
Install `devtree` and register both the config file and the Vite plugin. Devtree defaults to `vite-plus`; set `dev_server.runner` to `vite` for plain Vite apps.

```bash
pnpm add -D devtree vite-plus
```

For plain Vite apps, install `vite` instead and set `dev_server.runner` to `'vite'`.

```ts
import { define_devtree_config } from 'devtree'

export default define_devtree_config({
app_name: 'my-app',
dev_server: {
runner: 'vite-plus',
},
env: {
provider: 'dotenv',
entries: ({ instance }) => [
Expand Down Expand Up @@ -62,6 +67,8 @@ export default defineConfig({
})
```

Plain Vite apps can import `defineConfig` from `vite` instead.

```json
{
"scripts": {
Expand Down
Loading
Loading