worktrunk 0.42.0

A CLI for Git worktree management, designed for parallel AI agent workflows
Documentation
//! Worktree operations with file-based shell integration.
//!
//! # The Directory Change Problem
//!
//! Worktree commands (`switch`, `remove`, `merge`) need to change the user's working directory,
//! but there's a fundamental Unix limitation: **child processes cannot change their parent's
//! working directory**. This is a security feature and core Unix design principle.
//!
//! When a user runs `wt switch my-feature`, the `wt` binary runs as a child process of the shell.
//! The binary can change *its own* working directory, but when it exits, the parent shell remains
//! in the original directory.
//!
//! # Solution: Split File-Based Directive Passing
//!
//! Shell wrappers create two temp files and set `WORKTRUNK_DIRECTIVE_CD_FILE`
//! and `WORKTRUNK_DIRECTIVE_EXEC_FILE` to their paths:
//!
//! 1. Shell wrapper creates two temp files via `mktemp` (cd and exec)
//! 2. Shell wrapper sets `WORKTRUNK_DIRECTIVE_CD_FILE` and `WORKTRUNK_DIRECTIVE_EXEC_FILE`
//! 3. wt binary writes a raw path to the CD file (no shell escaping)
//! 4. wt writes arbitrary shell to the EXEC file (only for `--execute`)
//! 5. Shell wrapper reads the CD file with `cd -- "$(< file)"` (no shell parsing)
//! 6. Shell wrapper sources the EXEC file if non-empty
//!
//! ## Without Shell Integration (Direct Binary Call)
//!
//! ```bash
//! $ wt switch my-feature
//! Created new branch and worktree for 'my-feature' @ /path/to/worktree
//!
//! Run `wt config shell install` to enable automatic cd
//!
//! $ pwd
//! /original/directory  # ← User is still here!
//! ```
//!
//! The binary performs git operations and prints user-friendly messages, but **cannot** change
//! the parent shell's directory. User must manually `cd` to the worktree.
//!
//! ## With Shell Integration
//!
//! ```bash
//! $ wt switch my-feature
//! Created new branch and worktree for 'my-feature' @ /path/to/worktree
//!
//! $ pwd
//! /path/to/worktree  # ← Automatically changed!
//! ```
//!
//! When shell integration is enabled (`eval "$(wt config shell init bash)"`), the shell wrapper:
//!
//! 1. Creates two temp files and sets the CD and EXEC directive env vars
//! 2. Runs the wt binary (which writes a raw path to the CD file)
//! 3. Reads the CD file with `cd -- "$(< file)"` after wt exits
//!
//! # Implementation Details
//!
//! Result types (`SwitchResult`, `RemoveResult`) are pure data structures that only contain
//! operation results. All presentation logic is handled by the `output` module:
//!
//! - `output::handle_switch_output()`: Formats and outputs switch operation results
//! - `output::handle_remove_output()`: Formats and outputs remove operation results
//!
//! The output handlers check `is_shell_integration_active()` to determine if hints should
//! be suppressed (when shell integration is already configured).
//!
//! ## Exit Code Semantics
//!
//! When using `-x` to execute commands after switching:
//!
//! - **If wt operation fails**: Returns wt's exit code (command never executes)
//! - **If wt succeeds but command fails**: Returns the command's exit code
//! - **Rationale**: Enables command chaining with proper error propagation
//!
//! Example:
//! ```bash
//! wt switch feature -x "cargo build" && cargo test
//! # If wt fails (e.g., worktree doesn't exist), cargo build never runs
//! # If cargo build fails, cargo test doesn't run (exit code propagates)
//! ```
//!
//! The shell wrapper is generated by `wt config shell init <shell>` from templates in `templates/`.

pub(crate) mod hooks;
mod push;
mod resolve;
mod switch;
mod types;

// Re-export public types and functions
pub use push::{handle_no_ff_merge, handle_push};
pub(crate) use resolve::paths_match;
pub use resolve::{
    compute_worktree_path, is_worktree_at_expected_path, offer_bare_repo_worktree_path_fix,
    path_mismatch, resolve_worktree_arg, worktree_display_name,
};
pub use switch::{execute_switch, plan_switch};
pub use types::{
    MergeOperations, OperationMode, RemoveResult, SwitchBranchInfo, SwitchPlan, SwitchResult,
};