Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"allow": [
"Bash(npm run build:*)",
"Bash(pnpm list:*)",
"Bash(pnpm add:*)"
"Bash(pnpm add:*)",
"Bash(git checkout:*)",
"Bash(pnpm run build:*)"
]
}
}
6 changes: 5 additions & 1 deletion CLI-DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,11 @@ pnpm update-cli

The command "man pages" are copied from `../gitbutler/cli-docs` so that changes to the commands docs can be included in changes with the code.

To update the command man-pages, you can run ./scripts/sync-commands.sh
To update the command man-pages, you can run:

```bash
pnpm update-manpages
```

## Manual Runs

Expand Down
49 changes: 49 additions & 0 deletions content/docs/cli-guides/cli-tutorial/ai-stuff.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
title: Working with AI
description: How to use the GitButler CLI with AI and agents
---

There are a couple of different ways that the GitButler CLI can use or interact with AI tools. Some are via `--ai` options to commands to use AI to help with tasks, others are ways that coding agents can more easily use the CLI to accomplish tasks.

## Dash Dash AI

There are a few commands that will take a `--ai` option to use a configured AI provider to generate something.

### `but commit --ai`

Probably the most commonly used would be `but commit --ai`, which will take a look at the changes in the files you're committing and generate an example commit message for you. If you're not feeling like writing anything more than "did some stuff", this could be a nice option for you.

This will automatically commit the work specified with the generated message, but you can also easily edit it with `but reword <commit>` if you wish.

### `but squash --ai`

If you squash two commits together, by default it will simply concatenate the commit messages together, which is rarely what you probably want. You can easily edit the message afterwards, but if you want to let AI try to combine the messages for you, you can give `but squash --ai` a try.

<Callout type="info">

We're working on integrating AI features into many more of our commands, so keep an eye out.

</Callout>

## Skills

If you're using an AI coding agent that can read skills, you can have GitButler automatically install a GitButler specific skill for various agents with `but skill install`.

```git
❯ but skill install

Select a skill folder format:

? Which format would you like to use?:
> Claude Code - Claude Code CLI skill format (./.claude/skills/gitbutler)
OpenCode - OpenCode AI skill format (./.opencode/skills/gitbutler)
Codex - Codex skill format (./.codex/skills/gitbutler)
GitHub Copilot - GitHub Copilot local (repo) skill format (./.github/skills/gitbutler)
GitHub Copilot - GitHub Copilot global skill format (./.copilot/skills/gitbutler)
```

We keep these templates up to date, so if you update GitButler, you may want to update the skills too.

## Hooks and MCP

You can also install explicit hooks or an MCP server if you prefer. You can read more about those options [over here](/features/ai-integration/ai-overview)
12 changes: 6 additions & 6 deletions content/docs/cli-guides/cli-tutorial/branching-and-commiting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -243,26 +243,26 @@ but status

### Committing Specific Files or Hunks

Instead of staging files first and then committing with `-o`, you can also directly specify which files or hunks to include in a commit using the `-F` or `--files` option. This lets you commit only specific changes without having to assign them to a branch first.
Instead of staging files first and then committing with `-o`, you can also directly specify which files or hunks to include in a commit using the `-p` or `--changes` option. This lets you commit only specific changes without having to assign them to a branch first.

For example, if you have multiple unassigned files and only want to commit some of them:

```bash
but commit -F h0,i0 -m "only these two files" user-bookmarks
but commit -p h0,i0 -m "only these two files" user-bookmarks
```

You can specify files in several ways:

- **By CLI ID**: Use the short identifier shown in `but status` (e.g., `h0`, `i0`)
- **Space-separated**: `--files h0 i0 k0`
- **Comma-separated**: `-F h0,i0,k0`
- **By path**: `-F app/models/bookmark.rb`
- **Space-separated**: `--changes h0 i0 k0`
- **Comma-separated**: `-p h0,i0,k0`
- **By path**: `-p app/models/bookmark.rb`

This also works with hunk IDs. When a file has multiple hunks (shown in `but status -f` or `but diff`), you can commit individual hunks rather than the entire file. This is useful when you have changes in the same file that belong to different logical commits.

