# lazygit - Product Requirements Document

## Overview

**lazygit** is a simple terminal UI for git commands, written in Go. It provides an intuitive, keyboard-driven interface for managing git repositories without memorizing complex git commands.

- **Version**: 0.58.1
- **Author**: Jesse Duffield
- **Repository**: https://github.com/jesseduffield/lazygit
- **License**: MIT

## Table of Contents

1. [Core Concepts](#core-concepts)
2. [User Interface](#user-interface)
3. [Panel System](#panel-system)
4. [Keybindings](#keybindings)
5. [Git Operations](#git-operations)
6. [Configuration](#configuration)
7. [CLI Interface](#cli-interface)
8. [Automation with VHS](#automation-with-vhs)

---

## Core Concepts

### Design Philosophy

- **Keyboard-first**: All operations accessible via keyboard shortcuts
- **Context-aware**: Keybindings change based on focused panel and selected item
- **Visual feedback**: Real-time diff views, color-coded file states
- **Non-destructive**: Confirmation prompts for dangerous operations
- **Discoverable**: Built-in help system (`?`) shows available actions

### File States

| Indicator | Meaning |
|-----------|---------|
| `M` | Modified (tracked file changed) |
| `A` | Added (new file staged) |
| `D` | Deleted |
| `R` | Renamed |
| `C` | Copied |
| `??` | Untracked (new file not staged) |
| `UU` | Unmerged (conflict) |

---

## User Interface

### Layout Overview

```
+--[1]-Status---------+--[0]-Main View (Diff/Log/Patch)--------+
| repo-name -> branch |                                         |
+--[2]-Files----------+                                         |
| Files/Worktrees/    |                                         |
| Submodules          |                                         |
+--[3]-Branches-------+                                         |
| Local/Remotes/Tags  |                                         |
+--[4]-Commits--------+-----------------------------------------+
| Commits/Reflog      |--Command log---------------------------+|
+--[5]-Stash----------+                                        ||
| Stash entries       |                                        ||
+---------------------+----------------------------------------++
| Status bar: Quick actions | Keybindings: ? |    Version 0.58.1|
+------------------------------------------------------------------+
```

### Panel Numbers

| # | Panel | Description |
|---|-------|-------------|
| 0 | Main View | Displays diffs, logs, patches, commit details |
| 1 | Status | Repository name and current branch |
| 2 | Files | Working tree changes, worktrees, submodules |
| 3 | Branches | Local branches, remotes, tags |
| 4 | Commits | Commit history, reflog |
| 5 | Stash | Stash entries |

### Navigation Between Panels

| Key | Action |
|-----|--------|
| `1-5` | Jump directly to panel by number |
| `0` | Focus main view |
| `h/l` or `Left/Right` | Move between panels |
| `Tab` | Toggle between side panels and main view |
| `[` / `]` | Switch tabs within a panel |

### Screen Modes

| Key | Mode | Description |
|-----|------|-------------|
| `+` | Next screen mode | Cycles: normal -> half -> full |
| `_` | Previous screen mode | Cycles backwards |

---

## Panel System

### Panel 1: Status

Displays the repository name and current branch.

**Actions:**
| Key | Action |
|-----|--------|
| `Enter` | Recent repositories |
| `a` | All branches log graph |
| `u` | Check for updates |

### Panel 2: Files / Worktrees / Submodules

**Tabs:** Files | Worktrees | Submodules

#### Files Tab

**File Operations:**
| Key | Action |
|-----|--------|
| `Space` | Stage/unstage file |
| `a` | Stage/unstage all files |
| `Enter` | Enter staging view (line-by-line staging) |
| `d` | Discard changes |
| `D` | Reset options menu |
| `e` | Edit file |
| `o` | Open file |
| `i` | Ignore file (.gitignore) |
| `r` | Refresh files |
| `` ` `` | Toggle file tree view |
| `-` | Collapse all directories |
| `=` | Expand all directories |

**Commit Operations:**
| Key | Action |
|-----|--------|
| `c` | Commit staged changes |
| `C` | Commit with editor |
| `w` | Commit without pre-commit hook |
| `A` | Amend last commit |
| `Ctrl+f` | Find base commit for fixup |

**Stash Operations:**
| Key | Action |
|-----|--------|
| `s` | Stash all changes |
| `S` | Stash options menu |

**Stash Options Menu:**
- `a` - Stash all changes
- `i` - Stash all changes and keep index
- `U` - Stash all changes including untracked files
- `s` - Stash staged changes
- `u` - Stash unstaged changes

**Reset Options Menu (`D`):**
- `u` - Discard unstaged changes (`git checkout -- .`)
- `d` - Discard untracked files (`git clean -fd`)
- `S` - Discard staged changes (`stash staged and drop stash`)
- `s` - Soft reset (`git reset --soft HEAD`)
- `m` - Mixed reset (`git reset --mixed HEAD`)
- `h` - Hard reset (`git reset --hard HEAD`)

#### Worktrees Tab

| Key | Action |
|-----|--------|
| `n` | New worktree |
| `Space` | Switch to worktree |
| `d` | Remove worktree |
| `w` | View worktree options |

#### Submodules Tab

| Key | Action |
|-----|--------|
| `i` | Initialize submodule |
| `u` | Update submodule |
| `b` | Bulk menu |
| `Enter` | Enter submodule |

### Panel 3: Local Branches / Remotes / Tags

**Tabs:** Local branches | Remotes | Tags

#### Local Branches Tab

| Key | Action |
|-----|--------|
| `Space` | Checkout branch |
| `n` | New branch |
| `d` | Delete branch |
| `r` | Rebase current branch onto selected |
| `R` | Rename branch |
| `M` | Merge selected into current branch |
| `f` | Fast-forward branch |
| `F` | Force checkout |
| `-` | Checkout previous branch |
| `u` | Set upstream |
| `i` | View git-flow options |
| `o` | Create pull request |
| `O` | View pull request options |
| `Ctrl+y` | Copy pull request URL |
| `T` | Create tag |
| `s` | Sort order |

**Rebase Menu (`r`):**
- `s` - Simple rebase onto selected branch
- `i` - Interactive rebase onto selected branch
- `b` - Rebase onto base branch

#### Remotes Tab

| Key | Action |
|-----|--------|
| `Enter` | View branches |
| `n` | New remote |
| `d` | Remove remote |
| `e` | Edit remote |
| `f` | Fetch from remote |
| `F` | Add fork remote |

#### Tags Tab

| Key | Action |
|-----|--------|
| `Ctrl+o` | Copy tag to clipboard |
| `Space` | Checkout tag |
| `n` | New tag |
| `d` | Delete tag |
| `P` | Push tag |
| `g` | Reset to tag |
| `Enter` | View commits |
| `w` | View worktree options |

### Panel 4: Commits / Reflog

**Tabs:** Commits | Reflog

#### Commits Tab

**Navigation & Selection:**
| Key | Action |
|-----|--------|
| `j/k` | Move up/down |
| `Space` | Checkout commit |
| `Enter` | View commit files |
| `v` | Toggle range select |
| `*` | Select commits of current branch |

**Commit Manipulation:**
| Key | Action |
|-----|--------|
| `r` | Reword commit message |
| `R` | Reword with editor |
| `e` | Edit commit (start interactive rebase) |
| `d` | Drop commit |
| `s` | Squash down |
| `S` | Squash all above commits |
| `f` | Mark as fixup |
| `F` | Create fixup commit |
| `p` | Pick commit |
| `Ctrl+j` | Move commit down |
| `Ctrl+k` | Move commit up |
| `i` | Start interactive rebase |

**Advanced Operations:**
| Key | Action |
|-----|--------|
| `A` | Amend commit with staged changes |
| `a` | Reset commit author |
| `t` | Revert commit |
| `T` | Tag commit |
| `C` | Cherry-pick copy |
| `V` | Paste (cherry-pick) commits |
| `Ctrl+R` | Reset cherry-pick selection |
| `B` | Mark as base for rebase |
| `b` | View bisect options |
| `g` | View reset options |
| `y` | Copy commit attribute to clipboard |
| `o` | Open commit in browser |
| `Ctrl+l` | Open log menu |
| `n` | Create new branch off commit |

**Bisect Menu (`b`):**
- `b` - Mark commit as bad (start bisect)
- `g` - Mark commit as good (start bisect)
- `t` - Choose bisect terms
- Cancel

#### Reflog Tab

Shows the reference log for recovering lost commits.

| Key | Action |
|-----|--------|
| `Space` | Checkout reflog entry |
| `g` | View reset options |
| `C` | Cherry-pick copy |
| `V` | Paste commits |

### Panel 5: Stash

| Key | Action |
|-----|--------|
| `Space` | Apply stash |
| `g` | Pop stash |
| `d` | Drop stash |
| `n` | New branch from stash |
| `r` | Rename stash |
| `Enter` | View stash files |

---

## Keybindings

### Global Keybindings

**Navigation:**
| Key | Action |
|-----|--------|
| `j/k` or `Up/Down` | Move up/down in list |
| `h/l` or `Left/Right` | Move between panels |
| `<` / `>` | Go to top/bottom of list |
| `Home` / `End` | Go to top/bottom of list |
| `,` / `.` | Page up/down |
| `PgUp` / `PgDown` | Scroll main window |
| `J/K` or `Ctrl+u/Ctrl+d` | Scroll main window |
| `H` / `L` | Scroll left/right |

**Actions:**
| Key | Action |
|-----|--------|
| `?` | Show keybindings help |
| `Enter` | Confirm / Go into |
| `Esc` | Return / Cancel |
| `Space` | Primary action (context-dependent) |
| `/` | Start search |
| `n` / `N` | Next/previous search match |
| `q` | Quit |
| `Q` | Quit without changing directory |
| `Ctrl+c` | Quit (alternative) |
| `Ctrl+z` | Suspend application |

**Git Operations:**
| Key | Action |
|-----|--------|
| `P` | Push |
| `p` | Pull |
| `f` | Fetch (in files panel) |
| `R` | Refresh |
| `z` | Undo (reflog) |
| `Z` | Redo (reflog) |
| `m` | View merge/rebase options |

**View Options:**
| Key | Action |
|-----|--------|
| `@` | View command log options |
| `+` / `_` | Next/previous screen mode |
| `\|` | Cycle pagers |
| `W` or `Ctrl+e` | Diffing menu |
| `Ctrl+w` | Toggle whitespace in diff |
| `}` / `{` | Increase/decrease diff context |
| `)` / `(` | Increase/decrease rename similarity threshold |
| `Ctrl+t` | Open external diff tool |
| `Ctrl+s` | Filtering menu |

**Other:**
| Key | Action |
|-----|--------|
| `:` | Execute shell command |
| `Ctrl+r` | Switch to recent repo |
| `Ctrl+o` | Copy to clipboard |
| `Ctrl+p` | View custom patch options |

### Staging View Keybindings

When viewing a file's diff (entered via `Enter` on a file):

| Key | Action |
|-----|--------|
| `Space` | Stage/unstage line |
| `a` | Toggle select hunk |
| `A` | Stage/unstage all changes |
| `v` | Toggle range select |
| `j/k` | Move up/down |
| `J/K` | Scroll diff up/down |
| `E` | Edit hunk in editor |
| `e` | Edit file |
| `o` | Open file |
| `Esc` | Return to files panel |
| `Tab` | Switch to staged/unstaged changes |
| `b` | Pick both hunks (merge conflicts) |

---

## Git Operations

### Committing

1. **Stage changes**: `Space` on files or `a` to stage all
2. **Commit**: `c` to commit with inline message
3. **Commit with editor**: `C` to open editor for commit message
4. **Amend**: `A` to amend the last commit with staged changes
5. **Commit without hooks**: `w` to skip pre-commit hooks

### Branching

1. **Create branch**: `n` in branches panel
2. **Checkout**: `Space` on branch
3. **Delete**: `d` on branch
4. **Rename**: `R` on branch
5. **Checkout previous**: `-` in branches panel

### Merging

1. Navigate to branches panel (`3`)
2. Select the branch to merge
3. Press `M` to merge into current branch

**During merge conflicts:**
- Files with `UU` status indicate conflicts
- Enter file to resolve conflicts line-by-line
- Use `b` to pick both sides
- Stage resolved files with `Space`
- Continue merge with `m` -> continue option

### Rebasing

**Simple rebase:**
1. Go to branches panel
2. Select target branch
3. Press `r` to open rebase menu
4. Choose rebase type

**Interactive rebase:**
1. Go to commits panel
2. Navigate to the commit before where you want to start
3. Press `i` to start interactive rebase
4. Use `p` (pick), `s` (squash), `f` (fixup), `d` (drop), `e` (edit)
5. Reorder commits with `Ctrl+j/k`
6. Press `m` to view rebase options and continue/abort

### Cherry-picking

1. Navigate to the commit to cherry-pick
2. Press `C` to copy the commit
3. Switch to the target branch
4. Press `V` to paste (cherry-pick)
5. Use `Ctrl+R` to reset cherry-pick selection

### Stashing

**Quick stash:**
- `s` in files panel stashes all changes

**Stash options (`S`):**
- Stash all changes
- Stash including untracked
- Stash only staged
- Stash only unstaged
- Keep index

**Using stashes:**
- `Space` - Apply stash (keep stash)
- `g` - Pop stash (apply and remove)
- `d` - Drop stash

### Bisecting

1. Go to commits panel
2. Press `b` to open bisect menu
3. Mark a known bad commit with `b`
4. Mark a known good commit with `g`
5. Test each commit lazygit checks out
6. Mark as good/bad until bug is found
7. Reset bisect when done

### Working with Remotes

**Push:**
- `P` globally pushes current branch
- Force push available in push options menu

**Pull:**
- `p` globally pulls current branch
- Configurable pull strategy (merge/rebase)

**Fetch:**
- `f` in files panel fetches from remote
- Auto-fetch configurable in settings

---

## Configuration

### Configuration File Location

```bash
lazygit --print-config-dir  # Shows config directory
# Usually: ~/.config/lazygit/config.yml
```

### Key Configuration Options

```yaml
gui:
  # Panel sizing
  sidePanelWidth: 0.3333
  expandFocusedSidePanel: false
  mainPanelSplitMode: flexible  # flexible | horizontal | vertical

  # Display options
  showFileTree: true
  showIcons: false
  nerdFontsVersion: ""  # Set to "3" for nerd fonts v3
  showCommandLog: true
  showBottomLine: true
  showPanelJumps: true

  # Behavior
  mouseEvents: true
  skipDiscardChangeWarning: false
  skipStashWarning: false

  # Theme colors
  theme:
    activeBorderColor:
      - green
      - bold
    inactiveBorderColor:
      - default
    selectedLineBgColor:
      - blue
    unstagedChangesColor:
      - red

git:
  # Auto operations
  autoFetch: true
  autoRefresh: true
  fetchAll: true

  # Commit settings
  commit:
    signOff: false
    autoWrapCommitMessage: true
    autoWrapWidth: 72

  # Merge settings
  merging:
    manualCommit: false
    args: ""

  # Main branches for rebase targets
  mainBranches:
    - master
    - main

  # Log display
  log:
    order: topo-order  # topo-order | date-order | author-date-order
    showGraph: always  # always | never | when-maximised

# Refresh intervals (seconds)
refresher:
  refreshInterval: 10
  fetchInterval: 60

# Confirmation settings
confirmOnQuit: false
quitOnTopLevelReturn: false

# Custom commands (advanced)
customCommands: []
```

### Custom Keybindings

Keybindings can be customized in `config.yml`:

```yaml
keybinding:
  universal:
    quit: q
    return: <esc>
    togglePanel: <tab>
    prevItem: <up>
    nextItem: <down>
    # ... etc
  files:
    commitChanges: c
    amendLastCommit: A
    # ... etc
  branches:
    createPullRequest: o
    rebaseBranch: r
    # ... etc
```

### Custom Commands

Define custom commands accessible via keybindings:

```yaml
customCommands:
  - key: "C"
    command: "git cz"  # Commitizen
    context: "files"
    loadingText: "Opening commitizen"
    subprocess: true
  - key: "b"
    command: "git blame {{.SelectedFile.Name}}"
    context: "files"
    loadingText: "Blaming file"
```

---

## CLI Interface

### Basic Usage

```bash
lazygit                    # Open in current directory
lazygit -p /path/to/repo   # Open specific repository
lazygit status             # Focus status panel on open
lazygit branch             # Focus branch panel on open
lazygit log                # Focus log panel on open
lazygit stash              # Focus stash panel on open
```

### Command Line Flags

| Flag | Description |
|------|-------------|
| `-h, --help` | Display help |
| `-v, --version` | Print version |
| `-p, --path PATH` | Path to git repo |
| `-f, --filter PATH` | Filter log by path |
| `-c, --config` | Print default config |
| `-cd, --print-config-dir` | Print config directory |
| `-ucd, --use-config-dir DIR` | Override config directory |
| `-ucf, --use-config-file FILES` | Comma-separated config files |
| `-w, --work-tree PATH` | Git work-tree argument |
| `-g, --git-dir PATH` | Git git-dir argument |
| `-sm, --screen-mode MODE` | Initial screen mode: normal, half, full |
| `-d, --debug` | Run in debug mode with logging |
| `-l, --logs` | Tail lazygit logs |
| `--profile` | Start profiler on port 6060 |

### Examples

```bash
# Open repo at specific path
lazygit -p ~/projects/myrepo

# Filter commits by file path
lazygit -f src/main.js

# Use custom config
lazygit -ucf ~/.config/lazygit/work-config.yml

# Start in full screen mode
lazygit -sm full

# Debug mode
lazygit -d
# In another terminal:
lazygit -l  # Watch logs
```

---

## Automation with VHS

[VHS](https://github.com/charmbracelet/vhs) can be used to programmatically control lazygit for demos, testing, and documentation.

### VHS Tape Syntax

```tape
# Configure output
Output "demo.gif"
Set Shell "bash"
Set FontSize 14
Set Width 1200
Set Height 800

# Launch lazygit
Type "cd /path/to/repo && lazygit"
Enter
Sleep 2s

# Navigate with keyboard
Type "2"          # Go to files panel
Sleep 500ms
Type "j"          # Move down
Sleep 500ms
Space             # Stage file
Sleep 500ms
Type "c"          # Start commit
Sleep 1s
Type "Add new feature"
Enter
Sleep 1s

# Capture screenshots
Screenshot "commit-complete.png"

# Quit
Type "q"
```

### VHS Commands for lazygit

| Command | Usage | Description |
|---------|-------|-------------|
| `Type "x"` | `Type "c"` | Type character (triggers keybinding) |
| `Enter` | `Enter` | Press Enter key |
| `Escape` | `Escape` | Press Escape key |
| `Space` | `Space` | Press Space key |
| `Tab` | `Tab` | Press Tab key |
| `Up/Down/Left/Right` | `Down` | Arrow keys |
| `Sleep Xs` | `Sleep 500ms` | Wait for UI |
| `Screenshot "file.png"` | `Screenshot "/tmp/shot.png"` | Capture frame |

### Example: Automated Commit Demo

```tape
Output "lazygit-commit-demo.gif"
Set Shell "bash"
Set Width 1200
Set Height 800
Set Framerate 10

# Setup
Type "cd /tmp/test-repo && lazygit"
Enter
Sleep 2s

# Show modified files
Type "2"
Sleep 1s

# Stage all changes
Type "a"
Sleep 500ms

# Open commit dialog
Type "c"
Sleep 1s

# Type commit message
Type "feat: add new authentication module"
Enter
Sleep 1s

# Show result
Screenshot "commit-complete.png"
Sleep 2s

# Quit
Type "q"
```

### Running VHS Tapes

```bash
# Run tape and generate output
vhs demo.tape

# Validate tape without running
vhs validate demo.tape

# Record a new tape interactively
vhs record

# Publish GIF to share
vhs publish demo.gif
```

---

## Tips and Tricks

### Productivity Tips

1. **Use panel numbers**: Press `1-5` to jump directly to panels
2. **Toggle views**: Press `+` to maximize the current panel
3. **Filter commits**: Use `/` to search in any list
4. **Quick stash**: Press `s` to stash all changes instantly
5. **Undo mistakes**: Press `z` to undo via reflog
6. **Copy commit hash**: Press `y` on a commit for copy options
7. **Open in browser**: Press `o` on a commit to view on GitHub/GitLab

### Advanced Usage

1. **Patch mode**: Use `Ctrl+p` to create partial patches from commits
2. **Custom commands**: Define frequently used git aliases
3. **Multiple configs**: Use `-ucf` for project-specific settings
4. **Filter mode**: Use `-f` to focus on specific file history

### Keyboard Navigation Summary

```
┌─────────────────────────────────────────┐
│           PANEL NAVIGATION              │
├─────────────────────────────────────────┤
│  1-5: Jump to panel    Tab: Toggle view │
│  h/l: Move left/right  [/]: Switch tabs │
│  j/k: Move up/down     </> : Top/bottom │
├─────────────────────────────────────────┤
│           COMMON ACTIONS                │
├─────────────────────────────────────────┤
│  Space: Primary action  Enter: Go into  │
│  c: Commit             P: Push  p: Pull │
│  s: Stash              z: Undo  ?: Help │
│  /: Search             q: Quit          │
└─────────────────────────────────────────┘
```

---

## Comparison with Other Tools

| Feature | lazygit | tig | gitui | git CLI |
|---------|---------|-----|-------|---------|
| TUI Interface | Yes | Yes | Yes | No |
| Staging View | Line-level | Hunk-level | Line-level | Hunk-level |
| Interactive Rebase | Visual | No | Visual | Editor |
| Merge Conflict UI | Yes | No | Yes | No |
| Customizable | YAML config | Limited | TOML config | Aliases |
| Language | Go | C | Rust | C |
| Cross-platform | Yes | Yes | Yes | Yes |

---

## Resources

- **Documentation**: https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings
- **Configuration**: https://github.com/jesseduffield/lazygit/blob/v0.58.1/docs/Config.md
- **Tutorial Video**: https://youtu.be/VDXvbHZYeKY
- **Issues**: https://github.com/jesseduffield/lazygit/issues
- **Releases**: https://github.com/jesseduffield/lazygit/releases
- **Sponsor**: https://github.com/sponsors/jesseduffield

---

*Document generated through programmatic exploration of lazygit v0.58.1 using VHS automation.*
