diamond-cli 0.1.1

Lightning-fast CLI for stacked pull requests
diamond-cli-0.1.1 is not a library.

πŸ’Ž Diamond

Stop waiting for code reviews. Start shipping.

Diamond is a lightning-fast CLI for stacked pull requestsβ€”the workflow used at Meta, Google, and top engineering teams to ship code 4x faster.

License: Apache 2.0 CI

⚠️ Alpha Software: Diamond is in active development. Works well, but expect rough edges. Please report issues!


The Problem

You finish a feature. You open a PR. Then you wait.

Hours. Sometimes days. Your next feature depends on this one, so you're stuck. You could branch off your unmerged work, but rebasing that later? Nightmare fuel.

Meanwhile, your best engineers are context-switching instead of coding.

The Solution

Stacked pull requests let you build Feature B on top of Feature Aβ€”before Feature A is even reviewed. When Feature A gets feedback, Diamond automatically rebases your entire stack in milliseconds.

This is how the best teams ship faster:

βœ… Never blocked waiting for reviews – Keep coding while your team reviews βœ… 4x faster code reviews – Reviewers prefer 5 files over 50 (research-backed) βœ… Stay in flow – Stop context-switching between unrelated work βœ… Ship incrementally – Small PRs are easier to review, test, and rollback βœ… Every commit stays green – CI runs on every change, making git bisect actually useful


Installation

Prerequisites: Rust 1.82+

Install from crates.io (recommended):

cargo install diamond-cli

Or install latest from GitHub:

cargo install --git https://github.com/rsperko/diamond

Or build from source:

git clone https://github.com/rsperko/diamond.git
cd diamond
cargo install --path .

Verify installation:

dm --help

For GitHub: Install the GitHub CLI (gh) and authenticate:

gh auth login

For GitLab: Install the GitLab CLI (glab) and authenticate:

glab auth login

Diamond auto-detects your forge from the git remote URL. Self-hosted GitLab instances are fully supported.

GitLab Note: Diamond requires force push for stacked workflows. Feature branches work by default, but if your organization protects all branches, you'll need to enable "Allow force push" in your branch protection settings. See Troubleshooting for details.


Repository Setup (Important!)

⚠️ For the best experience, configure your repository to use squash merging:

Stacked PRs work best with a clean, linear git history. Configure your GitHub/GitLab repository to squash merge by default:

GitHub: Settings β†’ Pull Requests β†’ Uncheck "Allow merge commits", Check "Allow squash merging"

GitLab: Settings β†’ General β†’ Merge requests β†’ Set merge method to "Squash commits"

Without this, your git history will be cluttered with merge commits instead of clean, revertable changes. See Configuration Guide for details.


Shell Completion

Diamond supports tab completion for bash, zsh, fish, and more. Completions include all subcommands, options, and even dynamic branch name suggestions for commands like checkout and delete.

Bash:

dm completion bash > ~/.local/share/bash-completion/completions/dm
source ~/.bashrc

Zsh:

mkdir -p ~/.zsh/completions
dm completion zsh > ~/.zsh/completions/_dm
echo 'fpath=(~/.zsh/completions $fpath)' >> ~/.zshrc
autoload -Uz compinit && compinit

Fish:

dm completion fish > ~/.config/fish/completions/dm.fish

Example usage:

dm checkout <TAB>         # Shows: feat/auth  feat/ui  main
dm delete --<TAB>         # Shows: --reparent --help
dm submit --<TAB>         # Shows: --stack --force

For more details, see docs/COMPLETIONS.md.


Quick Start

1. Initialize Diamond in your repo

cd your-project
dm init

Diamond stores stack relationships as git refs (refs/diamond/parent/*), enabling seamless collaboration.

2. Create your first stacked feature

Start with the foundation:

dm create add-database-schema
# Write your migration files...
git add .
git commit -m "Add user table schema"

Now build on top of it immediatelyβ€”don't wait for review:

dm create add-user-service
# Write your business logic...
git commit -am "Add user service layer"

Stack another layer:

dm create add-user-api
# Write your REST endpoints...
git commit -am "Add user API endpoints"

3. Visualize your stack

dm log

Output:

● main (trunk)
└── ● add-database-schema (PR #156)
    └── ● add-user-service (PR #157)
        └── ● add-user-api ← (you are here)

4. Navigate your stack

Jump to any branch:

dm checkout        # Interactive picker
dm top             # Jump to top of stack
dm bottom          # Jump to bottom (closest to main)
dm up              # Move to child branch
dm down            # Move to parent branch

5. Submit your stack for review

Push and create PRs for the whole stack:

dm submit --stack

Diamond pushes each branch and creates GitHub/GitLab PRs with the correct base branches. Each PR is small, focused, and reviewable.


When Reviews Come Back

Your reviewer asks for changes on add-database-schema. No problem:

dm checkout add-database-schema
# Make changes...
git commit -am "Add index to email column"
dm restack   # Rebases all dependent branches automatically

Your entire stack stays in sync. No merge conflicts. No manual rebasing.


Essential Commands

Creating & Managing Branches

Command Alias Description
dm create <name> dm c Create a new branch on top of current
dm checkout [name] dm co Switch branches (interactive if no name)
dm track - Start tracking current branch
dm rename <name> - Rename current branch and update metadata
dm delete <name> - Delete branch (with optional re-parenting)

Navigating Stacks

Command Alias Description
dm log dm l Visualize your entire stack tree (TUI)
dm top dm t Jump to top of current stack
dm bottom dm b Jump to bottom (closest to trunk)
dm up dm u Move to child branch
dm down dm d Move to parent branch
dm info [branch] - Show branch details, commits, and PR status

Submitting & Syncing

Command Alias Description
dm submit dm s Push current branch and create PR
dm submit --stack - Submit entire stack (current + descendants)
dm sync - Fetch trunk and rebase all branches
dm restack - Rebase stack without fetching
dm pr - Open current branch's PR in browser

Modifying Branches

Command Alias Description
dm modify -am "msg" dm m Stage all and amend/create commit
dm squash dm sq Squash all commits in current branch
dm absorb - Auto-absorb staged changes into earlier commits
dm move --onto <branch> - Move branch to new parent

Recovering from Conflicts

Command Alias Description
dm continue dm cont Continue after resolving conflicts
dm abort - Abort current operation

Collaboration & Maintenance

Command Alias Description
dm get <PR> - Download a teammate's PR stack
dm freeze - Freeze branch to prevent modifications
dm unfreeze - Unfreeze branch to allow modifications
dm doctor --fix - Diagnose and repair stack metadata
dm undo - Restore branch from backup
dm gc - Clean up old backup refs

Real-World Example

Let's build a complete authentication system as a stack:

# Start from main
dm init

# Layer 1: Database
dm create auth-schema -am "Add users and sessions tables"

# Layer 2: Business logic (builds on Layer 1)
dm create auth-service -am "Add authentication service"

# Layer 3: API endpoints (builds on Layer 2)
dm create auth-api -am "Add /login and /logout endpoints"

# Layer 4: Frontend integration (builds on Layer 3)
dm create auth-ui -am "Add login form component"

# Visualize the stack
dm log

Your stack:

● main
└── ● auth-schema
    └── ● auth-service
        └── ● auth-api
            └── ● auth-ui ← (current)

Submit for review:

dm submit --stack

This creates 4 small PRs instead of 1 massive 2,000-line PR:

  • PR #1: Database schema (150 lines) βœ… Easy review
  • PR #2: Service layer (200 lines) βœ… Focused scope
  • PR #3: API endpoints (180 lines) βœ… Clear purpose
  • PR #4: UI components (220 lines) βœ… Reviewable

Each PR gets reviewed faster because reviewers can focus.


Why Diamond?

πŸ¦€ Rust Performance

Built with libgit2 for sub-millisecond operations. Your stack with 20 branches? Rebased in <100ms.

🎯 TUI-First Design

dm log gives you a beautiful terminal UI to visualize complex stacks. No more ASCII art in git log.

πŸ”§ Git-Native

Diamond uses standard Git branches and commits. Your team doesn't need Diamond to review your PRs. You can always drop back to vanilla Git.

πŸ“¦ Zero Lock-In

Metadata lives in .git/diamond/ (Git-ignored by default). Delete it and you're back to regular Git branches. No remote dependencies.


How It Works

Diamond stores parent-child relationships as git refs that travel with push/fetch:

refs/diamond/config/trunk    β†’ blob("main")
refs/diamond/parent/auth-schema  β†’ blob("main")
refs/diamond/parent/auth-service β†’ blob("auth-schema")
refs/diamond/parent/auth-api     β†’ blob("auth-service")

Children are derived by scanning parent refs (not stored explicitly).

When you run dm restack or dm sync, Diamond:

  1. Topologically sorts your branches (parents before children)
  2. Rebases each branch onto its parent using git rebase
  3. Handles conflicts interactively with dm continue / dm abort

That's it. No magic. Just smart orchestration of Git primitives.


FAQ

Q: Do my reviewers need Diamond? No. Diamond creates standard GitHub PRs and GitLab MRs. Reviewers see normal PRs with clear base branches.

Q: What if I get conflicts during rebase? Diamond pauses and lets you resolve conflicts manually. Then run dm continue to resume.

Q: Can I use this with GitLab? Yes! GitLab has full feature parity with GitHub. Diamond creates MRs, handles approvals, waits for pipelines, and supports auto-merge. Requires glab CLI. Self-hosted GitLab instances are also supported.

Q: What about Bitbucket / Gitea? Not yet, but the forge architecture makes adding new providers straightforward. Contributions welcome!

Q: What if Diamond breaks? Diamond stores metadata as git refs under refs/diamond/. Your Git history is never modified unsafely. Worst case: delete the refs and use Git normally.

Q: How is this different from other tools? Diamond is laser-focused on speed (Rust), simplicity (minimal commands), and beautiful UX (TUI). No web dashboards, no SaaS, no lock-in.

Q: How do I fix corrupted stack metadata? Run dm doctor --fix to automatically repair common issues like orphaned refs, broken parent links, and cycle detection.

Q: How do I undo a mistake? Diamond automatically creates backups before destructive operations. Run dm undo --list to see available backups, then dm undo <branch> to restore.

Q: My operation got interruptedβ€”what do I do? If you have an in-progress sync or restack, run dm continue after resolving any conflicts, or dm abort to cancel and roll back.


Advanced: Stack Surgery

Reorganize your stack on the fly:

Move a branch to a different parent:

dm move --onto main        # Move current branch to trunk

Delete a branch and re-parent its children:

dm delete auth-service --reparent
# auth-api now builds directly on auth-schema

Squash commits before submitting:

dm checkout auth-schema
dm squash                  # Squash all commits into one
dm restack                 # Update dependent branches

Team Collaboration

Diamond makes it easy to collaborate on stacked PRs:

Download a teammate's stack:

dm get 123                 # Download PR #123 and its dependencies
dm get https://github.com/org/repo/pull/123

Downloaded branches are frozen by default to prevent accidental modifications.

Stack on top of a colleague's work:

dm get 123                 # Get their stack (frozen)
dm create my-feature       # Build on top of it

Unfreeze to make changes:

dm unfreeze                # Allow modifications to current branch
dm unfreeze --upstack      # Also unfreeze all child branches

Contributing

Diamond is open source and built with πŸ¦€ Rust. Contributions welcome!

Development setup:

git clone https://github.com/rsperko/diamond.git
cd diamond
cargo build
cargo test                 # 206+ tests, ~90% coverage
cargo clippy -- -D warnings
just setup-hooks           # Configure git hooks (Gitleaks)

**Security:**
This project uses [Gitleaks](https://github.com/gitleaks/gitleaks) to prevent secrets from being committed.
Run `just setup-hooks` to install the pre-commit hook that checks for secrets.

**Architecture:**
- `src/main.rs` – CLI parsing (clap)
- `src/commands/` – Command implementations
- `src/git_gateway.rs` – Git operations (libgit2)
- `src/ref_store.rs` – Stack metadata in git refs
- `src/state.rs` – Operation state management
- `src/forge/` – GitHub/GitLab integration

---

## Inspired By

The stacked diff workflow has been used for years at:
- **Meta** (Phabricator)
- **Google** (Critique)
- **Uber, Airbnb, Stripe** (various internal tools)

Diamond brings this workflow to **any team using GitHub or GitLab**, with the speed of Rust and zero SaaS dependencies.

---

## License

Apache 2.0 Β© 2025

Built with ❀️ for developers who ship fast.

---

## Learn More

- πŸ“š [Stacked Diffs Explained](https://newsletter.pragmaticengineer.com/p/stacked-diffs) – The Pragmatic Engineer
- πŸ“Š [Why Stacked PRs Work](https://www.michaelagreiler.com/stacked-pull-requests/) – Dr. Michaela Greiler
- 🎯 [In Praise of Stacked PRs](https://benjamincongdon.me/blog/2022/07/17/In-Praise-of-Stacked-PRs/) – Ben Congdon