当前位置: 首页 > news >正文

[GenAI] Launch Multiple Cursor Composer AI Agents to Work in Parallel

AI coding assistants (like Cursor's Composer) are powerful, but running a single instance can become a bottleneck, especially for larger tasks or when experimenting with different approaches. This lesson shows you how to break free from that limitation by leveraging Git worktrees to enable parallel AI development.

The Problem:

  • Single Composer instances can be slow for complex tasks.
  • Multiple agents modifying the same files simultaneously lead to conflicts.
  • Traditional branching can be cumbersome for rapid experimentation.

The Solution: Git Worktrees

Git worktrees allow you to create multiple, independent working directories linked to the same Git repository. Each worktree can be associated with a different branch, providing isolated environments for development.

Workflow:

  1. Create Worktrees: Use git worktree add -b <branch-name> ../<project-name>-<branch-name> to create a new worktree and associated branch. The -b flag creates the branch. The path (../<project-name>-<branch-name>) places the worktree in a sibling directory (cleaner organization). Repeat for each variation you want to explore.
  2. Launch Multiple Cursor Instances: Open Cursor in each worktree directory (e.g., cursor ../my-project-variant1). Each instance is now isolated and can work on its assigned branch.
  3. Assign Tasks to Composer: Within each Cursor instance, use Composer (Chat or Agent mode) to work on specific tasks or implement different approaches to the same problem. Use @ to provide context (files, directories, docs).
  4. Monitor and Iterate: Check in on each Composer instance's progress. Because they're in separate worktrees, there are no conflicts.
  5. Merge the Best Solution: Once a branch has a successful solution, merge it back into your main branch using git merge <branch-name>.
  6. Clean Up: Remove the worktrees with git worktree remove ../<project-name>-<branch-name>.

ZSH Functions (Optional but Powerful):

The lesson introduces two ZSH functions (provided as code snippets) to automate this process:

  • wtree(): Takes branch names as arguments, creates corresponding worktrees, installs dependencies (with -p flag for PNPM), and optionally launches Cursor in each. This streamlines setup.
  • wtmerge(): Takes a single branch name as an argument, merges that branch into main, and then cleans up all worktrees created by wtree(). This simplifies merging and cleanup.

Benefits:

  • Parallel Development: Run multiple Composer instances simultaneously, drastically speeding up development.
  • Conflict-Free Experimentation: Isolate different approaches in separate branches/worktrees, eliminating merge conflicts.
  • Rapid Iteration: Quickly create, test, and merge (or discard) variations of your code.
  • Clean Workspace: Worktrees keep your main project directory uncluttered.

This lesson empowers you to unlock the full potential of AI coding assistants by running them in parallel, fostering faster experimentation and more efficient development. You'll learn a practical technique that significantly boosts your productivity when working with AI-generated code.

# wtree: Create a new worktree for each given branch.
# Usage: wtree [ -p|--pnpm ] branch1 branch2 ...
#
# This function does the following:
#   1. Parses command-line arguments; if -p/--pnpm is provided, it will later run "pnpm install".
#   2. Determines the current branch and repository root.
#   3. Uses a fixed parent directory (~/dev) to house all worktree directories.
#   4. For each branch passed:
#        - If the branch does not exist, it is created from the current branch.
#        - It checks that a worktree for that branch does not already exist.
#        - It then creates a worktree in ~/dev using a naming convention: <repoName>-<branch>.
#        - If the install-deps flag is true, it runs "pnpm install" inside the new worktree.
#        - Finally, it either opens the new worktree via the custom "cursor" command (if defined)
#          or prints its path.
wtree() {# Flag to determine whether to run "pnpm install"local install_deps=falselocal branches=()# Parse command-line argumentswhile [[ $# -gt 0 ]]; docase "$1" in-p|--pnpm)install_deps=trueshift;;*)branches+=("$1")shift;;esacdone# Ensure at least one branch name is provided.if [[ ${#branches[@]} -eq 0 ]]; thenecho "Usage: wtree [ -p|--pnpm ] branch1 branch2 ..."return 1fi# Determine the current branch; exit if not in a git repository.local current_branchcurrent_branch=$(git rev-parse --abbrev-ref HEAD) || {echo "Error: Not a git repository."return 1}# Determine repository root and name.local repo_root repo_namerepo_root=$(git rev-parse --show-toplevel) || {echo "Error: Cannot determine repository root."return 1}repo_name=$(basename "$repo_root")# Set fixed parent directory for worktrees.local worktree_parent="$HOME/dev"# Ensure the worktree parent directory exists.if [[ ! -d "$worktree_parent" ]]; thenif ! mkdir -p "$worktree_parent"; thenecho "Error: Failed to create worktree parent directory: $worktree_parent"return 1fifi# Loop over each branch provided as argument.for branch in "${branches[@]}"; do# Define the target path using a naming convention: <repoName>-<branch>local target_path="$worktree_parent/${repo_name}-${branch}"echo "Processing branch: ${branch}"# Check if a worktree already exists at the target path.if git worktree list | grep -q "^${target_path}[[:space:]]"; thenecho "Error: Worktree already exists at ${target_path}. Skipping branch '${branch}'."continuefi# If the branch does not exist, create it from the current branch.if ! git show-ref --verify --quiet "refs/heads/${branch}"; thenecho "Branch '${branch}' does not exist. Creating it from '${current_branch}'..."if ! git branch "${branch}"; thenecho "Error: Failed to create branch '${branch}'. Skipping."continuefifi# Create the new worktree for the branch.echo "Creating worktree for branch '${branch}' at ${target_path}..."if ! git worktree add "$target_path" "${branch}"; thenecho "Error: Failed to create worktree for branch '${branch}'. Skipping."continuefi# If the install flag is set, run "pnpm install" in the new worktree.if $install_deps; thenecho "Installing dependencies in worktree for branch '${branch}'..."if ! ( cd "$target_path" && pnpm install ); thenecho "Warning: Failed to install dependencies in '${target_path}'."fifi# Optionally, open the worktree directory via a custom "cursor" command if available.if type cursor >/dev/null 2>&1; thencursor "$target_path"elseecho "Worktree created at: ${target_path}"fiecho "Worktree for branch '${branch}' created successfully."echo "-----------------------------------------------------"done
}# wtmerge: Merge changes from a specified worktree branch into main,
# then clean up all worktrees and delete their branches.
#
# Usage: wtmerge <branch-to-keep>
#
# This function does the following:
#   1. Verifies that the branch to merge (branch-to-keep) exists as an active worktree.
#   2. Checks for uncommitted changes in that worktree:
#        - If changes exist, it attempts to stage and commit them.
#        - It gracefully handles the situation where there are no changes.
#   3. Switches the current (main) worktree to the "main" branch.
#   4. Merges the specified branch into main, with proper error checking.
#   5. Uses "git worktree list" to retrieve all active worktrees (under ~/dev
#      and matching the naming pattern) and removes them.
#   6. Deletes each branch that was created for a worktree (skipping "main").
wtmerge() {# Ensure exactly one argument is passed: the branch to merge.if [ $# -ne 1 ]; thenecho "Usage: wtmerge <branch-to-keep>"return 1filocal branch_to_keep="$1"# Determine the repository root and its name.local repo_root repo_namerepo_root=$(git rev-parse --show-toplevel) || {echo "Error: Not a git repository."return 1}repo_name=$(basename "$repo_root")# Fixed parent directory where worktrees are located.local worktree_parent="$HOME/dev"# Retrieve all active worktrees (from git worktree list) that match our naming convention.local worktrees=()while IFS= read -r line; do# Extract the worktree path (first field)local wt_pathwt_path=$(echo "$line" | awk '{print $1}')# Only consider worktrees under our fixed parent directory that match "<repo_name>-*"if [[ "$wt_path" == "$worktree_parent/${repo_name}-"* ]]; thenworktrees+=("$wt_path")fidone < <(git worktree list)# Check that the target branch worktree exists.local target_worktree=""for wt in "${worktrees[@]}"; doif [[ "$wt" == "$worktree_parent/${repo_name}-${branch_to_keep}" ]]; thentarget_worktree="$wt"breakfidoneif [[ -z "$target_worktree" ]]; thenecho "Error: No active worktree found for branch '${branch_to_keep}' under ${worktree_parent}."return 1fi# Step 1: In the target worktree, check for uncommitted changes.echo "Checking for uncommitted changes in worktree for branch '${branch_to_keep}'..."if ! ( cd "$target_worktree" && git diff --quiet && git diff --cached --quiet ); thenecho "Changes detected in branch '${branch_to_keep}'. Attempting auto-commit..."if ! ( cd "$target_worktree" &&git add . &&git commit -m "chore: auto-commit changes in '${branch_to_keep}' before merge" ); thenecho "Error: Auto-commit failed in branch '${branch_to_keep}'. Aborting merge."return 1elseecho "Auto-commit successful in branch '${branch_to_keep}'."fielseecho "No uncommitted changes found in branch '${branch_to_keep}'."fi# Step 2: Switch to the main worktree (assumed to be the current directory) and check out main.echo "Switching to 'main' branch in the main worktree..."if ! git checkout main; thenecho "Error: Failed to switch to 'main' branch."return 1fi# Step 3: Merge the target branch into main.echo "Merging branch '${branch_to_keep}' into 'main'..."if ! git merge "${branch_to_keep}" -m "feat: merge changes from '${branch_to_keep}'"; thenecho "Error: Merge failed. Please resolve conflicts and try again."return 1fi# Step 4: Remove all worktrees that were created via wtree().echo "Cleaning up worktrees and deleting temporary branches..."for wt in "${worktrees[@]}"; do# Extract branch name from worktree path.local wt_branchwt_branch=$(basename "$wt")wt_branch=${wt_branch#${repo_name}-}  # Remove the repo name prefixecho "Processing worktree for branch '${wt_branch}' at ${wt}..."# Remove the worktree using --force to ensure removal.if git worktree remove "$wt" --force; thenecho "Worktree at ${wt} removed."elseecho "Warning: Failed to remove worktree at ${wt}."fi# Do not delete the 'main' branch.if [[ "$wt_branch" != "main" ]]; thenif git branch -D "$wt_branch"; thenecho "Branch '${wt_branch}' deleted."elseecho "Warning: Failed to delete branch '${wt_branch}'."fifidoneecho "Merge complete: Branch '${branch_to_keep}' merged into 'main', and all worktrees cleaned up."
}
http://www.jsqmd.com/news/290126/

相关文章:

  • 多核异构MPU在多轴实时运动控制中的系统架构与实现解析
  • 从零构建嵌入式轻量级命令行调试工具
  • 【前端开发】Vue项目多客户配置自动化方案【二】
  • WD5030K实测解析:一款撑起宽压大电流场景的国产DC-DC芯片,7-30V宽压输入、12A
  • 【高斯泼溅】还在龟速建模?三步实现训练极速优化
  • 技术前沿!提示工程架构师提升AI提示质量的创新思路
  • 通过采集器监测环境的温湿度如果这个采集器连上网络接入云平台会发生什么呢?
  • 物联网模组柔性FPC天线方案选型与应用指南解析
  • Zookeeper集群部署实战:高可用配置与性能调优
  • 【预编码】基于matlab BDMA下行传输的集群块对角数字预编码【含Matlab源码 15008期】含报告
  • 【通信】基于matlab遗传算法多用户MISO系统速率分拆【含Matlab源码 15012期】
  • 64通道+166μs采样!触觉智能RK3506+OneOS低成本实时ADC采集
  • 触觉智能RV1126B核心板配置USB复合设备(上)
  • 重塑智算存储范式:绿算技术NVMe-oF芯片解决方案全景剖析
  • 零基础搞懂大模型微调:入门必备知识点
  • 书目
  • 【通信】DPCM编码及2DPSK调制数字频带通信系统仿真【含Matlab源码 15019期】
  • Visual Paradigm AI 数据库建模工具全面指南
  • 【光学】水波在多个垂直薄板下的透射系数【含Matlab源码 15013期】
  • P14162 [ICPC 2022 Nanjing R] 完美匹配
  • RM赛事C型板九轴IMU解算(3)(姿态融合算法)
  • Lua基础语法(上篇)
  • 驱动千店销售转化提升10%:3C零售门店的人效优化实战方案
  • 破解出海管理“消耗战”:中企如何用数字化工具赢得海外团队信任?
  • 【通信】基于matlab DPCM编码及2DPSK调制数字频带通信系统仿真【含Matlab源码 15019期】
  • 【光学】基于matlab水波在多个垂直薄板下的透射系数【含Matlab源码 15013期】
  • 【图像加密】基于matlab双随机相位编码和压缩传感实现安全图像加密【含Matlab源码 15009期】
  • 2026年 不锈钢模块/不锈钢加工厂/不锈钢剪板折弯厂家推荐排行榜:匠心工艺与精密制造实力解析
  • 基于 Vue + VueUse 的 WebSocket 优雅封装:打造高可用的全局连接管理方案
  • AI赋能运营:数字化系统如何自动分配收益与激励?