https://github.com/andersonkrs/twig
A glamorous tmux session manager with git worktree support.
https://github.com/andersonkrs/twig
cli developer-tools git-worktree productivity rust session-manager terminal tmux tmuxinator
Last synced: 10 days ago
JSON representation
A glamorous tmux session manager with git worktree support.
- Host: GitHub
- URL: https://github.com/andersonkrs/twig
- Owner: andersonkrs
- Created: 2026-01-24T10:39:35.000Z (18 days ago)
- Default Branch: main
- Last Pushed: 2026-01-31T22:21:44.000Z (10 days ago)
- Last Synced: 2026-02-01T02:05:54.676Z (10 days ago)
- Topics: cli, developer-tools, git-worktree, productivity, rust, session-manager, terminal, tmux, tmuxinator
- Language: Rust
- Homepage:
- Size: 230 KB
- Stars: 5
- Watchers: 0
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# twig
A tmux session manager with git worktree support, inspired by [tmuxinator](https://github.com/tmuxinator/tmuxinator).
Built to scratch my own itch. Terminal UI built with [Ratatui](https://ratatui.rs/).
When you are juggling features, fixes, and reviews, [git worktree](https://git-scm.com/docs/git-worktree)
lets you keep multiple branches checked out side by side. Twig ties each worktree to a tmux
session and provides a snappy TUI so you can spin up a clean, focused workspace per branch in
seconds.
https://github.com/user-attachments/assets/95e21d30-a055-4c1b-b0b6-dcccb61dd53e
## Requirements
- `tmux`
- `git`
## Installation
We recommend using [mise](https://mise.jdx.dev/) to install.
### Via mise
```bash
mise use -g cargo:https://github.com/andersonkrs/twig
```
This compiles twig from source and installs it globally.
### From source (for development)
```bash
git clone https://github.com/andersonkrs/twig.git ~/Work/twig
cd ~/Work/twig
# Install all tools (rust, lefthook) + git hooks
mise install
# Build
cargo build --release
# Symlink to PATH
ln -s ~/Work/twig/target/release/twig ~/.local/bin/twig
```
## Usage
```bash
twig start [project] # Start/attach to session (interactive if no arg)
twig list # List all projects/worktrees
twig list --focus-current # Focus current TWIG_PROJECT/TWIG_WORKTREE
twig new [name|repo_url] # Create new project (accepts name or git URL)
twig edit [project] # Open config in $EDITOR
twig delete [project] # Delete project config
twig stop [project] # Kill tmux session
# Debug tmux control-mode I/O
Use `--verbose` (or `TWIG_DEBUG=1`) to enable verbose tmux control output on stderr.
twig --verbose window new [project] [name]
# Run a command in a window/pane
twig run --project=dotfiles --window=6 --pane=1 -- whoami
# Run a command in a worktree session
twig run --project=dotfiles --tree=feature-x --window=1 -- btop
# Worktree commands
twig tree create [project] [branch] # Create worktree + session
twig tree list [project] # List worktrees
twig tree delete [project] [branch] # Delete worktree + kill session
```
When creating a project with a git URL, twig extracts the project name automatically:
```bash
twig new git@github.com:user/myproject.git # Creates project "myproject"
```
Aliases: `ls` for `list`, `s` for `start`, `n` for `new`, `e` for `edit`, `rm` for `delete`, `t` for `tree`
## Configuration
### Global Config
Location: `~/.config/twig/config.yml`
```yaml
# Base path for worktrees (default: ~/Work/.trees)
# Worktrees are created at: {worktree_base}/{project}/{branch}
worktree_base: ~/Work/.trees
# Projects directory (default: ~/.config/twig/projects)
projects_dir: ~/.config/twig/projects
```
### Project Config
Location: `~/.config/twig/projects/.yml`
```yaml
name: myproject
root: ~/Work/myproject
# Optional: git repo URL (https or ssh)
# If root doesn't exist, twig will clone this repo on first start
repo: git@github.com:user/myproject.git
windows:
# Simple window with command
- git: lazygit
# Empty shell window
- shell:
# Window with multiple panes
- editor:
panes:
- nvim
# Window with layout and multiple panes
- servers:
layout: main-vertical # main-vertical, main-horizontal, even-vertical, even-horizontal, tiled
panes:
- rails server
- bin/sidekiq
# Optional: worktree configuration
worktree:
# Files/folders to copy from parent project to worktree
copy:
- .env
- .env.local
- config/master.key
# Files/folders to symlink from parent project to worktree
# Only supported on Unix
symlink:
- .env
# Commands to run after worktree creation
post_create:
- bundle install
- yarn install
- rails db:migrate
# Note: post_create runs inside a temporary setup window in the worktree session
# so your shell init and environment (mise/rbenv/etc) are applied.
```
### Example Configs
**Rails project:**
```yaml
name: myapp
root: ~/Work/myapp
windows:
- editor:
panes:
- nvim
- shell:
- rails:
layout: main-vertical
panes:
- rails server
- bin/sidekiq
- console: rails console
- git: lazygit
worktree:
copy:
- .env
- .env.local
- config/master.key
- config/credentials.yml.enc
symlink:
- .env
post_create:
- bundle install
- yarn install
- bin/rails db:prepare
```
**Simple project:**
```yaml
name: dotfiles
root: ~/.dotfiles
windows:
- editor:
panes:
- nvim
- shell:
- shell:
- git: lazygit
```
## How It Works
### Sessions
When you run `twig start `:
1. Checks if session already exists → attaches if so
2. Creates new tmux session with configured windows/panes
3. Runs commands in each pane
4. Attaches to the session (or switches if already in tmux)
### Worktrees
When you run `twig tree create `:
1. Creates git worktree at `{worktree_base}/{project}/{branch}`
2. Creates the branch if it doesn't exist
3. Copies and symlinks configured files from parent project
4. Runs post-create commands
5. Starts a tmux session named `{project}__{branch}`
Session naming: `myproject__feature-auth` (double underscore separator)
Worktree path: `~/Work/.trees/myproject/feature-auth`
When you run `twig tree delete `:
1. Kills the tmux session if running
2. Removes the git worktree
## Tmux Popup Session Picker
You can replace the tmux session picker with a popup that calls `twig ls --focus-current`.
This uses the `TWIG_PROJECT` and `TWIG_WORKTREE` environment variables to focus the cursor
on the current project/worktree when available.
Add a key binding to your `~/.tmux.conf`:
```tmux
# Twig popup
unbind s
bind-key s display-popup -E -w 80% -h 60% "twig ls --focus-current"
```
If you want the popup to always open from anywhere (not just inside a twig session), it
will still work but will fall back to the first project when the env vars are not set.
## Releases
- Releases are managed by release-plz using conventional commits to determine the bump.
- A release PR is created/updated on every push to `main`.
- Merge the release PR to tag and publish a GitHub release; binaries are uploaded for
linux x86_64 and macOS universal2.
## Development
```bash
# Install dependencies + git hooks
mise install
# Build
cargo build --release
```
Formatting and linting are automatically run by lefthook on pre-commit.
## License
MIT