<Callout type="info">

If you don't specify `-F`, all uncommitted changes (or changes staged to the target branch) are committed. Use `-F` when you need fine-grained control over what goes into a commit.
If you don't specify `-p`, all uncommitted changes (or changes staged to the target branch) are committed. Use `-p` when you need fine-grained control over what goes into a commit.

</Callout>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ So, let's take a look at what this looks like and how we can deal with conflicte
{/* restore [e53a4a85d83d] */}
{/* run git push -f origin 96ccca9:main */}

```cli [conflict-resolution-but-status-1, 308px]
```cli [conflict-resolution-but-status-1, 396px]
but status
```

Expand Down
2 changes: 1 addition & 1 deletion content/docs/cli-guides/cli-tutorial/forges.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Once it's opened, you'll get a URL you can view the pull request on.

In order to open a PR on GitHub, you'll need to authenticate to that forge. You can see which authentications you have by running `but config`:

```cli [forges-but-config-1, 484px]
```cli [forges-but-config-1, 506px]
but config
```

Expand Down
2 changes: 2 additions & 0 deletions content/docs/cli-guides/cli-tutorial/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"conflict-resolution",
"forges",
"configuration",
"ai-stuff",
"scripting",
"conclusion"
]
}
20 changes: 20 additions & 0 deletions content/docs/cli-guides/cli-tutorial/scripting.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: Scripting
description: How to script with GitButler CLI
---

### JSON Errwhere

All of the commands are designed to be very user friendly when we have an interactive terminal, but you can also very easily script everything by passing the `--json` or `-j` option to anything. For example, here is using `but show` on a commit.

```cli [scripting-but-show-1, 330px]
but show 2672465
```

Now with the `--json` option:

```cli [scripting-but-show-2, 682px]
but show --json 2672465 | jq
```

You can do this with anything - committing, status, diffing, etc. Just throw a `-j` in there and you get parseable data (or, data your agent can very easily work with).
2 changes: 1 addition & 1 deletion content/docs/cli-guides/cli-tutorial/updating-the-base.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ When GitButler is first initialized in a project, you are asked to choose a bran

You can always check your target branch setting with `but config`:

