GitHub - andersonkrs/twig: A glamorous tmux session manager with git worktree support.

4 min read Original article ↗

twig

A tmux session manager with git worktree support, inspired by tmuxinator.

Built to scratch my own itch. Terminal UI built with Ratatui.

Requirements

  • tmux
  • git

Installation

We recommend using mise to install.

Via mise

mise use -g cargo:https://github.com/andersonkrs/twig

This compiles twig from source and installs it globally.

From source (for development)

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

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

# 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:

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

# 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/<name>.yml

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:

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:

name: dotfiles
root: ~/.dotfiles

windows:
  - editor:
      panes:
        - nvim
  - shell:
  - shell:
  - git: lazygit

How It Works

Sessions

When you run twig start <project>:

  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 <project> <branch>:

  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 <project> <branch>:

  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:

# 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.

Development

# Install dependencies + git hooks
mise install

# Build
cargo build --release

Formatting and linting are automatically run by lefthook on pre-commit.

License

MIT