# Shell Integration Demo
This document demonstrates how Worktrunk's shell integration works in practice.
## Setup
1. Build worktrunk:
```bash
cargo build --release
```
2. Add shell integration to your shell config:
**Bash** (`~/.bashrc`):
```bash
eval "$(wt init bash)"
```
**Fish** (`~/.config/fish/config.fish`):
```fish
## Demo: How It Works
### Step 1: Generate Shell Integration Code
```bash
$ wt init bash
# worktrunk shell integration for bash
# Generated by: wt init bash
# Helper function to parse wt output and handle directives
_wt_exec() {
local output line exit_code
output="$("wt" "$@" 2>&1)"
exit_code=$?
# Parse output line by line
while IFS= read -r line; do
if [[ "$line" == __WORKTRUNK_CD__* ]]; then
# Extract path and change directory
\cd "${line#__WORKTRUNK_CD__}"
else
# Regular output - print it
echo "$line"
fi
done <<< "$output"
return $exit_code
}
# Override wt command to add --internal flag for switch and finish
wt() {
local subcommand="$1"
case "$subcommand" in
switch|finish)
# Commands that need --internal for directory change support
shift
_wt_exec "$subcommand" --internal "$@"
;;
*)
# All other commands pass through directly
command wt "$@"
;;
esac
}
# ... (more code)
```
### Step 2: Understanding the Directive Protocol
When you run `wt switch --internal my-feature`, the binary outputs:
```
__WORKTRUNK_CD__/path/to/worktree
Switched to worktree: my-feature
```
The shell wrapper:
1. Captures all output
2. Parses line by line
3. Executes `cd /path/to/worktree` when it sees `__WORKTRUNK_CD__`
4. Prints other lines normally
### Step 3: Using the Shell Integration
```bash
# After sourcing the integration code:
$ eval "$(wt init bash)"
# Now you can use wt commands:
$ wt switch feature-x
__WORKTRUNK_CD__/tmp/example-worktree
Switched to worktree: feature-x
# Your shell automatically cd'd to the worktree!
$ pwd
/tmp/example-worktree
```
## Customization Examples
### Custom Command Prefix
```bash
# Use a custom prefix instead of default 'wt'
$ eval "$(wt init bash --cmd myprefix)"
# Now use myprefix commands:
$ myprefix switch feature
$ myprefix finish
$ myprefix list
```
## Implementation Architecture
```
┌─────────────────┐
│ User Shell │
│ (bash/fish) │
└────────┬────────┘
│
│ eval "$(wt init bash)"
▼
┌─────────────────┐
│ Shell Wrapper │ Generated by templates/bash.sh
│ Functions: │
│ - wt() │ Intercepts: wt switch, wt finish
│ - _wt_exec │ Parses: __WORKTRUNK_CD__ directives
└────────┬────────┘
│
│ wt switch --internal my-branch
▼
┌─────────────────┐
│ Worktrunk Bin │ Rust application
│ (Rust) │
│ │ Outputs:
│ Commands: │ - __WORKTRUNK_CD__/path/to/worktree
│ - switch │ - Regular messages
│ - finish │
│ - list │
└─────────────────┘
```
## Testing the Integration
```bash
# Run integration tests
chmod +x .tmp/test_integration.sh
./.tmp/test_integration.sh
# Expected output:
# Testing worktrunk shell integration...
#
# Test 1: Generate bash integration
# ✓ Bash integration generated successfully
#
# Test 2: Generate fish integration
# ✓ Fish integration generated successfully
#
# Test 3: Test custom command prefix
# ✓ Custom command prefix works
#
# Test 4: Test directive output
# ✓ Directive output works
#
# Test 5: Simulate shell wrapper behavior
# ✓ Shell wrapper functions work
#
# All tests passed! ✓
```
## Why This Pattern?
This "eval init" pattern is proven by successful tools:
- **zoxide**: Smarter cd command with frequency tracking
- **starship**: Cross-shell prompt customization
- **direnv**: Per-directory environment loading
- **pyenv**: Python version management
### Benefits:
1. **Clean separation**: Rust handles git logic, shell handles `cd`
2. **Type-safe templates**: Askama generates shell code at compile time
3. **Progressive enhancement**: Works without integration, better with it
4. **Shell-agnostic**: Same pattern works across bash, fish, zsh
5. **Minimal overhead**: Generated functions are lightweight
6. **Debuggable**: Easy to see exactly what shell code is generated
### Key Design Decisions:
- Use `--internal` flag (hidden from `--help`) for directive mode
- Directives use `__WORKTRUNK_CD__` prefix (unlikely to conflict with real output)
- Shell wrapper preserves exit codes
- Regular output passes through unchanged
- No state maintained by binary (stateless)