Mastering Git Worktrees for Isolated Agent Tasks

Isolated Development with Git Worktrees

Imagine a team of highly efficient AI developers, each working on a separate feature branch, but all within the same repository, without ever stepping on each other’s toes. This is the power we’re bringing to Kanbots in this chapter. We’ll enable each Kanban card to spawn and manage its own isolated Git environment using Git worktrees.

This milestone is critical because AI agents, especially those generating code, need a clean, predictable workspace. Without isolation, concurrent agents could overwrite each other’s changes, leading to chaos and unpredictable outcomes. Git worktrees provide this crucial sandboxing, allowing agents to operate in parallel, each with its own working directory and branch, while still sharing the underlying repository history and objects.

By the end of this chapter, your Kanbots application will have the foundational Rust backend logic and Svelte frontend integration to create, switch to, and remove Git worktrees directly from a Kanban card. This sets the stage for integrating AI agents in the next chapter, ensuring they have a stable and isolated environment to perform their tasks.

Understanding Git Worktrees: The Foundation of Isolation

At its core, a Git worktree allows you to have multiple working directories attached to the same Git repository. Each working directory can be on a different branch.

What is a Git Worktree?

A worktree is a separate working tree, distinct from your main working directory (the “main worktree”). It has its own checked-out branch, but it shares the same .git directory (or rather, points back to the main .git directory) as the primary repository. This means all worktrees share the same commit history, objects, and refs, but can have different files currently checked out and modified.

Why Do Worktrees Exist?

Git introduced worktrees to solve common developer frustrations:

  • Parallel Development: Work on multiple features or bug fixes simultaneously without constantly stashing and switching branches in a single working directory.
  • Context Switching: Quickly jump between different branches for review or testing without affecting your current work.
  • Experimentation: Try out a new idea on a separate branch in an isolated environment.

How Worktrees Solve Problems for Kanbots

For Kanbots, worktrees are essential for:

  • Agent Isolation: Each AI agent, assigned to a Kanban card, gets its own dedicated workspace. This prevents agents from interfering with each other’s generated code or state.
  • Context Management: An agent can operate on a specific branch within its worktree, ensuring its actions are confined to a defined scope.
  • Parallel Execution: Multiple agents can run concurrently on different cards, each managing its own worktree, without worrying about merge conflicts until their tasks are complete and ready for integration.
  • Clean Slate: When an agent starts a task, it can be provided with a fresh worktree, reducing the risk of stale or unexpected files influencing its behavior.

Basic Git Worktree Commands

Here are the fundamental Git commands we’ll be translating into our Rust backend:

  • Add a new worktree:

    git worktree add <path> <branch_name>

    This creates a new worktree at <path> and checks out <branch_name> in it. If <branch_name> doesn’t exist, it will be created.

  • List existing worktrees:

    git worktree list

    Shows all worktrees associated with the current repository.

  • Remove a worktree:

    git worktree remove <path>

    Deletes the worktree at <path>. The branch associated with it remains unless deleted separately. Requires the worktree to be clean (no uncommitted changes).

  • Force remove a worktree:

    git worktree remove --force <path>

    Deletes the worktree even if it has uncommitted changes. Use with caution.

Designing Worktree Integration for Kanbots

Integrating Git worktrees means our Rust backend will become the orchestrator for Git commands. The Svelte frontend will provide the UI elements to trigger these actions, communicating with Rust via Tauri’s IPC layer.

Architecture Overview

flowchart TD User[User] --> Svelte_UI[Svelte Frontend] Svelte_UI -->|IPC Invoke Command| Tauri_Rust[Tauri Rust Backend] Tauri_Rust -->|Execute Git Command| Git_CLI[Git CLI] Git_CLI --> Filesystem[Local Filesystem] Filesystem --> Worktree_Dir[Worktree Directory] Tauri_Rust -->|IPC Emit Event| Svelte_UI Svelte_UI --> User
  1. Svelte Frontend: Provides buttons or actions on a Kanban card to create, delete, or interact with a worktree.
  2. Tauri Rust Backend: This is where the core logic resides. It receives commands from the Svelte frontend via IPC (Inter-Process Communication).
  3. Git CLI: The Rust backend will execute git commands using std::process::Command, interacting directly with the local Git installation.
  4. Local Filesystem: Git creates and manages the actual worktree directories on the user’s disk.

Data Flow for Creating a Worktree

  1. User clicks “Create Worktree” on a Kanban card in the Svelte UI.
  2. The Svelte frontend invokes a Rust command (e.g., create_card_worktree) via Tauri’s IPC. It passes the card_id and potentially a branch_name.
  3. The Rust backend receives the command.
  4. It constructs and executes a git worktree add command, creating a new directory structure for the worktree.
  5. If successful, the Rust backend might emit an event back to the Svelte frontend (e.g., worktree_created) to update the UI.
  6. The Svelte frontend receives the event and updates the card’s status or displays the worktree path.

Target Repository Structure

Kanbots will manage a dedicated Git repository where all agent worktrees will reside. This repository will be separate from the Kanbots application’s own source code. We’ll call this the “agent development repository” or agent_dev_repo.

A typical structure might look like this:

/path/to/kanbots-app/ # Your Kanbots desktop application
/path/to/agent_dev_repo/ # The Git repository managed by Kanbots
├── .git/
├── .worktrees/
│   ├── card_123_feature_x/ # Worktree for card 123
│   └── card_456_bug_fix/ # Worktree for card 456
├── src/
├── Cargo.toml
└── ... (main branch content)

Each worktree will be created within the agent_dev_repo/.worktrees/ directory. The name of the worktree directory will incorporate the card ID and potentially the branch name for clarity.

Implementing Git Worktree Management (Rust Backend)

We’ll start by adding the necessary Rust logic to the Tauri backend. We will leverage std::process::Command to execute Git CLI commands.

1. Update Cargo.toml

We don’t need any new crates for std::process::Command, but it’s good practice to ensure tauri is configured correctly.

# src-tauri/Cargo.toml
[package]
name = "kanbots"
version = "0.1.0"
description = "A Tauri + Svelte + AI agents Kanban app"
authors = ["You"]
license = ""
repository = ""
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[build-dependencies]
tauri-build = { version = "2.0.0-beta", features = [] }

