Skip to content
Try Gitea Cloud ☁️ for 30 days → Accelerate your Development & Deploys!
Clirelease

gt, the new Gitea CLI

Banner for blog post with title "gt, the new Gitea CLI"

Gitea’s command line tool, tea, has been rewritten from scratch. It has a new name, gt, and a new home, gitea.com/gitea/cli. Today, we are releasing its first version, gitea-cli 0.1.0.

gt manages repositories, issues, pull requests, releases, Actions, packages and the rest of Gitea from your terminal. It has explicit commands that work the same way at your desk and in CI. It requires Gitea 28 or newer.

tea has served Gitea users since 2018, and many people improved it over the years. It has grown organically, though. Commands differ in their flags and output, much of the logic sits directly in the command handlers, and adding a feature means touching a lot of unrelated code. Instead of another round of incremental fixes, we started over with a clear structure and a consistent command surface.

We first landed the rewrite in the tea repository as a stack of pull requests. The result no longer resembled tea: different commands, a different config, and no compatibility layer. So we gave it its own name and repository instead of shipping it as a breaking “tea 1.0”. Less than 4% of the lines in today’s code base go back to tea, and most of those are test tables.

  • Cobra instead of urfave/cli, with one command per file in internal/app.
  • A service layer. All API access goes through internal/services, built on the Gitea Go SDK. Raw HTTP is used only where the SDK has a gap, and every such call is marked.
  • A transport layer that is careful with your network. It bounds only the wait for an answer, so large uploads and slow downloads are not cut off, while stalled ones fail. It retries only transient failures and keeps credentials on your instance when Gitea redirects to object storage.
  • A terminal layer that sanitizes server-provided text before it reaches your terminal, follows NO_COLOR, CLICOLOR and friends, and enables escape sequences on the Windows console.
  • Tests: 1,222 test functions, up from 216 in tea, plus integration tests against a real Gitea in CI.

Every list and view command supports --json, and --jq filters the output without needing jq installed. Each command’s help lists its JSON fields, and shell completion offers them:

Terminal window
gt issue list --json number,title --jq '.[] | "\(.number)\t\(.title)"'

Pull requests behave the way you expect from a modern forge CLI. gt pr create pushes your branch, to your fork if you work in one. gt pr checkout and gt pr diff cover fork and AGit pull requests, and gt pr checks exits with code 8 while checks are still pending:

Terminal window
gt pr checkout 13 --update
gt pr diff 13 | git apply
gt pr checks 13 --watch && gt pr merge 13 --squash

Reviews can be written in your editor. On a terminal, gt pr review offers to annotate the diff: existing comments are shown in place, and every line you start with # becomes an inline comment on the line above it.

Actions are first-class:

Terminal window
gt workflow run deploy.yml --ref main --field env=staging
gt run watch 34 --timeout 10m && echo deployed
gt run logs 34 --job build --follow
gt run download 34
gt secret set DEPLOY_TOKEN

Some of what is new compared with tea:

  • Packages: gt package upload tool 1.0.0 dist/tool-linux-amd64, plus listing, linking and deleting.
  • Search and status: gt search, gt status and gt notification watch.
  • More of Gitea: teams, branch protection, deploy keys, label import and export, issue dependencies and timelines, projects, and syncing forks and mirrors with gt repo sync.
  • Interactive forms for create and edit. With TERM=dumb, every prompt is asked as a plain line of text, which works with screen readers.
  • Aliases, completion and diagnostics: gt alias, gt completion and gt doctor.
  • Access proxies: per-instance headers, client certificates and an http_timeout setting for instances behind a proxy such as Cloudflare Access.
  • Documented behaviour: gt help environment, gt help exit-codes and gt help formatting.

We want to be open about our tools: gt was built with heavy use of AI agents (Claude Code), with a human deciding on design, scope and every change that was merged.

The process mattered more than the tool.

  • Small steps. The rewrite started on 7 October as reviewable pull requests, layer by layer: transport and settings, then auth and git, terminal, services, and finally the commands.
  • A user experience audit. We compared every command against a real Gitea and against established CLIs, which led to a dozen follow-up changes in output, flags and prompts.
  • Adversarial review before the release. Before tagging 0.1.0 we ran repeated rounds of review. In each round, fresh agents with no memory of earlier rounds tried to break gt against local Gitea 28.2 instances: one plain, one with S3 storage, and an Actions runner. They read the diff, ran every documented example, injected network faults, and planted hostile text in issues, logs and branch names. Every finding was fixed with a regression test, and then the next round started.

These rounds found and fixed several hundred problems, from wrong exit codes to a review comment landing on the wrong line. Some were bugs introduced by earlier fixes, which is why we kept repeating the rounds until they came back almost empty. The results are pull requests #7 and #18.

gt is a new tool, not an upgrade of tea:

  • Nothing is migrated. gt keeps its configuration in ~/.config/gitea-cli/ and does not read tea’s config. Log in once with gt auth login. On a terminal it asks how: OAuth in the browser, or a token. In CI, use --with-token.
  • Both can be installed side by side. The binaries and config directories are different.
  • Environment variables use the GITEA_CLI_ prefix. GITEA_TOKEN and GITEA_INSTANCE_URL work as well, which is handy in CI.

Most commands look familiar. These moved:

teagt
tea login add, tea logins, tea whoamigt auth login, gt auth status
tea open--web on the relevant command
tea clonegt repo clone
tea commentgt issue comment, gt pr comment
tea actions ...gt run, gt workflow, gt secret, gt variable

On Linux, macOS and FreeBSD:

Terminal window
curl -fsSL https://gitea.com/gitea/cli/raw/branch/main/scripts/install.sh | sh

On Windows (PowerShell):

Terminal window
irm https://gitea.com/gitea/cli/raw/branch/main/scripts/install.ps1 | iex

Both scripts verify the SHA-256 checksum of the download. You can also:

  • Download binaries from dl.gitea.com/gitea-cli, for amd64, arm64 and arm.
  • Use Docker: docker run --rm gitea/gitea-cli --help.
  • Build from source: go install gitea.dev/cli/cmd/gt@latest.

This is a first release, and the version number says so. Until 1.0, flags and output may still change where the 0.x experience shows they should. For scripts, use --json: the text output is meant for people and may change between releases. gt targets Gitea 28 and newer, and older versions are not supported.

gt would not exist without tea and everyone who built and maintained it since 2018, filed issues and sent fixes. Many of the open tea issues shaped what gt does today.

Try it, and tell us what breaks or what is missing: open an issue on gitea.com/gitea/cli or find us on Discord.