Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save sourman/9ac986f36a23a709ab5da813670b5793 to your computer and use it in GitHub Desktop.

Select an option

Save sourman/9ac986f36a23a709ab5da813670b5793 to your computer and use it in GitHub Desktop.
Cursor worktrees fast server spin up
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import path from "path";
import { componentTagger } from "lovable-tagger";
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
server: {
host: "::",
port: 8080,
},
plugins: [
react(),
mode === 'development' &&
componentTagger(),
// Inject worktree name into HTML title
{
name: 'inject-worktree-title',
transformIndexHtml(html) {
const worktree = process.env.VITE_WORKTREE;
if (worktree) {
return html.replace(
/<title>(.*?)<\/title>/,
`<title>[${worktree}] $1</title>`
);
}
return html;
},
},
].filter(Boolean),
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
}));
# git worktrees spin up script meant for running in conjunction with cursor worktrees
# cursor creates wokrtrees in wsl in ~/.cursor/worktrees/$project/[slug] for each worktree
# The waled function spawns new vite servers in recently created worktrees and can take
# an arg to spevify lookbak window in minutes. e.g. waled 5 will only look at folders
# touched in the last 5 minutes
# mawet cleans up all the pids spawned by waled
# Function 1: Start dev servers for recently created worktree directories
waled() {
local lookback_minutes="${1:-10}"
if ! [[ "$lookback_minutes" =~ ^[0-9]+$ ]]; then
echo "Error: Lookback time must be a positive number (minutes)"
echo "Usage: cdworktree [lookback_minutes]"
return 1
fi
repo="$(basename "$(pwd)")"
export WORK_TREE_DIR=~/.cursor/worktrees/"${repo}__WSL__ubuntu_"/
if [ ! -d "$WORK_TREE_DIR" ]; then
echo "Work tree directory not found: $WORK_TREE_DIR"
return 1
fi
echo "Looking for directories created in the last $lookback_minutes minutes..."
# Find directories created in the last N minutes
recent_dirs=$(find "$WORK_TREE_DIR" -maxdepth 1 -type d -mmin -"$lookback_minutes" ! -path "$WORK_TREE_DIR")
if [ -z "$recent_dirs" ]; then
echo "No recent directories found in $WORK_TREE_DIR (last $lookback_minutes minutes)"
return 0
fi
# Create PID tracking file
pid_file="/tmp/worktree-pids-${repo}-$$.pid"
map_file="${pid_file%.pid}.map"
touch "$pid_file"
touch "$map_file"
# Spawn bash for each directory
while IFS= read -r dir; do
if [ -n "$dir" ]; then
worktree_name="$(basename "$dir")"
echo "Starting dev server for: $dir (worktree: $worktree_name)"
# Store mapping
echo "$worktree_name:$dir" >> "$map_file"
(
cd "$dir" && npm i && VITE_WORKTREE="$worktree_name" npm run dev
) &
pid=$!
echo "$pid" >> "$pid_file"
echo "$pid:$worktree_name" >> "${pid_file%.pid}.details"
echo "Spawned PID $pid for $worktree_name"
fi
done <<< "$recent_dirs"
echo ""
echo "PIDs tracked in: $pid_file"
echo "Worktree mapping in: $map_file"
echo ""
echo "Worktree -> Directory mapping:"
cat "$map_file"
}
# Function 2: Kill all spawned worktree processes
mawet() {
# Find all PID files matching the pattern
pid_files=$(find /tmp -maxdepth 1 -name "worktree-pids-*.pid" -type f 2>/dev/null)
if [ -z "$pid_files" ]; then
echo "No worktree PID files found"
return 0
fi
# Collect all PIDs and process groups from all files
all_pids=()
all_pgroups=()
while IFS= read -r pid_file; do
if [ -f "$pid_file" ]; then
echo "Reading PIDs from: $pid_file"
while IFS= read -r pid; do
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
all_pids+=("$pid")
# Get process group ID
pgid=$(ps -o pgid= -p "$pid" 2>/dev/null | tr -d ' ')
if [ -n "$pgid" ]; then
all_pgroups+=("$pgid")
fi
fi
done < "$pid_file"
# Also show the mapping before killing
map_file="${pid_file%.pid}.map"
if [ -f "$map_file" ]; then
echo "Killing servers:"
cat "$map_file" | while IFS=: read -r name dir; do
echo " - $name"
done
fi
fi
done <<< "$pid_files"
# Kill all process groups (which includes child processes like Vite)
if [ ${#all_pgroups[@]} -eq 0 ]; then
echo "No active process groups found"
else
# Remove duplicates
unique_pgroups=($(printf "%s\n" "${all_pgroups[@]}" | sort -u))
echo "Killing ${#unique_pgroups[@]} process groups: ${unique_pgroups[*]}"
for pgid in "${unique_pgroups[@]}"; do
# Kill the entire process group
if kill -- "-$pgid" 2>/dev/null; then
echo "Killed process group $pgid"
else
echo "Failed to kill process group $pgid, trying individual PIDs"
fi
done
sleep 2
# Fallback: kill any remaining individual PIDs
for pid in "${all_pids[@]}"; do
if kill -0 "$pid" 2>/dev/null; then
echo "Force killing remaining PID $pid"
kill -9 "$pid" 2>/dev/null
fi
done
fi
# Clean up PID files
echo "Cleaning up PID files..."
rm -f /tmp/worktree-pids-*.pid
rm -f /tmp/worktree-pids-*.map
rm -f /tmp/worktree-pids-*.details
}
@sourman
Copy link
Author

sourman commented Dec 4, 2025

The first file defines two functions. waled() bash function and mawet()

  1. after creating multiple agents using cursor, waled will intelligently go into each new worktree created by cursor and it starts npm run dev in each of them so that you can preview the changes made by each agent
  2. When done viewing the changed you can cline up all the vite servers by running mawet which will find and kill all the spawned npm run dev instances

Do not forget to update the vite config (or whatever env) so that it auto injects the folder slug into the browser window so it is easy to understand which browser window was created by which agent

https://www.loom.com/share/d0ab6755251b4848b500ab1e3f8a734a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment