Exercise: Parallel Feature Development with Worktrees
This exercise practices the complete worktree workflow: setting up isolated development environments, running parallel agent sessions, and resolving the merge conflicts that result when branches converge.
Overview
The huh library is a Go package for building interactive terminal forms. It provides field types (text input, select, multiselect, confirm) that developers compose into forms for CLI applications. The codebase is small enough to understand quickly while having clear module boundaries that enable parallel work.
The exercise creates two worktrees, assigns independent features to each, runs agent sessions in parallel, and then merges the results. The merge will produce conflicts because both features touch shared infrastructure. Resolving those conflicts practices the techniques from this module.
The task
Add two independent features to the huh library:
Feature A: Add a FilePicker field type
A new field that presents a file browser interface, allowing users to navigate directories and select files.
This requires creating a new field type following the patterns established by existing fields like field_input.go and field_select.go.
Feature B: Add a HighContrast theme
A new theme optimized for accessibility, using bold colors and maximum contrast.
This requires adding a new theme to theme.go and ensuring it works with all existing field types.
Both features are independent in concept but share infrastructure:
- Both modify the form's field registration or theming system
- Both likely update shared test files or examples
- Both may add to the same import blocks or interface definitions
This shared infrastructure creates merge conflicts when the branches combine.
Setup
Clone the repository:
git clone https://github.com/charmbracelet/huh.git
cd huhVerify the project builds and tests pass:
go build ./...
go test ./...Explore the project structure:
ls -la
ls field*.go
cat theme.go | head -50Understand the existing patterns before parallelizing:
field_input.go,field_select.goshow how field types are structuredtheme.goshows how themes are definedhuh.goshows how fields are registered and orchestrated
Phase 1: Create worktrees
Create two worktrees for parallel development:
# Create worktree for Feature A (FilePicker)
git worktree add -b feature/filepicker ../huh-filepicker main
# Create worktree for Feature B (HighContrast theme)
git worktree add -b feature/high-contrast ../huh-highcontrast main
# Verify worktree setup
git worktree listThe directory structure now looks like:
~/projects/
├── huh/ # main worktree (stay on main)
├── huh-filepicker/ # Feature A worktree
└── huh-highcontrast/ # Feature B worktreeEach worktree has its own branch. Changes in one worktree do not affect the others until branches merge.
Phase 2: Parallel agent sessions
Open two terminal windows (or tmux panes, or IDE splits). Launch separate Claude Code sessions in each worktree.
Terminal 1 - Feature A:
cd ../huh-filepicker
claudeTerminal 2 - Feature B:
cd ../huh-highcontrast
claudePrompt for Feature A (FilePicker)
Add a new FilePicker field type to this forms library.
The FilePicker should:
- Display a file browser interface in the terminal
- Allow navigating up/down through files and into directories
- Support filtering by file extension (e.g., only show .go files)
- Return the selected file path as a string
- Follow the same patterns as existing fields (field_input.go, field_select.go)
Create field_filepicker.go with the implementation.
Add a simple example showing how to use it.
Make sure existing tests still pass.Prompt for Feature B (HighContrast theme)
Add a new HighContrast theme to this forms library.
The theme should:
- Use maximum contrast colors (black/white with bold accents)
- Be optimized for users with visual impairments
- Follow the same structure as existing themes in theme.go
- Work with all existing field types
Add the theme to theme.go and create an example demonstrating it.
Make sure existing tests still pass.Run both agent sessions simultaneously. Switch between terminals to monitor progress. Let each agent work independently without cross-coordination.
What to observe during parallel execution
- Do the agents ask about the same files?
- How long does each feature take independently?
- Does either agent modify files you expected the other to touch?
- Do agents maintain focus on their assigned feature?
Take notes. These observations inform future parallelization decisions.
Phase 3: Commit and prepare to merge
Once both agents complete their work, commit changes in each worktree.
In Terminal 1 (huh-filepicker):
git add .
git commit -m "Add FilePicker field type for file/directory selection"In Terminal 2 (huh-highcontrast):
git add .
git commit -m "Add HighContrast theme for accessibility"Return to the main worktree:
cd ../huhPhase 4: Merge and resolve conflicts
Merge both feature branches into main. The first merge should succeed without conflicts. The second merge will likely produce conflicts.
# Merge Feature A first
git merge feature/filepicker -m "Merge FilePicker field type"
# Merge Feature B (expect conflicts here)
git merge feature/high-contrastWhen conflicts occur, Git reports which files have problems:
Auto-merging huh.go
CONFLICT (content): Merge conflict in huh.go
Auto-merging theme.go
CONFLICT (content): Merge conflict in theme.go
Automatic merge failed; fix conflicts and then commit the result.Resolution workflow
For each conflicted file, the workflow is:
- Examine the conflict
- Understand what both branches intended
- Resolve to preserve both changes
- Verify the resolution compiles
- Run tests
- Stage the resolution
Examine conflicts:
git status
git diff --name-only --diff-filter=UOpen a conflicted file and find the markers:
<<<<<<< HEAD
// Code from Feature A (already merged)
=======
// Code from Feature B (being merged)
>>>>>>> feature/high-contrastResolution options:
Manual resolution: Edit the file directly. Keep both additions, ensuring they do not conflict logically. For import blocks, combine the imports. For registration code, add both registrations. For test files, include tests for both features.
AI-assisted resolution: In Claude Code, request help:
Resolve the merge conflicts in huh.go.
Both features (FilePicker and HighContrast theme) need to be preserved.
The conflicts are in the import block and the field registration section.Always review AI-generated resolutions. The 46% unacceptable rate from research applies here. Verify that both features remain functional after resolution.
Verify each resolution
After resolving each file:
# Check it compiles
go build ./...
# Run tests
go test ./...Only proceed to the next conflicted file if the build and tests pass. Errors compound when multiple resolutions are made without verification.
Complete the merge
Once all conflicts are resolved and tests pass:
git add .
git commit -m "Merge HighContrast theme, resolving conflicts with FilePicker"Phase 5: Cleanup
Remove the worktrees now that features are merged:
git worktree remove ../huh-filepicker
git worktree remove ../huh-highcontrast
# Verify cleanup
git worktree listDelete the feature branches if they are no longer needed:
git branch -d feature/filepicker
git branch -d feature/high-contrastAnalysis
Record your observations from the exercise:
| Metric | Value |
|---|---|
| Time to set up worktrees | |
| Time for Feature A (FilePicker) | |
| Time for Feature B (HighContrast) | |
| Total parallel time | |
| Number of conflicted files | |
| Time to resolve conflicts | |
| Total exercise time |
Compare parallel vs sequential:
If you had done these features sequentially, the time would be Feature A + Feature B. Parallel time is max(Feature A, Feature B) + merge/conflict time. Did parallelization save time overall?
Conflict analysis:
- Which files had conflicts?
- Were the conflicts predictable from the task descriptions?
- Could task boundaries have been drawn differently to avoid conflicts?
- How did AI-assisted resolution compare to manual resolution (if you tried both)?
Reflection questions
Task independence: Were these features as independent as they seemed? What shared infrastructure did both touch? How would you assess task independence before parallelizing in the future?
Prevention vs resolution: Could the conflicts have been prevented?
What if Feature A had been scoped to avoid touching huh.go?
What if both features used separate example files instead of modifying shared ones?
Parallel efficiency: At what point does conflict resolution overhead exceed sequential execution time? For this exercise, was the overhead worth it?
Worktree overhead: Was worktree setup and cleanup time significant? For a smaller feature (15 minutes of agent work), would worktrees still be worthwhile?
Success criteria
- Two worktrees created successfully
- Both agent sessions ran in parallel
- Both features implemented and committed
- First merge completed without conflicts
- Second merge produced conflicts (as expected)
- All conflicts resolved correctly
- Final build succeeds (
go build ./...) - All tests pass (
go test ./...) - Worktrees cleaned up properly
- Analysis section completed
Variations
Variation A: Three-way parallel
Add a third feature (e.g., a DatePicker field type) in a third worktree.
Observe how conflict complexity scales with parallelism.
Three branches merging produce more conflict combinations than two.
Variation B: Conflict prevention
Before creating worktrees, analyze the features and identify likely conflict points. Scope the tasks explicitly to avoid shared files:
- Feature A works only in
field_filepicker.goandfilepicker_example.go - Feature B works only in
theme.goandtheme_example.go
Run the exercise with these boundaries. Do conflicts still occur? Was the scoping effort worth the prevention?
Variation C: Different languages
Repeat the exercise with a TypeScript or Python repository. The tiged/tiged scaffolding tool or wbolster/jsonlines library work well. Do worktree workflows differ between language ecosystems? How do dependency installation times affect the overhead calculation?
Variation D: Sequential baseline
Do the features sequentially in a single worktree without branching. Measure the total time. Compare directly to your parallel time. For these specific features, which approach was faster?
What this exercise teaches
Worktrees enable parallel agent work by providing isolation. Without them, two agents modifying the same repository create file conflicts, context pollution, and build state interference. With them, each agent operates independently until merge time.
Merge conflicts are the cost of parallelization. They are not failures they are expected outcomes when multiple streams of work converge. The question is whether parallel development time saved exceeds conflict resolution time spent.
Prevention beats resolution. Clear task boundaries, explicit file ownership, and careful scoping reduce conflicts before they occur. When parallelizing, the analysis phase (determining what each agent will touch) matters as much as the execution phase.
AI tools assist but do not replace judgment. AI-assisted merge resolution accelerates the mechanical parts of conflict resolution but requires human review. The 46% unacceptable rate from research is not a failure of AI it reflects the inherent difficulty of merging code with conflicting intentions.
The workflow compounds. Worktree creation, parallel execution, and conflict resolution become faster with practice. The exercise simulates what becomes routine in ASD work: spinning up parallel sessions for independent tasks and integrating the results.