```cli [updating-the-base-but-config-1, 484px]
```cli [updating-the-base-but-config-1, 506px]
but config
```

Expand Down
25 changes: 25 additions & 0 deletions content/docs/commands/but-apply.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
title: "`but apply`"
description: "Apply a branch to the workspace."
---

If you want to apply an unapplied branch to your workspace so you
can work on it, you can run `but apply <branch-name>`.

This will apply the changes in that branch into your working directory
as a parallel applied branch.

## Examples

Apply by branch name:

```text
but apply my-feature-branch
```

**Usage:** `but apply <BRANCH_NAME>`

## Arguments

* `<BRANCH_NAME>` — Name of the branch to apply (required)

43 changes: 3 additions & 40 deletions content/docs/commands/but-branch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ title: "`but branch`"
description: "Commands for managing branches."
---

This includes creating, deleting, listing, showing details about, and
applying and unapplying branches.
This includes creating, deleting, listing, and showing details about branches.

By default without a subcommand, it will list the branches.

To apply or unapply branches, use `but apply` and `but unapply`.

**Usage:** `but branch <COMMAND>`

## Subcommands
Expand Down Expand Up @@ -111,41 +112,3 @@ You can also choose to fetch and display review information, show files modified
* `--ai` — Generate AI summary of the branch changes
* `--check` — Check if the branch merges cleanly into upstream and identify conflicting commits

### `but branch apply`

Apply a branch to the workspace

If you want to apply an unapplied branch to your workspace so you
can work on it, you can run `but branch apply <branch-name>`.

This will apply the changes in that branch into your working directory
as a parallel applied branch.

**Usage:** `but branch apply <BRANCH_NAME>`

**Arguments:**

* `<BRANCH_NAME>` — Name of the branch to apply (required)

### `but branch unapply`

Unapply a branch from the workspace

If you want to unapply an applied branch from your workspace
(effectively stashing it) so you can work on other branches,
you can run `but branch unapply <branch-name>`.

This will remove the changes in that branch from your working
directory and you can re-apply it later when needed. You will then
see the branch as unapplied in `but branch list`.

**Usage:** `but branch unapply <BRANCH_NAME> [OPTIONS]`

**Arguments:**

* `<BRANCH_NAME>` — Name of the branch to unapply (required)

**Options:**

* `-f`, `--force` — Force unapply without confirmation

6 changes: 3 additions & 3 deletions content/docs/commands/but-commit.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ If a target is provided without --before or --after, defaults to --before behavi
## Options

* `-m`, `--message` `<MESSAGE>` — Commit message
* `-f`, `--file` `<FILE>` — Read commit message from file
* `--message-file` `<FILE>` — Read commit message from file
* `-c`, `--create` — Whether to create a new branch for this commit. If the branch name given matches an existing branch, that branch will be used instead. If no branch name is given, a new branch with a generated name will be created
* `-o`, `--only` — Only commit staged files, not unstaged files
* `-n`, `--no-hooks` — Bypass pre-commit hooks
* `-i`, `--ai` `<AI>` — Generate commit message using AI with optional user summary
* `-F`, `--files` `<FILES>` — Uncommitted file or hunk CLI IDs to include in the commit. Can be specified multiple times or as comma-separated values. If not specified, all uncommitted changes (or changes staged to the target branch) are committed
* `-i`, `--ai` `<AI>` — Generate commit message using AI with optional user summary. Use --ai by itself or --ai="your instructions" (equals sign required for value)
* `-p`, `--changes` `<CHANGES>` — Uncommitted file or hunk CLI IDs to include in the commit. Can be specified multiple times or as comma-separated values. If not specified, all uncommitted changes (or changes staged to the target branch) are committed

23 changes: 16 additions & 7 deletions content/docs/commands/but-rub.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,26 @@ the branch. You can also "rub" a commit onto another commit to squash
them together. You can rub a commit onto a branch to move that commit.
You can rub a file from one commit to another.

Non-exhaustive list of operations:
## Operations Matrix

Each cell shows what happens when you rub SOURCE → TARGET:

```text
│Source │Target
──────┼───────────┼──────
Amend │File,Branch│Commit
Squash│Commit │Commit
Stage │File,Branch│Branch
Move │Commit │Branch
SOURCE ↓ / TARGET → │ zz (unassigned) │ Commit │ Branch │ Stack
─────────────────────┼─────────────────┼────────────┼─────────────┼────────────
File/Hunk │ Unstage │ Amend │ Stage │ Stage
Commit │ Undo │ Squash │ Move │ -
Branch (all changes) │ Unstage all │ Amend all │ Reassign │ Reassign
Stack (all changes) │ Unstage all │ - │ Reassign │ Reassign
Unassigned (zz) │ - │ Amend all │ Stage all │ Stage all
File-in-Commit │ Uncommit │ Move │ Uncommit to │ -
```

Legend:
- `zz` is a special target meaning "unassigned" (no branch)
- `-` means the operation is not supported
- "all changes" / "all" refers to all uncommitted changes from that source

## Examples

Squashing two commits into one (combining the commit messages):
Expand Down
2 changes: 1 addition & 1 deletion content/docs/commands/but-squash.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ Can be invoked in three ways:

* `-d`, `--drop-message` — Drop source commit messages and keep only the target commit's message
* `-m`, `--message` `<MESSAGE>` — Provide a new commit message for the resulting commit
* `-i`, `--ai` `<AI>` — Generate commit message using AI with optional user summary or instructions
* `-i`, `--ai` `<AI>` — Generate commit message using AI with optional user summary or instructions. Use --ai by itself or --ai="your instructions" (equals sign required for value)

44 changes: 44 additions & 0 deletions content/docs/commands/but-unapply.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
title: "`but unapply`"
description: "Unapply a branch from the workspace."
---

If you want to unapply an applied branch from your workspace
(effectively stashing it) so you can work on other branches,
you can run `but unapply <branch-name>`.

This will remove the changes in that branch from your working
directory and you can re-apply it later when needed. You will then
see the branch as unapplied in `but branch list`.

The identifier can be:
- A CLI ID pointing to a stack or branch (e.g., "bu" from `but status`)
- A branch name

If a branch name (or an identifier pointing to a branch) is provided,
the entire stack containing that branch will be unapplied.

## Examples

Unapply by branch name:

```text
but unapply my-feature-branch
```

Unapply by CLI ID:

```text
but unapply bu
```

**Usage:** `but unapply <IDENTIFIER> [OPTIONS]`

## Arguments

* `<IDENTIFIER>` — CLI ID or name of the branch/stack to unapply (required)

## Options

* `-f`, `--force` — Force unapply without confirmation

9 changes: 6 additions & 3 deletions content/docs/commands/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
"but-uncommit",
"but-amend",
"but-squash",
"but-move",
"but-pick",
"---Operations Log---",
"but-oplog",
"but-undo",
Expand All @@ -41,6 +39,11 @@
"but-update",
"but-alias",
"but-config",
"but-skill"
"---Miscellaneous---",
"but-apply",
"but-move",
"but-pick",
"but-skill",
"but-unapply"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
┊╭┄<u><span style='color:var(--blue,#00a)'>ch</span></u> [<b><span style='color:var(--green,#0a0)'>user-changes</span></b>] <span style='opacity:0.67'><i>(no commits)</i></span>
├╯
┴ <span style='opacity:0.67'>204e309</span> (common base) [<b><span style='color:var(--green,#0a0)'>origin/main</span></b>] <span style='opacity:0.67'>2025-07-06</span> Merge pull request #10 from schacon/sc-description<span style='opacity:0.67'>(checked 12 seconds ago)</span>
┴ <span style='opacity:0.67'>204e309</span> (common base) [<b><span style='color:var(--green,#0a0)'>origin/main</span></b>] <span style='opacity:0.67'>2025-07-06</span> Merge pull request #10 from schacon/sc-description

<span style='opacity:0.67'>Hint: run `but diff` to see uncommitted changes and `but stage &lt;file&gt;` to stage them to a branch</span>
</pre>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
┊╭┄<u><span style='color:var(--blue,#00a)'>ch</span></u> [<b><span style='color:var(--green,#0a0)'>user-changes</span></b>] <span style='opacity:0.67'><i>(no commits)</i></span>
├╯
┴ <span style='opacity:0.67'>204e309</span> (common base) [<b><span style='color:var(--green,#0a0)'>origin/main</span></b>] <span style='opacity:0.67'>2025-07-06</span> Merge pull request #10 from schacon/sc-description<span style='opacity:0.67'>(checked 12 seconds ago)</span>
┴ <span style='opacity:0.67'>204e309</span> (common base) [<b><span style='color:var(--green,#0a0)'>origin/main</span></b>] <span style='opacity:0.67'>2025-07-06</span> Merge pull request #10 from schacon/sc-description

<span style='opacity:0.67'>Hint: run `but diff` to see uncommitted changes and `but stage &lt;file&gt;` to stage them to a branch</span>
</pre>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
┊● <u><span style='color:var(--blue,#00a)'>f5</span></u><span style='opacity:0.67'>5a30e</span> add bookmark model and associations
├╯
┴ <span style='opacity:0.67'>204e309</span> (common base) [<b><span style='color:var(--green,#0a0)'>origin/main</span></b>] <span style='opacity:0.67'>2025-07-06</span> Merge pull request #10 from schacon/sc-description<span style='opacity:0.67'>(checked 11 seconds ago)</span>
┴ <span style='opacity:0.67'>204e309</span> (common base) [<b><span style='color:var(--green,#0a0)'>origin/main</span></b>] <span style='opacity:0.67'>2025-07-06</span> Merge pull request #10 from schacon/sc-description

<span style='opacity:0.67'>Hint: run `but diff` to see uncommitted changes and `but stage &lt;file&gt;` to stage them to a branch</span>
</pre>
Expand Down
Loading