sync-worktrees 2.2.0 → 3.1.0

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 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
- ### Interactive Mode
47
+ Run `sync-worktrees` in any directory:
47
48
 
48
- When running without all required arguments, sync-worktrees will prompt you interactively:
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
- # Interactive setup - prompts for missing values
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
- ### Command Line
58
+ To manage multiple repositories, edit the generated config file and add entries under `repositories`. See [Configuration File](#configuration-file).
59
59
 
60
- ```bash
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
- # Single repository (scheduled hourly)
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
- # Multiple repositories (using config file)
68
- sync-worktrees --config ./sync-worktrees.config.js
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
- ## Options
70
+ ### Opening a worktree from the TUI
72
71
 
73
- | Option | Alias | Description | Required | Default |
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
- # Scheduled sync (every 30 minutes)
98
- sync-worktrees -u git@github.com:user/repo.git -w ./worktrees -s "*/30 * * * *"
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
- # Only sync branches active in the last 30 days
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
- # Sync branches active in the last 6 months, check every hour
104
- sync-worktrees -u git@github.com:user/repo.git -w ./worktrees --branchMaxAge 6m
79
+ #### Environment variables
105
80
 
106
- # Disable automatic updates of existing worktrees
107
- sync-worktrees -u https://github.com/user/repo.git -w ./worktrees --no-update-existing
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
- ### Using a config file
111
- ```bash
112
- # Sync all repositories
113
- sync-worktrees --config ./sync-worktrees.config.js
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
- # Filter specific repositories
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
- # List configured repositories
119
- sync-worktrees --config ./sync-worktrees.config.js --list
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