From b1bbf2cf973bebced7ed36d5b51637d045d13a53 Mon Sep 17 00:00:00 2001 From: HugoCasa Date: Wed, 25 Feb 2026 15:44:42 +0100 Subject: [PATCH] workmux better ee cleanup + cursor wrapper autocompletion and open-ee --- README_WORKMUX_DEV.md | 12 +++++- scripts/wm-cursor | 81 +++++++++++++++++++++++++++++++++++++++- scripts/worktree-cleanup | 30 ++++++++++----- 3 files changed, 110 insertions(+), 13 deletions(-) diff --git a/README_WORKMUX_DEV.md b/README_WORKMUX_DEV.md index bfb2d7e576..0b113e47ee 100644 --- a/README_WORKMUX_DEV.md +++ b/README_WORKMUX_DEV.md @@ -65,7 +65,7 @@ Setting up zsh autocomplete is also recommended — see the [workmux docs](https Each worktree is assigned a **slot** that determines its ports: | Slot | Backend | Frontend | -|------|---------|----------| +| ---- | ------- | -------- | | 0 | 8000 | 3000 | | 1 | 8010 | 3010 | | 2 | 8020 | 3020 | @@ -192,7 +192,6 @@ sandbox: This mounts both the main EE repo (used by the main worktree) and the EE worktrees directory (used by feature worktrees) into every sandbox container. - ## Cursor SSH Integration (`wmc`) `wm-cursor` (aliased as `wmc`) gives each worktree its own Cursor SSH remote window with an independently-focused tmux session. All windows are visible in the status bar across all Cursor terminals, but each one is focused on its own worktree. @@ -219,6 +218,7 @@ This: 1. **Merges `.vscode/settings.json`** — adds the `wm-tmux` terminal profile (auto-attaches to the `main` tmux session), disables auto port forwarding, configures forwarding for ports 8000/3000/5432, and stops rust-analyzer from auto-starting. Existing settings are preserved. 2. **Creates `.vscode/tasks.json`** — auto-starts the dev database (`start-dev-db.sh`) when the folder opens. 3. **Adds `wmc` alias to `~/.zshrc`** — so you can use `wmc` from any tmux window. +4. **Adds `eval "$(wmc completions)"`** to `~/.zshrc` — provides tab-completion for subcommands and worktree names (for `open`, `open-ee`, and `close`). After setup, reopen Cursor's terminal to pick up the new profile. @@ -240,6 +240,14 @@ This runs `workmux add`, creates a grouped tmux session, writes `.vscode/setting wmc open my-feature ``` +**Open the EE worktree in Cursor (no tmux session):** + +```bash +wmc open-ee my-feature +``` + +This finds the matching `windmill-ee-private__worktrees/` directory and opens it in a new Cursor window. + **Close a worktree's Cursor window and tmux window (keeps the worktree):** ```bash diff --git a/scripts/wm-cursor b/scripts/wm-cursor index 552bdcd985..596d89bd3c 100755 --- a/scripts/wm-cursor +++ b/scripts/wm-cursor @@ -199,6 +199,40 @@ cmd_close() { workmux close $name } +cmd_open_ee() { + local name=${1:?Usage: wm-cursor open-ee } + + local wt_path=$(workmux path $name) + local main_repo_root="$(cd "$(git -C "$wt_path" rev-parse --git-common-dir 2>/dev/null)/.." && pwd)" + + # Find ee repo (same discovery logic as worktree-env) + local ee_repo="" candidate + for candidate in \ + "${main_repo_root:+${main_repo_root}/../windmill-ee-private}" \ + "${wt_path}/../windmill-ee-private" \ + "${HOME}/windmill-ee-private" \ + "${HOME}/projects/windmill-ee-private"; do + if [[ -n $candidate ]] && [[ -d $candidate ]]; then + ee_repo=${candidate:A} + break + fi + done + + if [[ -z $ee_repo ]]; then + print -u2 "Error: Could not find windmill-ee-private repo" + exit 1 + fi + + local ee_worktree_dir="${ee_repo}__worktrees/${name}" + if [[ ! -d $ee_worktree_dir ]]; then + print -u2 "Error: EE worktree not found at ${ee_worktree_dir}" + exit 1 + fi + + $cursor_bin -n $ee_worktree_dir + print "Opened Cursor for EE worktree: ${ee_worktree_dir}" +} + cmd_setup() { local repo_root=${1:?Usage: wm-cursor setup } repo_root=${repo_root:A} @@ -275,7 +309,7 @@ json.dump(json.loads(text), sys.stdout, indent=2) print "Created ${settings_file}" fi - # --- zsh alias --- + # --- zsh alias + completion --- local rc=${ZDOTDIR:-$HOME}/.zshrc local alias_line="alias wmc=${(q)script_path}" @@ -286,6 +320,45 @@ json.dump(json.loads(text), sys.stdout, indent=2) print "\n# wm-cursor alias\n${alias_line}" >> $rc print "Added wmc alias to ${rc}" fi + + local eval_line='eval "$(wmc completions)"' + if ! grep -qF 'wmc completions' $rc; then + print "${eval_line}" >> $rc + print "Added completions eval to ${rc}" + fi +} + +cmd_completions() { + cat <<'COMP' +_wmc_worktree_names() { + local -a names + names=(${(f)"$(git worktree list --porcelain 2>/dev/null | sed -n 's|^worktree .*/||p' | tail -n +2)"}) + _describe 'worktree' names +} + +_wmc() { + local -a subcmds=( + 'add:Create worktree + open Cursor' + 'open:Open Cursor for existing worktree' + 'open-ee:Open EE worktree in Cursor' + 'close:Clean up grouped tmux session' + 'setup:Set up .vscode settings, tasks + wmc alias' + 'completions:Print zsh completions' + ) + + if (( CURRENT == 2 )); then + _describe 'subcommand' subcmds + else + case $words[2] in + open|open-ee|close) + _wmc_worktree_names + ;; + esac + fi +} + +compdef _wmc wmc wm-cursor +COMP } # --- Main --- @@ -293,16 +366,20 @@ json.dump(json.loads(text), sys.stdout, indent=2) case ${1-} in add) shift; cmd_add "$@" ;; open) shift; cmd_open "$@" ;; + open-ee) shift; cmd_open_ee "$@" ;; close) shift; cmd_close "$@" ;; setup) shift; cmd_setup "$@" ;; + completions) cmd_completions ;; *) - print -u2 "Usage: wm-cursor [args...]" + print -u2 "Usage: wm-cursor [args...]" print -u2 "" print -u2 "Subcommands:" print -u2 " add [--features ] [workmux-add-args...] Create worktree + open Cursor" print -u2 " open [--features ] Open Cursor for existing worktree" + print -u2 " open-ee Open EE worktree in Cursor" print -u2 " close Clean up grouped tmux session" print -u2 " setup Set up .vscode settings, tasks + wmc alias" + print -u2 " completions Print zsh completions (use with eval)" print -u2 "" print -u2 "Options:" print -u2 " --features Cargo features for the backend (e.g. \"enterprise,parquet\")" diff --git a/scripts/worktree-cleanup b/scripts/worktree-cleanup index cdac356635..078d3882e6 100755 --- a/scripts/worktree-cleanup +++ b/scripts/worktree-cleanup @@ -26,18 +26,30 @@ fi # Remove the matching windmill-ee-private worktree if one exists wt_basename=$(basename "$wt_dir") -# Check parent directory first (sibling to worktree root), then fall back to home +# Find ee repo using same discovery logic as worktree-env +main_repo_root="$(cd "$(git -C "$wt_dir" rev-parse --git-common-dir 2>/dev/null)/.." && pwd)" parent_dir="$(cd "$wt_dir/.." && pwd)" -echo "[cleanup] wt_basename=$wt_basename parent_dir=$parent_dir" -if [ -d "${parent_dir}/windmill-ee-private" ]; then - ee_repo="${parent_dir}/windmill-ee-private" -else - ee_repo="${HOME}/windmill-ee-private" +echo "[cleanup] wt_basename=$wt_basename main_repo_root=$main_repo_root parent_dir=$parent_dir" + +ee_repo="" +for candidate in \ + "${main_repo_root:+${main_repo_root}/../windmill-ee-private}" \ + "${parent_dir}/windmill-ee-private" \ + "${HOME}/windmill-ee-private" \ + "${HOME}/projects/windmill-ee-private"; do + if [ -n "$candidate" ] && [ -d "$candidate" ]; then + ee_repo="$(cd "$candidate" && pwd)" + break + fi +done + +if [ -z "$ee_repo" ]; then + echo "[cleanup] Could not find windmill-ee-private repo, skipping EE worktree cleanup" fi -ee_worktree_dir="${ee_repo}__worktrees/${wt_basename}" -echo "[cleanup] ee_repo=$ee_repo ee_worktree_dir=$ee_worktree_dir exists=$([ -d "$ee_worktree_dir" ] && echo yes || echo no)" -if [ -d "$ee_worktree_dir" ]; then +ee_worktree_dir="${ee_repo:+${ee_repo}__worktrees/${wt_basename}}" +echo "[cleanup] ee_repo=${ee_repo:-} ee_worktree_dir=${ee_worktree_dir:-} exists=$([ -n "$ee_worktree_dir" ] && [ -d "$ee_worktree_dir" ] && echo yes || echo no)" +if [ -n "$ee_worktree_dir" ] && [ -d "$ee_worktree_dir" ]; then git -C "$ee_repo" worktree remove "$ee_worktree_dir" --force 2>/dev/null \ && echo "[cleanup] Removed EE worktree at $ee_worktree_dir" \ || echo "[cleanup] Warning: Could not remove EE worktree at $ee_worktree_dir"