# GitButler CLI Command Structure: Architecture and Implementation Guide

> Explore the GitButler CLI command structure, detailing its parse-context-dispatch architecture, Clap for parsing, Context for state management, and command implementations for efficient Git workflows.

- Repository: [GitButler/gitbutler](https://github.com/gitbutlerapp/gitbutler)
- Tags: architecture
- Published: 2026-02-16

---

**The GitButler CLI uses a parse-context-dispatch architecture where `clap` handles argument parsing, `but_ctx::Context` manages repository state, and command modules in [`command/vbranch.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/command/vbranch.rs) and [`command/project.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/command/project.rs) implement the core logic.**

The GitButler command-line interface is implemented in the `gitbutler-cli` crate as a thin wrapper around the core library. Understanding the GitButler CLI command structure reveals how the tool bridges user input with the virtual branch management system through a clean separation of concerns.

## CLI Architecture Overview

The pipeline consists of five distinct phases that transform raw command-line input into repository operations:

- **Argument definition** – All CLI flags and subcommands are declared with **clap** macros inside `Args` and nested enums in [`crates/gitbutler-cli/src/args.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/crates/gitbutler-cli/src/args.rs).
- **Parsing** – `clap::Parser::parse()` turns the raw command line into an `Args` struct at line 14 of [`main.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/main.rs).
- **Application context** – A `but_ctx::Context` is discovered from the current directory (or a supplied path) and holds the repo, workspace, and configuration (lines 24-25 of [`main.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/main.rs)).
- **Dispatch** – The `match args.cmd` block routes the request to the appropriate command module (`vbranch` or `project`) at lines 22-48 of [`main.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/main.rs).
- **Command implementation** – Each subcommand is a small, focused function that works against the `Context` in [`command/vbranch.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/command/vbranch.rs) or [`command/project.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/command/project.rs).

## Command Hierarchy and Structure

### Top-Level Commands

The CLI exposes two primary command groups defined in the `Subcommands` enum:

- **branch** (aliased as `vbranch`): Manages virtual branches (stacks) with subcommands including `list`, `apply`, `commit`, `series`, and `create`.
- **project**: Handles repository registration with subcommands `list` and `add`.

### Subcommand Organization

The hierarchy is defined in [`crates/gitbutler-cli/src/args.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/crates/gitbutler-cli/src/args.rs) using nested enums. The `Subcommands` enum branches into `Branch(vbranch::Platform)` or `Project(project::Platform)`, each containing their own `SubCommands` variants. This structure allows the CLI to parse commands like `gitbutler-cli branch create feature/login` by matching the `Branch` variant, then the `Create` subcommand within the `vbranch::Platform` enum.

## Virtual Branch Commands Implementation

### Core Operations

The [`command/vbranch.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/command/vbranch.rs) module implements all stack manipulation logic through focused functions that map directly to CLI subcommands:

- **`list`**: Enumerates stacks via `VirtualBranchesHandle::list_all_stacks()` and prints one-line summaries for each virtual branch.
- **`create`**: Invokes `gitbutler_branch_actions::create_virtual_branch` with a `BranchCreateRequest` to initialize new stacks.
- **`apply`**: Supports two distinct modes—`apply_by_name` activates existing virtual branches by name, while `apply_from_branch` converts real Git branches into virtual stacks when the `--branch` flag is provided.
- **`commit`**: Gathers worktree changes, builds `DiffSpec` objects, and executes the legacy commit engine via `commit_engine::create_commit_simple`.
- **`series`**: Loads an existing stack via `stack_by_name` and invokes `stack.add_series_top_of_stack` to manage patch series within stacks.

### Context and Worktree Safety

Every command receives a `but_ctx::Context` object that abstracts repository access and project metadata. Before modifying state, commands acquire an exclusive worktree guard to prevent race conditions:

```rust
let mut guard = ctx.exclusive_worktree_access();
let outcome = ctx.branch_manager().create_virtual_branch_from_branch(
    ...,
    guard.write_permission()
)?;

```

This pattern appears in `apply_by_name`, `apply_from_branch`, and `create` functions (lines 56-68 of [`vbranch.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/vbranch.rs)), ensuring safe concurrent access to the Git repository.

## Project Management Commands

The [`command/project.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/command/project.rs) module handles repository registration and discovery:

- **`list`**: Calls `gitbutler_project::dangerously_list_projects_without_migration()` to display known projects with their IDs, titles, and paths.
- **`add`**: Normalizes the supplied path to a canonical Git worktree (lines 24-28), registers it via `gitbutler_project::add_at_app_data_dir`, and optionally sets a base remote branch through `gitbutler_branch_actions::set_base_branch` when the `--switch-to-workspace` flag is provided.

Repository discovery occurs at [`command/project.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/command/project.rs) lines 24-28, where the path is resolved against the filesystem.

## Context, Tracing, and Debug Output

The CLI supports diagnostic visibility through the `--trace` flag, which initializes the `tracing` crate in [`main.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/main.rs) (line 75). When enabled, commands serialize their results to JSON via `debug_print` in [`command/mod.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/command/mod.rs), providing structured output for debugging and scripting integration.

## Usage Examples

Listing all virtual branches in the current project:

```bash
gitbutler-cli branch

```

Creating a new virtual branch named `feature/auth`:

```bash
gitbutler-cli branch create feature/auth

```

Applying an existing real branch as a virtual stack:

```bash
gitbutler-cli branch apply -b main feature/login

```

Registering a new repository with a specific upstream:

```bash
gitbutler-cli project add -s refs/remotes/origin/main /path/to/repo

```

## Summary

- The GitButler CLI uses a **parse-context-dispatch architecture** with `clap` for argument parsing and `but_ctx::Context` for state management.
- Commands are organized into **branch** (`vbranch`) and **project** groups, implemented in [`command/vbranch.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/command/vbranch.rs) and [`command/project.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/command/project.rs).
- **Virtual branch operations** include listing, creating, applying, committing, and managing series within stacks.
- **Worktree safety** is enforced through exclusive access guards before any repository mutation.
- **Project registration** handles repository discovery and optional base branch configuration.

## Frequently Asked Questions

### How does the GitButler CLI handle argument parsing?

The CLI uses the `clap` crate with derive macros defined in [`crates/gitbutler-cli/src/args.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/crates/gitbutler-cli/src/args.rs). The `Args` struct represents the top-level command, while nested enums define subcommands for branch and project operations. Parsing occurs in [`main.rs`](https://github.com/gitbutlerapp/gitbutler/blob/main/main.rs) via `clap::Parser::parse()`.

### What is the purpose of the `but_ctx::Context` in GitButler CLI commands?

The `Context` object abstracts repository access, project metadata, and workspace state. It provides the Git repository handle, project data directory paths, and manages exclusive worktree access through guard objects. This ensures thread-safe operations and consistent state across commands.

### How does the CLI ensure safe concurrent access to the Git repository?

Before executing write operations, commands acquire an exclusive worktree guard using `ctx.exclusive_worktree_access()`. This guard provides a write permission token that must be passed to mutation methods in the branch manager. The pattern prevents race conditions when multiple CLI instances or the GUI application access the same repository.

### What is the difference between `apply_by_name` and `apply_from_branch` in the virtual branch commands?

`apply_by_name` looks up and activates a virtual branch (stack) by its virtual name, while `apply_from_branch` converts an existing real Git branch into a virtual stack. The latter is triggered when the `--branch` flag is passed to the apply subcommand, allowing users to migrate existing branches into GitButler's virtual branch system.