---
name: grit
description: Use the grit CLI for version control in Git repositories — status, diffs, commits, branches, merges, cherry-picks, fetch/pull/push and tags — with JSON output for scripts and agents. Use when a task involves committing, branching, syncing with a remote or reading history and `grit` is installed.
---

# grit

`grit` is a small, opinionated Git client. It reads and writes ordinary Git repositories, so `git` and `grit` can be used on the same repository. It does not mirror Git's commands or flags: there is usually one obvious way to do each thing, and every command can answer in JSON.

This skill was generated by `grit {version}`. Run `grit <command> --help` for the exact options of the installed version.

## Rules

- Pass `--json` whenever you will read the result. stdout then holds exactly one JSON object; progress and prompts go to stderr.
- Use `--filter '<jq-like expr>'` (with `--json`) to keep only what you need: `grit status --json --filter '{branch, clean}'`.
- On failure the exit code is 1 and stdout is `{"error": "…"}`. Exit code 2 is a usage error (unknown flag or command) and has no JSON.
- Always give `grit commit` a message. It never opens an editor.
- Don't translate Git habits flag-for-flag. `grit commit -a`, `git add -p`, `rebase`, `stash`, `reset` and `--amend` don't exist here; see "What grit doesn't do".

## Where am I?

```console
$ grit status --json
```

Plain `grit` is the same as `grit status`. Keys: `branch`, `detached`, `head`, `target` (the branch your work is headed for), `ahead`, `commits` (up to ten not on the target), `staged`, `unstaged`, `untracked`, `clean`.

The target branch is the first that exists of: the `target.branch` config value, `origin/master`, `origin/main`, `master`, `main`. Change it with `grit config target.branch origin/develop`.

## Reading history and changes

| Task | Command |
| --- | --- |
| Uncommitted changes as a diff | `grit diff` |
| The change one commit made | `grit diff <commit>` |
| A commit's message and file summary | `grit show [<commit-or-branch-or-tag>]` |
| Recent history, ten at a time | `grit log`, then `grit log --before <next>` using the `next` value |
| Commits on this branch not on the target | `grit shortlog` |

Revisions can be full or short ids, branch or tag names, or expressions like `HEAD~2`.

## Committing

```console
$ grit commit -m "Explain what changed and why"
```

`grit commit` stages **every** change first (modified, deleted and untracked files) and then commits. There is no way to commit only some files: if only part of the work belongs in this commit, finish or move the rest aside first. `grit add [<path>…]` stages files so you can review them in `grit status`, but it doesn't limit what `grit commit` records.

`grit commit` fails with "nothing to commit" on a clean tree and refuses a detached HEAD.

## Branches

| Task | Command |
| --- | --- |
| List branches | `grit branch` |
| Create a branch at the current commit (no switch) | `grit branch <name>` |
| Create and switch | `grit switch -c <name>` |
| Switch | `grit switch <name>` (also `grit checkout`, `grit co`) |
| Delete a merged branch | `grit branch -d <name>` |
| Delete regardless | `grit branch -D <name>` |

`grit switch`, `grit merge`, `grit pick` and `grit pull` refuse to run with uncommitted changes. Commit first. They also refuse rather than overwrite an untracked file.

## Combining work

- `grit merge <branch>` fast-forwards when it can, otherwise records a merge commit. `<branch>` can be local or remote-tracking (`origin/main`).
- `grit pick <commit>` applies one non-merge commit to the current branch as a new commit, keeping its author and message.
- On a conflict both commands list the conflicting files, exit 1 and change nothing. grit can't resolve conflicts yet; to finish, run `git merge <branch>` (or `git cherry-pick <commit>`), fix the files and commit.

## Remotes

| Task | Command |
| --- | --- |
| Copy a repository | `grit clone <url> [<dir>]` |
| List or add remotes | `grit remote`, `grit remote add <name> <url>` |
| Download without changing your branch | `grit fetch [<remote>]` |
| Fetch and merge the remote copy of this branch | `grit pull` |
| Publish this branch to `origin` under the same name | `grit push` |
| Publish all local tags | `grit push --tags` |

`grit push` never force-pushes. If the remote has commits you don't, the push is rejected (exit 1, `"rejected": true`); run `grit pull`, then push again.

URLs can be `https://`, `ssh://`, `user@host:path`, `git://`, `file://` or a local path.

## Tags and config

- `grit tag` lists tags, `grit tag <name>` creates a lightweight tag at the current commit, `grit tag -d <name>` deletes one.
- `grit config <key>` reads, `grit config <key> <value>` sets, `grit config --unset <key>` removes, `grit config --list` lists. Add `--global` for the per-user file.

## Staying non-interactive

- HTTPS GitHub: run `grit auth` once in an interactive session (it uses a browser device flow). After that, fetch, pull and push use the stored token. When stdin isn't a terminal, grit won't prompt to sign in; it fails with a hint instead.
- SSH: set `GIT_SSH_COMMAND='ssh -o BatchMode=yes'` so a missing key or unknown host fails fast instead of waiting for input.
- Don't run `grit update` in automation; it reinstalls the binary.
- `grit manager`, `grit upload-pack` and `grit receive-pack` are plumbing that speaks Git protocols on stdin/stdout. Don't call them directly.

## What grit doesn't do

grit has no equivalent of `rebase`, `stash`, `reset`, `revert`, `commit --amend`, partial staging, interactive commands, annotated or signed tags, or conflict resolution. When a task needs one of these, use `git` on the same repository and come back to `grit` afterwards.

## More

- Docs for every command, with JSON field tables: https://grit-scm.com/docs/
- Agent guide (output contract, exit codes, credentials): https://grit-scm.com/docs/agents/
- All docs as one text file: https://grit-scm.com/llms-full.txt