[dependencies]
tauri = { version = "2.0.0-beta", features = ["shell-open"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1.38.0", features = ["full"] } # Required for async operations and process handling

[features]
# this feature is used for production builds to regenerate the Tauri command schema
# do not remove it
custom-protocol = ["tauri/custom-protocol"]

Decision: We include tokio with full features for robust asynchronous process execution, which is ideal for running external commands like Git without blocking the main thread.

2. Define Git Command Utilities

Create a new module src-tauri/src/git_commands.rs to encapsulate our Git interactions.

// src-tauri/src/git_commands.rs
use std::path::{Path, PathBuf};
use std::process::Command;
use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::process::Command as TokioCommand;

/// Executes a git command in the specified repository path.
async fn run_git_command(
    repo_path: &Path,
    args: &[&str],
) -> Result<String, String> {
    let repo_path_str = repo_path.to_str().ok_or_else(|| "Invalid repo path".to_string())?;

    let mut command = TokioCommand::new("git");
    command.current_dir(repo_path_str);
    command.args(args);

    let output = command.output().await.map_err(|e| format!("Failed to execute git command: {}", e))?;

    if output.status.success() {
        Ok(String::from_utf8_lossy(&output.stdout).to_string())
    } else {
        Err(format!(
            "Git command failed: {}\nStderr: {}",
            String::from_utf8_lossy(&output.status.code().unwrap_or(-1).to_string()),
            String::from_utf8_lossy(&output.stderr)
        ))
    }
}

/// Initializes a new git repository at the given path if it doesn't exist.
pub async fn init_repo_if_not_exists(repo_path: &Path) -> Result<String, String> {
    if !repo_path.exists() {
        tokio::fs::create_dir_all(repo_path)
            .await
            .map_err(|e| format!("Failed to create repo directory: {}", e))?;
        run_git_command(repo_path, &["init"]).await
    } else if !repo_path.join(".git").exists() {
        // If directory exists but is not a git repo, init it
        run_git_command(repo_path, &["init"]).await
    } else {
        Ok(format!("Repository already exists at {}", repo_path.display()))
    }
}

/// Creates a new worktree for a given card ID and branch name.
/// The worktree will be created within the `repo_path/.worktrees/` directory.
pub async fn create_worktree(
    repo_path: &Path,
    card_id: &str,
    branch_name: &str,
) -> Result<PathBuf, String> {
    let worktrees_dir = repo_path.join(".worktrees");
    tokio::fs::create_dir_all(&worktrees_dir)
        .await
        .map_err(|e| format!("Failed to create .worktrees directory: {}", e))?;

    let worktree_path = worktrees_dir.join(format!("{}_{}", card_id, branch_name));

    if worktree_path.exists() {
        return Err(format!("Worktree already exists at {}", worktree_path.display()));
    }

    let result = run_git_command(
        repo_path,
        &[
            "worktree",
            "add",
            worktree_path.to_str().unwrap(), // Safe due to previous check
            branch_name,
        ],
    ).await?;

    // If branch_name didn't exist, git worktree add creates it and checks it out.
    // We should also ensure the main branch exists and has an initial commit for worktrees to work reliably.
    // For simplicity, we assume the main repo is initialized and has at least one commit.

    Ok(worktree_path)
}

/// Removes a worktree for a given card ID and branch name.
pub async fn remove_worktree(
    repo_path: &Path,
    card_id: &str,
    branch_name: &str,
    force: bool,
) -> Result<String, String> {
    let worktrees_dir = repo_path.join(".worktrees");
    let worktree_path = worktrees_dir.join(format!("{}_{}", card_id, branch_name));

    if !worktree_path.exists() {
        return Err(format!("Worktree not found at {}", worktree_path.display()));
    }

    let mut args = vec!["worktree", "remove"];
    if force {
        args.push("--force");
    }
    args.push(worktree_path.to_str().unwrap()); // Safe due to previous check

    run_git_command(repo_path, &args).await
}

/// Gets the path to the agent development repository.
/// For simplicity, we'll place it in a known location relative to the app data directory.
pub fn get_agent_dev_repo_path(app_handle: &tauri::AppHandle) -> Result<PathBuf, String> {
    let app_data_dir = app_handle.path().app_data_dir().ok_or("Failed to get app data directory")?;
    let repo_path = app_data_dir.join("agent_dev_repo");
    Ok(repo_path)
}

Explanation:

  • run_git_command: A helper function to execute any git command. It takes the repository path and a slice of arguments. It captures stdout and stderr and returns an Ok result on success or an Err with detailed error messages. We use tokio::process::Command for async execution.
  • init_repo_if_not_exists: This function ensures our target agent_dev_repo is a valid Git repository. If the directory doesn’t exist, it creates it and initializes a new Git repo. If the directory exists but isn’t a repo, it initializes it.
  • create_worktree: This is the core function for adding a worktree. It constructs the target path within .worktrees/ and executes git worktree add. It returns the path to the newly created worktree.
  • remove_worktree: This function deletes a worktree. It supports a force option, mapping directly to git worktree remove --force.
  • get_agent_dev_repo_path: A utility to determine the consistent location for our agent_dev_repo. Placing it in the app’s data directory (e.g., ~/Library/Application Support/com.kanbots.dev/agent_dev_repo on macOS) is a robust solution for desktop apps.

3. Integrate Commands into src-tauri/src/main.rs

Now, expose these Git commands as Tauri IPC commands.

// src-tauri/src/main.rs
// ... existing imports ...
mod git_commands; // Import the new module

// Tauri command to initialize the agent development repository
#[tauri::command]
async fn setup_agent_dev_repo(app_handle: tauri::AppHandle) -> Result<String, String> {
    let repo_path = git_commands::get_agent_dev_repo_path(&app_handle)?;
    git_commands::init_repo_if_not_exists(&repo_path).await
}

// Tauri command to create a new worktree for a card
#[tauri::command]
async fn create_card_worktree(
    app_handle: tauri::AppHandle,
    card_id: String,
    branch_name: String,
) -> Result<String, String> {
    let repo_path = git_commands::get_agent_dev_repo_path(&app_handle)?;
    let worktree_path = git_commands::create_worktree(&repo_path, &card_id, &branch_name).await?;
    Ok(format!("Worktree created at {}", worktree_path.display()))
}

// Tauri command to remove a worktree for a card
#[tauri::command]
async fn remove_card_worktree(
    app_handle: tauri::AppHandle,
    card_id: String,
    branch_name: String,
    force: bool,
) -> Result<String, String> {
    let repo_path = git_commands::get_agent_dev_repo_path(&app_handle)?;
    let result = git_commands::remove_worktree(&repo_path, &card_id, &branch_name, force).await?;
    Ok(result)
}


fn main() {
    tauri::Builder::new()
        .setup(|app| {
            // Optional: Initialize the repo on app startup.
            // For this chapter, we'll trigger it from the UI for clarity.
            // let handle = app.handle();
            // tauri::async_runtime::spawn(async move {
            //     match setup_agent_dev_repo(handle).await {
            //         Ok(msg) => println!("Repo setup: {}", msg),
            //         Err(e) => eprintln!("Failed to setup repo: {}", e),
            //     }
            // });
            Ok(())
        })
        .invoke_handler(tauri::generate_handler![
            // ... existing handlers ...
            setup_agent_dev_repo,
            create_card_worktree,
            remove_card_worktree,
        ])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Explanation:

  • We import our new git_commands module.
  • setup_agent_dev_repo: An IPC command to ensure the agent_dev_repo is ready. This is a good first step for the user.
  • create_card_worktree: Takes card_id and branch_name and calls our git_commands::create_worktree function.
  • remove_card_worktree: Takes card_id, branch_name, and a force boolean, then calls git_commands::remove_worktree.
  • These new commands are added to tauri::generate_handler!.

4. Create an Initial Commit in the Agent Dev Repo (Manual Step)

For git worktree add to work reliably, the main repository (agent_dev_repo) should have at least one commit. This is a common pitfall. Before testing, run these commands once in the agent_dev_repo directory (which will be created when you first run setup_agent_dev_repo via Kanbots):

# Navigate to your agent_dev_repo after it's created by Kanbots
# Example: cd ~/Library/Application\ Support/com.kanbots.dev/agent_dev_repo/ (macOS)
git add .
git commit -m "Initial commit for agent development repository"

You can also automate this in init_repo_if_not_exists by checking if there are any commits, but for now, we’ll keep it a manual setup step to highlight the requirement.

Integrating with the Svelte Frontend

Now, let’s add UI elements to our Svelte frontend to trigger these Rust commands. We’ll add buttons to a Kanban card component.

1. Update src/lib/tauri.ts

If you have a tauri.ts file for IPC calls, add the new command definitions.

// src/lib/tauri.ts
import { invoke } from '@tauri-apps/api/core';

export const tauriCommands = {
    // ... existing commands ...
    setupAgentDevRepo: async (): Promise<string> => {
        return invoke('setup_agent_dev_repo');
    },
    createCardWorktree: async (cardId: string, branchName: string): Promise<string> => {
        return invoke('create_card_worktree', { cardId, branchName });
    },
    removeCardWorktree: async (cardId: string, branchName: string, force: boolean = false): Promise<string> => {
        return invoke('remove_card_worktree', { cardId, branchName, force });
    },
};

2. Add Buttons to a Kanban Card Component

Let’s assume you have a KanbanCard.svelte component. We’ll add buttons to it.

<!-- src/lib/components/KanbanCard.svelte -->
<script lang="ts">
    import { tauriCommands } from '$lib/tauri';
    import { createEventDispatcher } from 'svelte';
    import { writable } from 'svelte/store';

    export let card: { id: string; title: string; description: string; worktreePath?: string; };

    const dispatch = createEventDispatcher();
    const worktreeStatus = writable(card.worktreePath ? 'created' : 'none');

    async function handleSetupRepo() {
        try {
            const result = await tauriCommands.setupAgentDevRepo();
            console.log('Repo setup:', result);
            alert(`Agent Dev Repo Setup: ${result}`);
        } catch (error) {
            console.error('Error setting up repo:', error);
            alert(`Error setting up repo: ${error}`);
        }
    }

    async function handleCreateWorktree() {
        const branchName = `feature-${card.id}`; // Simple branch naming convention
        try {
            const result = await tauriCommands.createCardWorktree(card.id, branchName);
            console.log('Worktree created:', result);
            alert(`Worktree created: ${result}`);
            card.worktreePath = result.split('at ')[1]; // Extract path from message
            worktreeStatus.set('created');
            dispatch('cardUpdate', card); // Notify parent component of card update
        } catch (error) {
            console.error('Error creating worktree:', error);
            alert(`Error creating worktree: ${error}`);
        }
    }

    async function handleRemoveWorktree() {
        const branchName = `feature-${card.id}`;
        if (!confirm('Are you sure you want to remove this worktree?')) return;
        try {
            const result = await tauriCommands.removeCardWorktree(card.id, branchName, true); // Force remove for simplicity in tutorial
            console.log('Worktree removed:', result);
            alert(`Worktree removed: ${result}`);
            card.worktreePath = undefined;
            worktreeStatus.set('none');
            dispatch('cardUpdate', card);
        } catch (error) {
            console.error('Error removing worktree:', error);
            alert(`Error removing worktree: ${error}`);
        }
    }
</script>

<div class="kanban-card">
    <h3>{card.title}</h3>
    <p>{card.description}</p>
    {#if $worktreeStatus === 'none'}
        <button on:click={handleCreateWorktree}>Create Worktree</button>
    {:else}
        <p>Worktree: {$worktreeStatus} ({card.worktreePath})</p>
        <button on:click={handleRemoveWorktree}>Remove Worktree</button>
    {/if}
    <button on:click={handleSetupRepo}>Setup Agent Repo (First Time)</button>
</div>

<style>
    .kanban-card {
        background-color: #f0f0f0;
        border: 1px solid #ccc;
        padding: 10px;
        margin-bottom: 10px;
        border-radius: 5px;
    }
    button {
        margin-right: 5px;
        padding: 5px 10px;
        cursor: pointer;
    }
</style>

Explanation:

  • We import tauriCommands and createEventDispatcher from Svelte.
  • worktreeStatus is a Svelte store to reactively update the UI based on worktree presence.
  • handleSetupRepo: Calls the Rust command to initialize the agent_dev_repo. This button should ideally be in a global settings area, but for this chapter, it’s placed on the card for easy access during testing.
  • handleCreateWorktree: Generates a branch name (e.g., feature-card_id) and calls createCardWorktree. It then updates the card’s worktreePath and worktreeStatus.
  • handleRemoveWorktree: Calls removeCardWorktree with force: true for simpler testing.
  • The UI conditionally renders “Create Worktree” or “Remove Worktree” based on worktreeStatus.

Testing & Verification: Ensuring Worktree Isolation

Now it’s time to verify that our worktree management works as expected.

Steps to Verify

  1. Start Kanbots:
    npm run tauri dev
  2. Initialize Agent Dev Repo:
    • In the Kanbots UI, click the “Setup Agent Repo (First Time)” button on any card.
    • You should see an alert “Agent Dev Repo Setup: Repository already exists…” or “Repository initialized…”.
    • Crucial Manual Step: Navigate to the agent_dev_repo directory (e.g., ~/Library/Application Support/com.kanbots.dev/agent_dev_repo/ on macOS, or similar in AppData/Roaming on Windows, or ~/.config on Linux). If this is the first time, run:
      # Example path - adjust for your OS
      cd "$(tauri info | grep 'App data directory' | awk '{print $NF}')/agent_dev_repo"
      git add .
      git commit -m "Initial commit for agent development repository"
      This ensures the main repo has a commit, which is required for adding worktrees reliably.
  3. Create a New Kanban Card: Add a new card to your board (e.g., “Implement User Login”).
  4. Create Worktree for the Card:
    • Click the “Create Worktree” button on your new card.
    • You should see an alert indicating the worktree was created, along with its path.
    • The button should change to “Remove Worktree”.
  5. Verify Worktree on Filesystem:
    • Open your terminal and navigate to the agent_dev_repo directory.
    • Run git worktree list. You should see your new worktree listed, pointing to the path like agent_dev_repo/.worktrees/card_123_feature-card_123.
    • Navigate into the new worktree directory: cd .worktrees/card_123_feature-card_123.
    • Run git branch. It should show you are on feature-card_123.
  6. Test Isolation:
    • Inside the worktree directory (agent_dev_repo/.worktrees/card_123_feature-card_123), create a new file: echo "Hello from agent" > agent_output.txt.
    • Commit this change:
      git add .
      git commit -m "Agent generated file"
    • Now, navigate back to the main agent_dev_repo directory: cd ../...
    • Check if agent_output.txt exists here: ls -l agent_output.txt. It should not exist.
    • Verify the current branch: git branch. You should be on main (or whatever your default branch is). This demonstrates the isolation.
  7. Remove Worktree:
    • Back in the Kanbots UI, click “Remove Worktree” on the card.
    • Confirm the action. You should see an alert confirming removal.
    • The button should revert to “Create Worktree”.
  8. Verify Removal:
    • In your terminal, run git worktree list again. The worktree should no longer be listed.
    • Check the filesystem: ls -l .worktrees/card_123_feature-card_123. The directory should be gone.

If all these steps pass, your Kanbots application is successfully managing Git worktrees!

Production Considerations: Robust Worktree Management

While our current implementation is functional, a production-ready system requires more robustness.

  • Error Handling: The current error messages are basic. In production, we’d parse Git’s stderr more carefully to provide user-friendly feedback (e.g., “Branch already exists,” “Worktree not empty,” “Git command not found”).
  • Disk Space Management: Each worktree consumes disk space. If users create many cards/worktrees, this can add up. Consider:
    • A warning or limit on the number of active worktrees.
    • Automatic cleanup of old/stale worktrees (e.g., after a card is archived).
  • Concurrency and Locking: While Git is generally safe with worktrees, if multiple agents try to modify the same underlying repository objects (e.g., fetching new remotes) at the exact same time, there could be edge cases. For now, our commands are simple enough not to cause issues, but complex workflows might need more careful synchronization.
  • Security: AI agents will execute commands within their worktrees. While worktrees provide filesystem isolation for code changes, the agent itself runs with the permissions of the Kanbots application. Ensure agents are not given capabilities that could compromise the host system (e.g., running arbitrary executables outside their designated worktree). This will be a more critical concern in later chapters when agents are actually introduced.
  • User Feedback: Beyond simple alerts, the UI should provide real-time feedback on worktree status (e.g., “Creating worktree…”, “Worktree ready”, “Error creating worktree”).
  • Branch Management: Our current implementation uses a simple feature-card_id branch name. A more advanced system might allow users to specify branch names, or integrate with remote repositories for pushing agent-generated branches.

Common Issues & Solutions

  1. “Repository does not have any commits yet” or “fatal: working tree is not a git repository”:
    • Issue: git worktree add requires the main repository (agent_dev_repo) to have at least one commit.
    • Solution: Ensure you’ve followed the manual step to git add . and git commit in your agent_dev_repo after it’s initialized.
  2. “Worktree already exists at :
    • Issue: You tried to create a worktree at a path that already exists. This can happen if a previous remove_worktree failed to delete the directory.
    • Solution: Manually delete the offending directory (rm -rf <path>) and then try creating the worktree again. Our create_worktree function checks for this.
  3. “fatal: ‘worktree’ is not a git command”:
    • Issue: Your Git installation might be too old, or Git is not properly installed/in your system’s PATH. Git worktrees were introduced in Git 2.5.
    • Solution: Update Git to a recent version (e.g., Git 2.45.0 as of 2026-05-24). Ensure git is accessible from your terminal.
  4. Permissions Errors:
    • Issue: Kanbots (and thus the Rust backend) doesn’t have the necessary permissions to create directories or execute Git commands in the target location.
    • Solution: Check the permissions of the parent directory where agent_dev_repo is created. Ensure the user running Kanbots has write access. On Linux, placing it in ~/.config/kanbots/agent_dev_repo is usually safe.

Summary & Next Steps

In this chapter, we’ve laid a crucial foundation for Kanbots: the ability to manage isolated Git worktrees. You’ve learned:

  • The fundamental concept of Git worktrees and why they are invaluable for parallel, isolated development.
  • How to design the interaction between the Svelte frontend and Rust backend for Git operations.
  • Implemented Rust backend logic using std::process::Command to create and remove worktrees.
  • Integrated these functionalities into the Svelte UI.
  • Verified the worktree creation and isolation through practical terminal commands.

Your Kanbots application can now dynamically provision Git environments for each card, a prerequisite for intelligent agent execution. This architectural decision significantly reduces complexity for agent orchestration and ensures a clean, controlled environment for code generation and review.

Next, we’ll build upon this by integrating our first AI agent (e.g., Claude Code or Codex) into a Kanban card, enabling it to perform tasks within its newly managed worktree.


References


This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.