sync-worktrees 2.1.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -56
- package/dist/index.js +3222 -920
- package/dist/index.js.map +4 -4
- package/dist/mcp-server.js +3852 -0
- package/dist/mcp-server.js.map +7 -0
- package/package.json +16 -3
package/README.md
CHANGED
|
@@ -28,6 +28,7 @@ sync-worktrees maintains a **separate working directory for each remote branch**
|
|
|
28
28
|
- 🔁 Automatic retry with exponential backoff for network and filesystem errors
|
|
29
29
|
- 🕐 Branch age filtering - only sync branches active within a specified time period
|
|
30
30
|
- 🔀 Smart handling of rebased/force-pushed branches with automatic divergence detection
|
|
31
|
+
- 🤖 MCP server for AI assistants - inspect and manage worktrees from Claude Desktop, Claude Code, Cursor, etc.
|
|
31
32
|
|
|
32
33
|
## Installation
|
|
33
34
|
|
|
@@ -43,82 +44,120 @@ pnpm add -g sync-worktrees
|
|
|
43
44
|
|
|
44
45
|
## Usage
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
Run `sync-worktrees` in any directory:
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
- **First run** — no config found → interactive wizard asks for repo URL, worktree directory, and schedule, then saves `sync-worktrees.config.js` in the current directory and starts syncing.
|
|
50
|
+
- **Subsequent runs** — `sync-worktrees` auto-loads `sync-worktrees.config.js` (or `.mjs` / `.cjs`) from the current directory. No flags needed.
|
|
49
51
|
|
|
50
52
|
```bash
|
|
51
|
-
|
|
52
|
-
sync-worktrees
|
|
53
|
-
|
|
54
|
-
# Or provide partial arguments and be prompted for the rest
|
|
55
|
-
sync-worktrees --repoUrl https://github.com/user/repo.git
|
|
53
|
+
cd ~/projects/my-sync-dir
|
|
54
|
+
sync-worktrees # wizard → saves config → runs
|
|
55
|
+
sync-worktrees # re-uses the saved config
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
To manage multiple repositories, edit the generated config file and add entries under `repositories`. See [Configuration File](#configuration-file).
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
# Single repository (one-time sync)
|
|
62
|
-
sync-worktrees --repoUrl https://github.com/user/repo.git --worktreeDir ./worktrees --runOnce
|
|
60
|
+
### Explicit config path
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
sync-worktrees --repoUrl https://github.com/user/repo.git --worktreeDir ./worktrees
|
|
62
|
+
Useful when the config lives outside the current directory:
|
|
66
63
|
|
|
67
|
-
|
|
68
|
-
sync-worktrees --config
|
|
64
|
+
```bash
|
|
65
|
+
sync-worktrees --config /path/to/sync-worktrees.config.js
|
|
66
|
+
sync-worktrees --config ./config.js --filter "frontend-*"
|
|
67
|
+
sync-worktrees --config ./config.js --list
|
|
69
68
|
```
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
### Opening a worktree from the TUI
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
|--------|-------|-------------|----------|---------|
|
|
75
|
-
| `--config` | `-c` | Path to JavaScript config file | No | - |
|
|
76
|
-
| `--filter` | `-f` | Filter repositories by name (wildcards supported) | No | - |
|
|
77
|
-
| `--list` | `-l` | List configured repositories and exit | No | `false` |
|
|
78
|
-
| `--repoUrl` | `-u` | Git repository URL (HTTPS or SSH) | Yes* | - |
|
|
79
|
-
| `--bareRepoDir` | `-b` | Directory for bare repository | No | `.bare/<repo-name>` |
|
|
80
|
-
| `--worktreeDir` | `-w` | Directory for storing worktrees | Yes* | - |
|
|
81
|
-
| `--cronSchedule` | `-s` | Cron pattern for scheduling | No | `0 * * * *` (hourly) |
|
|
82
|
-
| `--runOnce` | - | Execute once and exit | No | `false` |
|
|
83
|
-
| `--branchMaxAge` | `-a` | Maximum age of branches to sync (e.g., '30d', '6m', '1y') | No | - |
|
|
84
|
-
| `--skip-lfs` | - | Skip Git LFS downloads when fetching and creating worktrees | No | `false` |
|
|
85
|
-
| `--no-update-existing` | - | Disable automatic updates of existing worktrees | No | `false` |
|
|
86
|
-
| `--help` | `-h` | Show help | No | - |
|
|
87
|
-
|
|
88
|
-
\* Required when not using a config file
|
|
89
|
-
|
|
90
|
-
## Examples
|
|
91
|
-
|
|
92
|
-
### Single repository
|
|
93
|
-
```bash
|
|
94
|
-
# One-time sync
|
|
95
|
-
sync-worktrees -u https://github.com/user/repo.git -w ./worktrees --runOnce
|
|
72
|
+
Press `o` in the interactive TUI to open the selected worktree. The wizard supports two modes, toggled with `Tab`:
|
|
96
73
|
|
|
97
|
-
|
|
98
|
-
|
|
74
|
+
- **Terminal** (default) — launches a new terminal window with a `tmux` session attached to the worktree directory. Session name is `<repo>-<sanitized-branch>`; re-opening the same worktree attaches to the existing session instead of creating a duplicate.
|
|
75
|
+
- **Editor** — launches `$EDITOR` / `$VISUAL` (falls back to `code`) in the worktree.
|
|
99
76
|
|
|
100
|
-
|
|
101
|
-
sync-worktrees -u https://github.com/user/repo.git -w ./worktrees --branchMaxAge 30d
|
|
77
|
+
Terminal mode requires [`tmux`](https://github.com/tmux/tmux) to be installed.
|
|
102
78
|
|
|
103
|
-
|
|
104
|
-
sync-worktrees -u git@github.com:user/repo.git -w ./worktrees --branchMaxAge 6m
|
|
79
|
+
#### Environment variables
|
|
105
80
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
81
|
+
| Variable | Purpose | Default behavior |
|
|
82
|
+
|----------|---------|------------------|
|
|
83
|
+
| `SYNC_WORKTREES_TERMINAL` | Override the terminal launcher on any platform. Value is a command string; the tmux invocation is appended via `sh -c`. Example: `SYNC_WORKTREES_TERMINAL="alacritty -e"`. | See per-platform defaults below. |
|
|
84
|
+
| `TERMINAL` | Linux-only fallback when `SYNC_WORKTREES_TERMINAL` is unset. Same format. | Probes `gnome-terminal`, `konsole`, `alacritty`, `kitty`, `xterm` in order. |
|
|
85
|
+
| `EDITOR` / `VISUAL` | Editor mode launcher. | Falls back to `code`. |
|
|
109
86
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
87
|
+
Per-platform terminal defaults (when no env override is set):
|
|
88
|
+
|
|
89
|
+
- **macOS** — Ghostty if `Ghostty.app` is installed, otherwise Terminal.app via AppleScript.
|
|
90
|
+
- **Linux** — `$TERMINAL` if set; otherwise the first found among the candidates above.
|
|
91
|
+
|
|
92
|
+
## MCP Server
|
|
93
|
+
|
|
94
|
+
sync-worktrees ships a [Model Context Protocol](https://modelcontextprotocol.io) server so AI assistants (Claude Desktop, Claude Code, Cursor, Windsurf, etc.) can inspect and manage your worktrees directly. Installing the package exposes a second binary, `sync-worktrees-mcp`, that speaks MCP over stdio.
|
|
95
|
+
|
|
96
|
+
### Setup
|
|
114
97
|
|
|
115
|
-
|
|
116
|
-
sync-worktrees --config ./sync-worktrees.config.js --filter "frontend-*"
|
|
98
|
+
Add the server to your MCP client config. Use `npx` if the package is not installed globally:
|
|
117
99
|
|
|
118
|
-
|
|
119
|
-
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"mcpServers": {
|
|
103
|
+
"sync-worktrees": {
|
|
104
|
+
"command": "npx",
|
|
105
|
+
"args": ["-y", "-p", "sync-worktrees", "sync-worktrees-mcp"],
|
|
106
|
+
"env": {
|
|
107
|
+
"SYNC_WORKTREES_CONFIG": "/absolute/path/to/sync-worktrees.config.js"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
120
112
|
```
|
|
121
113
|
|
|
114
|
+
If installed globally, replace `command` with `sync-worktrees-mcp` and drop `args`. `SYNC_WORKTREES_CONFIG` is optional — without it the server runs in **auto-detect mode**: when the client's CWD sits inside a worktree managed by sync-worktrees, the server locates the bare repo, enumerates sibling worktrees, and enables per-worktree operations. Sync and initialize require a loaded config (or call `load_config` at runtime).
|
|
115
|
+
|
|
116
|
+
Client-specific locations:
|
|
117
|
+
|
|
118
|
+
| Client | Config file |
|
|
119
|
+
|--------|-------------|
|
|
120
|
+
| Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) |
|
|
121
|
+
| Claude Code | `claude mcp add sync-worktrees -- npx -y -p sync-worktrees sync-worktrees-mcp` |
|
|
122
|
+
| Cursor | `~/.cursor/mcp.json` (or project-level `.cursor/mcp.json`) |
|
|
123
|
+
|
|
124
|
+
### Available tools
|
|
125
|
+
|
|
126
|
+
| Tool | Purpose |
|
|
127
|
+
|------|---------|
|
|
128
|
+
| `detect_context` | Inspect a path, resolve the bare repo, enumerate sibling worktrees, report capabilities. |
|
|
129
|
+
| `list_worktrees` | List worktrees with status label (`clean`/`dirty`/`stale`/`current`), divergence, `safeToRemove`, last sync. |
|
|
130
|
+
| `get_worktree_status` | Detailed status for one worktree (dirty files, unpushed commits, stashes, operation in progress). |
|
|
131
|
+
| `create_worktree` | Create a worktree for a branch; optionally create the branch from `baseBranch` and push. |
|
|
132
|
+
| `remove_worktree` | Remove a worktree after safety checks; `force=true` skips validation. |
|
|
133
|
+
| `update_worktree` | Fast-forward one worktree to match upstream. |
|
|
134
|
+
| `sync` | Full sync cycle (fetch, create, prune, update). Requires config. Streams progress notifications. |
|
|
135
|
+
| `initialize` | Clone the bare repo and create the main worktree. Requires config. Streams progress. |
|
|
136
|
+
| `load_config` | Load or reload a config file at runtime. |
|
|
137
|
+
| `set_current_repository` | Select the active repo when multiple are configured. |
|
|
138
|
+
|
|
139
|
+
All tools that target a single repo accept an optional `repoName`. When omitted, they use the current repository — set by auto-detect, the first entry in the config, or `set_current_repository`.
|
|
140
|
+
|
|
141
|
+
### Safety
|
|
142
|
+
|
|
143
|
+
- `remove_worktree` refuses to delete worktrees with uncommitted changes, unpushed commits, stashes, or operations in progress (merge/rebase/cherry-pick/revert/bisect). Pass `force=true` to override.
|
|
144
|
+
- `create_worktree` rejects sanitized-path collisions (e.g. `feature/foo` vs `feature-foo` both resolving to `feature-foo/`) before touching disk.
|
|
145
|
+
- Path-targeted tools verify the supplied path is a registered worktree of the selected repository.
|
|
146
|
+
|
|
147
|
+
## Options
|
|
148
|
+
|
|
149
|
+
| Option | Alias | Description | Default |
|
|
150
|
+
|--------|-------|-------------|---------|
|
|
151
|
+
| `--config` | `-c` | Path to JavaScript config file (auto-detected in CWD when omitted) | - |
|
|
152
|
+
| `--filter` | `-f` | Filter repositories by name (wildcards supported) | - |
|
|
153
|
+
| `--list` | `-l` | List configured repositories and exit | `false` |
|
|
154
|
+
| `--runOnce` | - | Override config to run once and exit | `false` |
|
|
155
|
+
| `--no-update-existing` | - | Disable automatic updates of existing worktrees | `false` |
|
|
156
|
+
| `--debug` | `-d` | Show detailed reasons for skipped cleanups | `false` |
|
|
157
|
+
| `--help` | `-h` | Show help | - |
|
|
158
|
+
|
|
159
|
+
Most sync behavior (repo URL, worktree directory, cron schedule, branch filtering, LFS, retry) is configured in the config file. The CLI flags that only make sense for one-off runs (`--repoUrl`, `--worktreeDir`, `--cronSchedule`, `--branchMaxAge`, `--branchInclude`, `--branchExclude`, `--skip-lfs`, `--bareRepoDir`) are still supported — run `sync-worktrees --help` for the full list.
|
|
160
|
+
|
|
122
161
|
## Configuration File
|
|
123
162
|
|
|
124
163
|
For managing multiple repositories, create a JavaScript ES module config file:
|
|
@@ -130,6 +169,7 @@ export default {
|
|
|
130
169
|
cronSchedule: "0 * * * *", // Hourly
|
|
131
170
|
runOnce: false,
|
|
132
171
|
branchMaxAge: "30d", // Only sync branches active in last 30 days
|
|
172
|
+
branchExclude: ["wip-*", "tmp-*"], // Exclude WIP and temporary branches
|
|
133
173
|
updateExistingWorktrees: true // Auto-update worktrees that are behind (default: true)
|
|
134
174
|
},
|
|
135
175
|
|
|
@@ -153,6 +193,7 @@ export default {
|
|
|
153
193
|
repoUrl: process.env.BACKEND_REPO_URL, // Environment variables supported
|
|
154
194
|
worktreeDir: "/absolute/path/backend-worktrees",
|
|
155
195
|
branchMaxAge: "6m", // Override: only sync branches active in last 6 months
|
|
196
|
+
branchInclude: ["feature/*", "release-*", "main"], // Only sync specific branches
|
|
156
197
|
// Uses default schedule
|
|
157
198
|
retry: { maxAttempts: 10 } // Override retry for this repo
|
|
158
199
|
}
|
|
@@ -205,6 +246,51 @@ defaults: {
|
|
|
205
246
|
|
|
206
247
|
The tool automatically handles LFS errors by retrying with LFS disabled (max 2 retries by default, configurable via `retry.maxLfsRetries`).
|
|
207
248
|
|
|
249
|
+
### Branch Name Filtering
|
|
250
|
+
|
|
251
|
+
You can control which branches get synced using include and exclude patterns. This is useful for repositories where you only care about specific branch types (e.g., feature branches) or want to skip certain patterns (e.g., WIP branches).
|
|
252
|
+
|
|
253
|
+
**Pattern syntax**: Patterns support `*` wildcards that match any characters (including `/` in branch names).
|
|
254
|
+
- `feature/*` - matches `feature/login`, `feature/auth/oauth`, etc.
|
|
255
|
+
- `release-*` - matches `release-1.0`, `release-2.0-beta`, etc.
|
|
256
|
+
- `*-hotfix` - matches `urgent-hotfix`, `prod-hotfix`, etc.
|
|
257
|
+
|
|
258
|
+
**Filtering semantics**:
|
|
259
|
+
- `branchInclude` - only branches matching at least one pattern are synced
|
|
260
|
+
- `branchExclude` - branches matching any pattern are skipped
|
|
261
|
+
- When both are set, include runs first, then exclude removes from the result
|
|
262
|
+
- The default branch (e.g., `main`) is always retained regardless of filters
|
|
263
|
+
|
|
264
|
+
**Examples**:
|
|
265
|
+
```bash
|
|
266
|
+
# Command line
|
|
267
|
+
sync-worktrees -u https://github.com/user/repo.git -w ./worktrees \
|
|
268
|
+
--branchInclude "feature/*,release-*"
|
|
269
|
+
|
|
270
|
+
sync-worktrees -u https://github.com/user/repo.git -w ./worktrees \
|
|
271
|
+
--branchExclude "wip-*,tmp-*"
|
|
272
|
+
|
|
273
|
+
# Config file - global default
|
|
274
|
+
defaults: {
|
|
275
|
+
branchExclude: ["wip-*", "tmp-*"]
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
# Config file - per repository
|
|
279
|
+
repositories: [{
|
|
280
|
+
name: "frontend",
|
|
281
|
+
branchInclude: ["feature/*", "release-*"],
|
|
282
|
+
branchExclude: ["feature/wip-*"],
|
|
283
|
+
}]
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Combining with age filtering**: Branch name filtering runs first, then age filtering (`branchMaxAge`) is applied to the remaining branches. This lets you narrow down to specific branch types and further filter by activity.
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
# Only feature branches active in the last 30 days
|
|
290
|
+
sync-worktrees -u https://github.com/user/repo.git -w ./worktrees \
|
|
291
|
+
--branchInclude "feature/*" --branchMaxAge 30d
|
|
292
|
+
```
|
|
293
|
+
|
|
208
294
|
### Branch Age Filtering
|
|
209
295
|
|
|
210
296
|
To reduce clutter and save disk space, you can configure sync-worktrees to only sync branches that have been active within a specified time period. This is particularly useful for repositories with many stale or abandoned branches.
|
|
@@ -298,6 +384,8 @@ This ensures you never lose work due to force pushes while keeping your worktree
|
|
|
298
384
|
|
|
299
385
|
- Node.js >= 22.0.0
|
|
300
386
|
- Git
|
|
387
|
+
- [`tmux`](https://github.com/tmux/tmux) (optional, required only for Terminal mode in the TUI)
|
|
388
|
+
- An MCP-capable client (optional, only for the `sync-worktrees-mcp` server)
|
|
301
389
|
|
|
302
390
|
## Contributing
|
|
303
391
|
|