feat: add gitea gt cli skill

This commit is contained in:
raucao committed 2026-10-26 17:48:23 +04:00
commit e322aa6b79
6 files changed
+1355

No files matched your search

+24
View File
@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org/>
+54
View File
@@ -0,0 +1,54 @@
# gitea-gt-cli
An [Agent Skill](https://agentskills.io) for **`gt`**, the official Gitea CLI
(the rewrite of `tea`), covering repositories, issues, pull requests, reviews,
releases, Actions, packages, organizations, and authentication.
## Install
```bash
# HTTPS
npx skills add https://gitea.kosmos.org/raucao/gitea-gt-cli.git
# SSH
npx skills add ssh://git@gitea.kosmos.org/raucao/gitea-gt-cli.git
# Specific agent / global
npx skills add https://gitea.kosmos.org/raucao/gitea-gt-cli.git -a claude-code -g
```
The `skills` CLI supports any git host, so this works from Gitea. It will not be
listed on skills.sh, which only indexes GitHub repositories.
Without the `skills` CLI, copy `skills/gitea-gt-cli/` into your agent's skills
directory, for example `~/.agents/skills/gitea-gt-cli/` or
`.agents/skills/gitea-gt-cli/`.
## What's inside
```text
skills/gitea-gt-cli/
├── SKILL.md # when to use gt, auth, core concepts, workflows, gotchas
└── references/
├── commands-core.md # auth, repo, issue, pr, release, org, label, milestone, branch
├── commands-actions.md # run, workflow, secret, variable, package, admin
└── commands-misc.md # team, notification, search, status, time, webhook, wiki, ...
```
`SKILL.md` stays small and points at the reference file for each command group,
so the agent loads only the detail it needs.
## Requirements
- `gt` 0.1.0 or newer (`gt version`)
- A Gitea instance running **28 or newer**
Install `gt` itself with:
```bash
curl -fsSL https://gitea.com/gitea/cli/raw/branch/main/scripts/install.sh | sh
```
## License
[Unlicense](LICENSE) — public domain.
+256
View File
@@ -0,0 +1,256 @@
---
name: gitea-gt-cli
description: "Gitea CLI (gt) reference for working with Gitea from the terminal: repositories, issues, pull requests, reviews, releases, Actions runs/workflows, secrets, variables, packages, organizations, and auth. Use when managing Gitea with the `gt` command (the official rewrite of `tea`), or when a task mentions Gitea repos, issues, PRs, Actions, or authentication."
license: Unlicense
metadata:
version: "0.1.0"
upstream: https://gitea.com/gitea/cli
gt-version: ">=0.1.0"
gitea-version: ">=28"
---
# Gitea CLI (`gt`)
`gt` is Gitea's official command line tool, a rewrite of `tea` with a new name,
repository ([gitea.com/gitea/cli](https://gitea.com/gitea/cli)) and a consistent
command surface. It manages repositories, issues, pull requests, releases,
Actions, packages and the rest of Gitea from the terminal, and behaves the same
at your desk and in CI.
- **Version covered:** `gt` 0.1.0 (2026-10-23).
- **Requires:** Gitea **28 or newer**; older versions are not supported.
- **0.x:** flags and text output may still change. **Scripts must use `--json`**,
which is stable; text output is for people.
Use this skill whenever a task involves running `gt` or managing a Gitea
instance from the shell. Do not guess flags: every command's help lists its
flags and JSON fields, and the reference files below mirror that help.
## Install `gt`
```bash
# Linux, macOS, FreeBSD
curl -fsSL https://gitea.com/gitea/cli/raw/branch/main/scripts/install.sh | sh
# Windows (PowerShell)
irm https://gitea.com/gitea/cli/raw/branch/main/scripts/install.ps1 | iex
# Docker
docker run --rm gitea/gitea-cli --help
# From source
go install gitea.dev/cli/cmd/gt@latest
```
Verify with `gt version`. Binaries are also at
[dl.gitea.com/gitea-cli](https://dl.gitea.com/gitea-cli/).
## Authenticate
`gt` keeps accounts in `hosts.yml` and tokens in the system keyring (or a
private file), under `~/.config/gitea-cli/` (`GITEA_CLI_CONFIG_DIR` overrides).
It never reads `tea`'s config.
```bash
# Interactive: asks for instance, OAuth or token, storage, and git setup
gt auth login
# CI / non-interactive: token on stdin
gt auth login --host gitea.example.com --with-token < token.txt
echo "$TOKEN" | gt auth login --host gitea.example.com --with-token
# OAuth in the browser with explicit scopes
gt auth login --host gitea.example.com --oauth --scopes read:repository,read:user
# Inspect and use accounts
gt auth status # which accounts, active one, method (exit 4 if none/invalid)
gt auth status --verify # check credentials against the instance
gt auth token # print the active token (for curl/scripts)
gt auth switch # change the active account of an instance
gt auth setup-git # configure git to use gt for https push/fetch
gt doctor # diagnose settings, instance, account, repo and git
```
### Environment variables (CI)
- `GITEA_TOKEN` + `GITEA_INSTANCE_URL` (or `GITEA_CLI_HOST`): use a token
instead of stored credentials.
- `GITEA_CLI_*` prefixed variables mirror global flags and settings; see
`gt help environment` for the full list (config dir, user, repo, editor,
pager, color, http timeout, ...).
- `GITEA_INSTANCE_INSECURE`, `GITEA_INSTANCE_SSH_HOST`: pair with `GITEA_TOKEN`.
## Core concepts
### Instance and repository selection
`gt` picks the **instance** from: repository URL, `--host`, `GITEA_CLI_HOST` /
`GITEA_INSTANCE_URL`, `default_host`, the only instance with an account, or the
instance of the clone's repository.
It picks the **repository** from: `--repo`/`-R OWNER/REPO`, `GITEA_CLI_REPO`,
`git config gt.repository` (set by `gt repo set-default`), or a git remote
(`--remote`, else the base remote `pr checkout` recorded, the current branch's
remote, upstream, or origin). Like `gh`, a clone with `upstream` and `origin`
targets `upstream`.
```bash
gt -R alice/project issue list
gt issue list --repo alice/project # same, flag after the command
gt repo set-default upstream/name # make this clone target the upstream
```
### Global flags
Work with every command, before or after the command name:
| Flag | Meaning |
| --- | --- |
| `-R, --repo OWNER/REPO` | Select a repository (accepts a URL) |
| `--host URL` | Gitea instance URL, including any base path |
| `--user name` / `--sudo user` | Act as another account / as another user (admin) |
| `--json fields` | Output JSON: comma-separated fields, or all |
| `-q, --jq expr` | Filter JSON with a jq expression; implies `--json` |
| `-y, --yes` | Accept confirmations without prompting |
| `--no-input` | Disable prompts and implicit editor/browser |
| `--interactive` | Allow prompts with machine output |
| `--debug` | Log HTTP method, URL, status, duration to stderr |
| `--cwd dir` / `--remote remote` | Repository discovery |
### JSON output
Text output is for people and may change; **use `--json` in scripts**. `--jq`
runs inside `gt`, so jq need not be installed. An unknown field reports the
available ones, and each command's help lists its JSON fields.
```bash
gt issue list --json number,title --jq '.[] | "\(.number)\t\(.title)"'
gt pr list --json number,title,head --jq '.[] | select(.head == "feature/login")'
gt run list --since 24h --json id,status,conclusion,workflow
```
Some fields cost extra requests (e.g. `pr list` reviewers, `issue view`
blocked_by/blocks) and are fetched **only when the output names them**; name
them in `--json` rather than relying on `--jq`. See `gt help formatting`.
### Exit codes
| Code | Meaning |
| --- | --- |
| 0 | success (including an empty list) |
| 1 | command failed |
| 2 | usage error (unknown command/flag, bad argument) |
| 3 | canceled (declined confirmation, Esc, timeout) |
| 4 | authentication missing or rejected |
| 8 | `gt pr checks`: some checks still pending |
| 130 | interrupted with Ctrl-C |
Commands may document further codes. See `gt help exit-codes`.
## Command map
| Group | Commands | Reference |
| --- | --- | --- |
| Auth | `auth` (login, logout, refresh, setup-git, status, switch, token) | `references/commands-core.md` |
| Repositories | `repo` (create, clone, fork, sync, view, list, edit, migrate, deploy-key, ...) | `references/commands-core.md` |
| Issues | `issue` (create, list, view, edit, close, reopen, comment, timeline, attachment) | `references/commands-core.md` |
| Pull requests | `pr` (create, list, view, checkout, diff, checks, review, merge, status, clean) | `references/commands-core.md` |
| Releases | `release` (create, list, view, edit, upload, download, asset, publish) | `references/commands-core.md` |
| Orgs & labels | `org`, `label`, `milestone`, `branch` | `references/commands-core.md` |
| Actions | `run`, `workflow`, `secret`, `variable`, `package`, `admin` | `references/commands-actions.md` |
| Everything else | `team`, `notification`, `search`, `status`, `time`, `webhook`, `wiki`, `ssh-key`, `api`, `config`, `alias`, `completion` | `references/commands-misc.md` |
**Read the reference file** when you need exact flags, arguments, accepted
`--json` fields, or examples for a command. `gt <group> <cmd> --help` is always
authoritative for the installed version.
## Common workflows
### Issue lifecycle
```bash
gt issue list --assignee @me --state open
gt issue view 12 --comments
gt issue create --title "Crash on start" --body "Steps..." --label bug --milestone v1.0
gt issue edit 12 --add-label triage --add-assignee @me
gt issue comment 12 --body "Fixed in #14"
gt issue close 12 --comment "Done in #14"
```
### Pull requests (create → checks → review → merge)
```bash
gt pr create --fill # push branch, open PR, title/body from commits
gt pr create --fill --yes # non-interactive: also push without asking
gt pr list --author @me --state all
gt pr checkout 13 --update # local branch tracking the PR head
gt pr diff 13 | git apply # pipe clean diff (git apply works)
gt pr checks 13 --watch # waits; exit 8 while pending, 1 if a check failed
gt pr review --approve
gt pr review 13 --request-changes -b "Please hash the password"
gt pr merge 13 --squash --delete-branch
```
### Actions: run, watch, logs, artifacts
```bash
gt workflow list
gt workflow run deploy.yml --ref main --field env=staging
gt run list --workflow CI --branch main --status failure
gt run watch 34 --timeout 10m && echo deployed
gt run view 34 --log
gt run logs 34 --job build --follow
gt run download 34 --name build --dir dist
gt secret set DEPLOY_TOKEN
```
### Releases
```bash
gt release create v1.0.0 dist/tool-linux dist/tool-darwin --notes-file CHANGELOG.md
gt release list
gt release upload v1.0.0 dist/tool-darwin --clobber
gt release download v1.0.0
```
### Fork / clone / keep in sync
```bash
gt repo fork --remote # inside a clone: add fork as origin, rename old origin to upstream
gt repo clone alice/project src --depth 1
gt repo sync # fast-forward the default branch from its remote
gt repo sync bob/project # fork without a local remote: update it on the server
```
## Coming from `tea`
`gt` is a new tool, not an upgrade of `tea`; nothing is migrated and both can be
installed side by side.
| `tea` | `gt` |
| --- | --- |
| `tea login add`, `tea logins`, `tea whoami` | `gt auth login`, `gt auth status` |
| `tea open` | `--web` on the relevant command |
| `tea clone` | `gt repo clone` |
| `tea comment` | `gt issue comment`, `gt pr comment` |
| `tea actions ...` | `gt run`, `gt workflow`, `gt secret`, `gt variable` |
## Gotchas
- **Scripts:** always parse `--json`, never text output. Fields are stable;
columns and wording are not, in 0.x.
- **`gt pr checks`** exits **8** while checks are pending and **1** when one
failed — chain `gt pr checks 13 --watch && gt pr merge 13`.
- **First-run auth in CI** fails with exit **4**; set `GITEA_TOKEN` and
`GITEA_INSTANCE_URL`, or `gt auth login --with-token`.
- **Fork vs upstream:** in a clone with `upstream` and `origin`, commands target
`upstream`. Use `gt repo set-default --view`/`--unset`, or `-R`, to change.
- **Non-interactive prompts:** pass `--no-input` or `--yes`; with `TERM=dumb`
every prompt is asked as a plain line, which works with screen readers.
- **`--json` extra-request fields** are empty unless named in `--json`. Name
them (e.g. `--json number,title,reviewers`), don't rely on `--jq` traversal.
- **`release create` never pushes:** push the tag first, or pass `--target`.
- **Labels/milestones** must already exist in the repository; create them with
`gt label create` / `gt milestone create` (or `gt label import`).
- **Help topics** for the details above: `gt help environment`,
`gt help formatting`, `gt help exit-codes`.
@@ -0,0 +1,262 @@
# Command reference: Actions
`gt` treats Gitea Actions as first-class. Groups: `run` (workflow runs), `workflow`
(definitions and dispatch), `secret`, `variable`, `package` (registry), and `admin`.
`gt <group> <cmd> --help` is authoritative for the installed version.
**Run argument:** a run ID (`34`, `#34`) or a run URL
(`https://HOST/OWNER/REPO/actions/runs/34`). Without one, a terminal asks you to
pick a recent run.
**JSON fields (run):** `actor, attempt, branch, commit, completed_at, conclusion,
created_at, event, id, jobs, run_number, started_at, status, title, updated_at,
url, workflow, workflow_path`.
---
## run
```text
gt run <command>
artifact cancel delete download jobs list logs rerun view watch
```
`run list` aliases `run ls`.
### list
`-u/--actor @me`, `-b/--branch`, `-c/--commit SHA|rev`, `-e/--event`,
`-w/--workflow file|name`, `-s/--status` (status or conclusion, repeatable),
`--since`/`--until` (date, RFC3339, or duration ago; scans up to 5000 runs),
`-L/--limit`, `--page`.
```bash
gt run list
gt run list --workflow CI --branch main --status failure
gt run list --since 24h --json id,status,conclusion,workflow
```
### view / watch
- `view [<run-id>] [--log] [--no-jobs] [-w]` — run, jobs and steps.
- `watch [<run-id>] [-i|--interval 3s] [--timeout 1h]` — refresh until done;
**fails when the run completes without success**; tolerates a 5-minute outage.
```bash
gt run view 34
gt run view 34 --json jobs --jq '.jobs[] | {name, conclusion}'
gt run watch 34 --timeout 10m && echo deployed
```
### logs
`logs [<run-id>] [-j|--job name|ID] [-f|--follow] [--failed]
[-i|--interval 5s] [-O|--output file|-] [-D|--dir dir] [--timeout 1h]
[--clobber] [--skip-existing]`
Prints each job's logs, job names to stderr. `--follow` waits for jobs and new
lines. `--output`/`--dir` download the whole run's logs as a ZIP.
```bash
gt run logs 34
gt run logs 34 --job build --follow
gt run logs 34 --output logs.zip
```
### download
`download [<run-id>] [-n|--name artifact] [-D|--dir dir] [-O|--output path|-]
[--zip] [--clobber] [--skip-existing]` — extracts each artifact into a
directory named after it; a single `--name` extracts into the destination
itself; `--zip` keeps archives.
```bash
gt run download 34
gt run download 34 --name build --dir dist
gt run download 34 --zip
```
### jobs / artifact list / cancel / rerun / delete
- `jobs [<run-id>] [-L n] [--page n]` — JSON: `completed_at, conclusion,
created_at, id, labels, name, run_attempt, started_at, status, steps, url`.
- `artifact list [<run-id>]` — list uploaded artifacts.
- `cancel [<run-id>] [--force]` — keeps the run and logs.
- `rerun [<run-id>] [--failed] [-j|--job name|ID]` — all jobs, failed only, or one.
- `delete [<run-id>]`.
```bash
gt run jobs 34 --json id,conclusion --jq '.[] | select(.conclusion == "failure") | .id'
gt run rerun 34 --failed
```
---
## workflow
```text
gt workflow <command>
disable enable list run view
```
`workflow list` aliases `workflow ls`.
**Workflow argument:** file name (`ci.yml`), name without extension (`ci`),
path (`.gitea/workflows/ci.yml`), or workflow name (`CI`).
**JSON fields:** `id, name, path, state, url`.
### run (dispatch)
`gt workflow run <workflow>` with `-r/--ref branch|tag`,
`-f/--field key=value` (repeatable), `--follow`, `--interval 2s`,
`--timeout 30m`. Requires a `workflow_dispatch` trigger. Inputs are validated
against the declared inputs: unknown, missing-required, or invalid choice/boolean
values are refused. The workflow must exist on the default branch (like `gh`);
`--ref` selects the version that runs. Without `--ref`, runs on the checked-out
branch if it is on the server.
JSON fields: `id, url`.
```bash
gt workflow run CI
gt workflow run ci.yml --ref main -f target=production -f dry_run=false
gt workflow run nightly --follow
```
### view / list / enable / disable
- `view <workflow> [-r ref] [--yaml] [-w]` — workflow and recent runs.
- `list`
- `enable <workflow>`, `disable <workflow>`
```bash
gt workflow view CI
gt workflow view ci.yml --yaml --ref feature/login
gt workflow disable Nightly
```
---
## secret
```text
gt secret <command>
delete list set
```
Secrets are read by workflows as `${{ secrets.NAME }}`. Scope: repository
(default), organization (`--org`), or your account (`--account`). Names are
stored **upper-cased**.
> The global `--user` flag selects the account `gt` acts as — it is **not** a
> scope. Use `--org` / `--account` for scope.
### set
`gt secret set [<name>]` with `-b/--body value`, `-F/--body-file file|-`,
`-d/--description`, `-f/--env-file file|-` (sets every `NAME=value`).
The value comes from the flag/file, else stdin when not a terminal (one
trailing line break removed), else a prompt.
JSON: `created_at, description, name`.
```bash
gt secret set DEPLOY_TOKEN
echo -n "$TOKEN" | gt secret set NPM_TOKEN --org acme
gt secret set --env-file .env
```
### list / delete
- `list [-L n] [--page n] [-o|--org ORG]` (alias `ls`)
- `delete <name> [-o|--org ORG] [--account] [-y|--yes]` (alias `rm`)
```bash
gt secret list --org acme
gt secret delete DEPLOY_TOKEN --org acme --yes
```
---
## variable
```text
gt variable <command>
delete get list set view
```
Variables are read by workflows as `${{ vars.NAME }}`. Same scoping and naming
rules as secrets (`--org`, `--account`; names upper-cased).
**JSON fields:** `description, name, value`.
### set / get / view / list / delete
- `set [<name>] [-b value] [-F file|-] [-d description] [-f|--env-file file|-]
[-o|--org ORG] [--account]`
- `get <name> [...]` — print just the value (for scripts).
- `view <name>` — value plus description.
- `list [-L n] [--page n] [-o|--org ORG] [--account]` (alias `ls`)
- `delete <name> [-o|--org ORG] [--account] [-y|--yes]` (alias `rm`)
```bash
gt variable set ENVIRONMENT --body staging
gt variable set CONFIG --org acme < config.json
gt variable set --env-file .env
region=$(gt variable get REGION --org acme)
gt variable list --org acme
```
---
## package
```text
gt package <command>
delete link list unlink upload versions view
```
Packages live in the registry of a user or organization: the owner of the
selected repository, else your account, unless `--owner` names another. A
package is addressed by **type** (e.g. `generic`, `npm`, `container`) and
**name**.
`package list` aliases `package ls`; `package delete` aliases `package rm`.
**JSON fields:** `created_at, creator, id, name, owner, repository, type, url,
version`; `view` adds `files`.
- `list [-t|--type type] [-S|--search text] [--owner OWNER] [-L n] [--page n]`
- `versions <type> <name> [--owner] [-L n] [--page n]`
- `view <type> <name> [<version>] [--owner]` — latest version without one.
- `upload <name> <version> <file>... [--owner]` — generic packages; each file
is stored under its base name.
- `link <type> <name> <repository> [--owner]`
- `unlink <type> <name> [--owner]`
- `delete <type> <name> [<version>] [--all] [--owner] [-y|--yes]`
```bash
gt package upload tool 1.0.0 dist/tool-linux-amd64 dist/tool-darwin-arm64
gt package list --owner acme --type container
gt package versions generic tool
gt package delete generic tool 1.0.0
```
---
## admin
```text
gt admin <command>
user (list, view, create, edit, delete)
```
Instance administration; requires an administrator account. (`--sudo user` on
other commands acts as another user.)
```bash
gt admin user list
gt admin user create alice --email alice@example.com
```
@@ -0,0 +1,428 @@
# Command reference: core
Per-command flags, arguments, JSON fields and examples for the core `gt` groups:
`auth`, `repo`, `issue`, `pr`, `release`, `org`, `label`, `milestone`, `branch`.
`gt <group> <cmd> --help` is authoritative for the installed version.
## Shared flags
- **Repository-scoped groups** (`repo`, `issue`, `pr`, `release`, `branch`,
`label`, `milestone`) inherit:
`-R, --repo OWNER/REPO`, `--remote remote`, `--cwd directory`.
- **List/view commands** additionally inherit `--json fields` and
`-q, --jq expression` (see `gt help formatting`).
- **Mutating commands** that confirm inherit `-y, --yes`.
- Global flags (`--host`, `--user`, `--sudo`, `--no-input`, `--interactive`,
`--debug`) work everywhere; see `gt help environment`.
---
## auth
```text
gt auth <command>
login logout refresh setup-git status switch token
```
### gt auth login
Log in to a Gitea instance. Without a method flag on a terminal it asks for the
instance, login method, token storage and whether git should use `gt`.
| Flag | Meaning |
| --- | --- |
| `--with-token` | Read an access token from stdin (or prompt) |
| `--oauth` | Authorize in a browser; `--client-id ID` selects the OAuth app |
| `--scopes scopes` | OAuth scopes, e.g. `read:repository,read:user` (implies `--oauth`) |
| `--credential-store {keyring\|file}` | Where to keep the token (default `keyring`) |
| `--insecure` | Skip TLS verification for this instance |
| `--header "Name: value"` | Send a header with every request (repeatable; `$VAR` expansion) |
| `--ssh-key file`, `--ssh-agent-key fp`, `--ssh-agent-principal p` | Sign requests with SSH |
| `--client-cert file`, `--client-key file` | TLS client certificate |
| `-y, --yes` | Replace an existing account without confirming |
```bash
gt auth login
gt auth login --host gitea.com --with-token < token.txt
gt auth login --host gitea.com --oauth --scopes read:repository,read:user
gt auth login --host g.example.com --with-token \
--header 'CF-Access-Client-Id: $CF_ID' --header 'CF-Access-Client-Secret: $CF_SECRET'
```
### gt auth status / token / switch / setup-git / logout / refresh
- `status [--verify] [--json ...]` — accounts per instance, active one, method.
Fails exit 4 when there is no account or the credential is missing/rejected;
with `--json` it exits 0 and you read `credential_available`, `verified`,
`error`. JSON fields: `active, credential_available, credential_store, error,
expires_at, git_credential_helper, host, method, scopes, user, verified`.
- `token` — print the active token (refreshing an expiring OAuth token). SSH-key
accounts have no token.
- `switch` — change the active account of an instance.
- `setup-git [--keep-helpers] [--local]` — configure git to ask `gt` for
credentials.
- `logout`, `refresh` (refresh an OAuth token).
```bash
gt auth status --verify
curl -H "Authorization: token $(gt auth token)" https://gitea.com/api/v1/user
```
---
## repo
```text
gt repo <command>
archive clone create delete deploy-key edit fork list migrate
rename set-default sync transfer unarchive view
```
`repo list` aliases `repo ls`; `repo create` aliases `repo new`.
**Repository argument** (where accepted): `NAME` (one of yours), `OWNER/NAME`,
`HOST/OWNER/NAME`, or a URL. Without one, the current clone's repository.
**JSON fields (repo objects):** `actions_enabled, archived, clone_url,
default_branch, description, empty, fork, forks_count, full_name, id, mirror,
mirror_interval, name, open_issues_count, open_pr_count, original_url, parent,
private, ssh_url, stars_count, template, topics, updated_at, url, website`.
### Key subcommands
- `list [<owner>] [--starred] [--watched] [--type {fork|source|mirror}] [-L n]
[--page n]`
- `view [<repo>] [-b branch] [-w]`
- `create [<name>] [--org ORG] [--private|--public] [--auto-init]
[--readme TMPL] [--gitignores TMPL] [--license TMPL] [--default-branch NAME]
[-d DESC] [--template OWNER/REPO] [--source DIR] [--push] [--clone]
[--as-template]`
- `clone <repo> [<dir>] [-- <gitflags>] [-d depth] [--no-upstream]
[-u upstream-name]` — a fork's parent is added as `upstream`; a mirror's
source as `source`.
- `fork [<repo>] [--clone] [--org ORG] [--remote] [--remote-name NAME]
[--fork-name NAME] [-- <gitflags>]` — inside a clone, `--remote` adds the fork
as `origin` and renames the old `origin` to `upstream`.
- `sync [<repo>] [-b branch]` — fast-forward a local branch (default: default
branch) from its remote without switching; for a fork/mirror without a local
remote, updates it on the server. JSON: `branch, commit, previous, remote`.
- `set-default [<repo>] [-u|--unset] [-v|--view]` — store `gt.repository` in the
clone so commands target it instead of the git remotes.
- `edit`, `delete`, `rename`, `transfer`, `archive`, `unarchive`, `migrate`,
`deploy-key`.
```bash
gt repo list --starred --json full_name,url
gt repo create project --private --auto-init --license MIT
gt repo create acme/service --template acme/service-template
gt repo create project --source . --push
gt repo fork alice/project --clone -- --depth 1
gt repo sync --branch release/1.0
gt repo sync bob/project # update the fork on the server
```
---
## issue
```text
gt issue <command>
attachment close comment create edit list reopen timeline view
```
`issue list` aliases `issue ls`; `issue create` aliases `issue new`.
**Issue argument:** `123`, `#123`, a URL, or `OWNER/REPO#123`.
**JSON fields (issue):** `assignees, author, body, comments, created_at,
due_date, id, kind, labels, milestone, number, ref, state, title, updated_at,
url`. `view`/`edit` add `blocked_by, blocks` (extra requests, only when named).
### list
| Flag | Meaning |
| --- | --- |
| `-s, --state {open\|closed\|all}` | default `open` |
| `-a, --assignee`, `-A, --author`, `--mentions` | `@me` for yourself |
| `--no-assignee` | only issues without an assignee |
| `-l, --label names`, `-m, --milestone titles` | filters |
| `--kind {issues\|pulls\|all}` | include PRs (Gitea lists PRs among issues) |
| `-S, --search text` | search titles and bodies |
| `--since`, `--until` | updated window (date, timestamp, or duration ago) |
| `-L, --limit n` (1..1000, default 30), `--page n` | pagination |
| `-w, --web` | open in browser |
```bash
gt issue list --label bug --state all
gt issue list --assignee @me --json number,title
gt issue list --kind all --milestone v1.0 | cut -f1,2
```
### create
`-t/--title`, `-b/--body`, `-F/--body-file file|-`, `-e/--editor`,
`-a/--assignee login`, `-l/--label name` (prefix `repo:`/`org:` to disambiguate),
`-m/--milestone`, `-p/--project`, `--ref`, `--deadline DATE`,
`-T/--template name`, `--attachment File`, `-w/--web`.
Gitea applies labels/milestone/assignees/deadline only to users with issue write
access; otherwise `gt` reports the left-out fields and fails.
```bash
gt issue create --title "Crash on start" --body "Steps..." \
--label bug --milestone v1.0
gt issue create --template "Bug report"
```
### edit
Adds/removes relative to current values, or replaces with `--set-*`:
`--add-label`, `--remove-label`, `--set-labels`, `--add-assignee`,
`--remove-assignee`, `--set-assignees`, `-m/--milestone`,
`--remove-milestone`, `--add-blocked-by`, `--remove-blocked-by`,
`--add-project`, `--remove-project`, `-t/--title`, `-b/--body`,
`-F/--body-file`, `-e/--editor`, `--ref`, `--deadline`. Accepts multiple issues.
```bash
gt issue edit 12 --title "Crash on start" --add-label bug
gt issue edit 12 13 --add-assignee @me --milestone v1.0
gt issue edit 12 --add-blocked-by 9
```
### close / reopen / comment / timeline / view / attachment
- `close {N}... [-c comment]`, `reopen {N}...`
- `comment {N} [-b text] [-F file] [-e] [--edit-last] [--delete-last]
[--attachment File]`; subcommands `list|view|edit|delete`. JSON: `author,
body, created_at, id, issue_number, updated_at, url`.
- `timeline {N} [-L n] [--page n]` — comments and changes, oldest first.
- `view {N} [-c|--comments] [-w]`
- `attachment {list|view|upload|download|edit|delete}`
```bash
gt issue view 12 --comments
gt issue comment 12 --body "Fixed in #14"
gt issue close 12 13 --comment "Done in #14"
```
---
## pr
```text
gt pr <command>
attachment checkout checks clean close comment create diff
edit list merge ready reopen review status timeline view
```
`pr list` aliases `pr ls`; `pr create` aliases `pr new`; `pr checkout` aliases
`pr co`.
**PR argument:** `13`, `#13`, a URL, or a head branch name (e.g. `feature/login`
or `bob:feature/login`). Without one, the PR of the current branch.
**JSON fields (PR):** `assignees, author, base, body, comments, created_at,
draft, due_date, head, head_remote_deleted, head_repo, head_sha, id, labels,
merge_commit_sha, mergeable, merged, merged_at, merged_by, milestone, number,
review_decision, reviewer_teams, reviewers, reviews, state, title, updated_at,
url`. `reviewers`, `reviewer_teams`, `reviews`, `review_decision` and
`merged_by` on `list` cost extra requests and are fetched only when named.
### list
`-s, --state {open|closed|merged|all}` (default `open`), `-a/--assignee`,
`-A/--author`, `--no-assignee`, `-l/--label`, `-m/--milestone`,
`-B/--base branch`, `-H/--head branch|OWNER:BRANCH`, `-d/--draft`,
`-S/--search`, `--sort`, `-L/--limit`, `--page`, `-w/--web`.
### create
`--fill` (title/body from commits), `-t/--title`, `-b/--body`,
`-F/--body-file`, `-e/--editor`, `-B/--base`, `-H/--head`, `-d/--draft`,
`-a/--assignee`, `-r/--reviewer`, `--reviewer-team`, `-l/--label`,
`-m/--milestone`, `-p/--project`, `--deadline`, `--attachment`,
`--allow-maintainer-edits` (default true), `--agit` (+ `--topic`), `-w/--web`,
`-y/--yes`.
Pushes a not-yet-remote branch after confirmation (`--yes` in CI). A branch
without a same-named upstream goes to the fork when origin is a fork, or to the
only remote of your own fork; otherwise to the repository's remote.
```bash
gt pr create --fill --yes
gt pr create -t "Add login" -b "Closes #1" -B develop -r carol -l enhancement
```
### checkout / diff / checks
- `checkout {N|url|branch} [-b branch] [--detach] [--update]` — local branch
tracking the head. JSON: `branch, commit, detached, remote, tracking`.
- `diff [{N|url|branch}] [--name-only] [--color auto|always|never] [-w]` — clean
diff when piped (`gt pr diff 13 | git apply`).
- `checks [{N|url|branch}] [--watch] [--interval d] [--timeout d] [-w]` — exit
**8** while pending, **1** on failure. JSON: `created_at, description, id,
name, sha, state, updated_at, url`.
```bash
gt pr checkout 13 --update
gt pr diff 13 | git apply
gt pr checks 13 --watch && gt pr merge 13
```
### merge
`-s/--method {merge|rebase|rebase-merge|squash|fast-forward-only}` (default:
repo's style), shortcuts `--merge`, `--rebase`, `--squash`, `--auto`
(after checks), `-d/--delete-branch` (also deletes the local head branch when
checked out), `-t/--title`, `-b/--message`, `-F/--message-file`, `-e/--editor`.
```bash
gt pr merge 13 --squash --delete-branch
gt pr merge 13 --auto --yes
```
### review
Choose the type with `-a/--approve`, `-r/--request-changes` (needs a body), or
`-c/--comment`. Flags: `-b/--body`, `-F/--body-file`, `-e/--editor`,
`--pending` (save for later), `--commit sha`,
`--comments-file file` (JSON array of `path`, `body`, `new_position` or
`old_position`), `-y/--yes`. Subcommands: `create, list, view, delete, submit,
request, cancel-request, comments, reply, resolve, unresolve, dismiss,
undismiss`. JSON: `author, body, comments_count, commit, dismissed, id,
official, stale, state, submitted_at, team, url`.
On a terminal, no type opens an interactive review that can annotate the diff
in your editor.
```bash
gt pr review --approve
gt pr review 13 -r -b "Please hash the password"
gt pr review 13 --pending --comments-file inline.json
gt pr review submit 13 --approve
```
### status / clean / ready / comment
- `status [--limit n]` — current branch's PR with checks/review, then your
authored/assigned/review-requested PRs. JSON: `assigned, authored,
current_branch, review_requested`.
- `clean [{...}] [--ignore-sha]` — delete the branch of a merged/closed PR
locally and on Gitea. JSON: `default_branch, local_branch, remote,
remote_branch, remote_deleted, remote_skip_reason, remote_skipped`.
- `ready [{...}] [--undo]` — mark ready/back to draft (toggles `WIP:`/`[WIP]`).
- `comment` — like `issue comment` (JSON: `author, body, created_at, id,
issue_number, updated_at, url`).
- `view`, `edit`, `close`, `reopen`, `timeline`, `attachment`.
---
## release
```text
gt release <command>
asset create delete download edit list publish upload view
```
`release list` aliases `release ls`; `release create` aliases `release new`.
**JSON fields:** `assets, author, body, created_at, draft, id, prerelease,
published_at, tag, target, title, url`.
### create
`gt release create [<tag>] [<file>...]` with `-t/--title`, `-n/--notes`,
`-F/--notes-file`, `-e/--editor`, `-d/--draft`, `-p/--prerelease`,
`--target branch|commit` (for a new tag), `--asset File`, `--verify-tag`.
`gt` **never pushes**: push the tag first, or let Gitea create it with
`--target`. A tag that exists only in your clone is refused without `--target`.
```bash
gt release create v1.0.0 dist/tool-linux dist/tool-darwin --notes-file CHANGELOG.md
gt release create v1.1.0-rc1 --target release/1.1 --draft --prerelease --title "1.1 RC 1"
```
### upload / download / asset / publish / edit / delete / list / view
- `upload <tag> <file>... [--name NAME] [--clobber]` — JSON per asset:
`created_at, download_count, id, name, size, url`.
- `download <tag> [...]`, `asset <list|...>`, `publish <tag>...`,
`edit <tag>...`, `delete <tag>...`, `list [-L n] [--page n]`,
`view <tag>`.
```bash
gt release upload v1.0.0 dist/tool-linux --clobber
```
---
## org
```text
gt org <command>
create delete edit list member view
```
Organizations you belong to. Teams are in `team` (see
`commands-misc.md`).
```bash
gt org list
gt org view acme
gt org member list acme
gt org create acme --description "Acme org"
```
## label
```text
gt label <command>
create delete edit export import list
```
Scope with `--org organization` for organization labels; otherwise the
repository's. Addressed by name or ID. JSON: `color, description, exclusive,
id, is_archived, name`.
`create <name> [-c color] [-d description] [--exclusive] [--archived]
[-f/--force]` — random color without `-c`; `--force` updates on name clash.
```bash
gt label create bug --color d73a4a --description "Something is broken"
gt label create "priority/high" --exclusive
gt label export labels.yml
gt label import labels.yml
```
## milestone
```text
gt milestone <command>
close create delete edit issue list reopen view
```
Addressed by title or ID. `milestone issue` manages the issues/PRs in it.
```bash
gt milestone create v1.0 --deadline 2026-12-31 --description "First release"
gt milestone list --state open
gt milestone issue list v1.0
```
## branch
```text
gt branch <command>
create delete list protect rename unprotect view
```
Server-side branches (use `git` for local branches).
```bash
gt branch list
gt branch create release/1.0 --source main
gt branch protect main --required-approvals 2 --status-check ci/build
gt branch view main
```
@@ -0,0 +1,331 @@
# Command reference: misc
Remaining `gt` groups: `team`, `notification`, `search`, `status`, `time`,
`webhook`, `wiki`, `ssh-key`, `api`, `config`, `alias`, `completion`.
`gt <group> <cmd> --help` is authoritative for the installed version.
---
## team
```text
gt team <command>
create delete edit list member repo view
```
Teams grant members access to an organization's repositories. In JSON, `access`
is the effective access shown in text (e.g. `write`, `"write (code, issues,
pulls)"`); `permission` is the team-wide level Gitea reports (`none` for a team
that grants access per unit).
**JSON fields:** `access, all_repositories, can_create_repo, description, id,
name, organization, permission, units`.
- `create <org> [<name>] [--name NAME] [--permission {read|write|admin}]
[--unit repo.code=write,repo.wiki=read] [--all-repositories]
[--can-create-repo] [-d description]`
- `edit`, `delete`, `view`, `list`
- `member {add|list|remove}` — adding a user to a team of an org also makes them
an org member.
- `repo {add|list|remove}` — repositories named alone (`service`) or `ORG/NAME`.
```bash
gt team create acme developers --permission write
gt team create acme/reviewers --unit repo.code=read,repo.pulls=write
gt team member add acme/developers bob
gt team repo add acme/developers service
```
---
## notification
```text
gt notification <command>
list mark-read mark-unread pin unpin view watch
```
Across your whole inbox unless `-R`/`--this-repo` selects a repository. **IDs
are notification thread IDs, not issue numbers.** `--type` is `issue`, `pull`,
`commit`, or `repository`.
**JSON fields:** `id, number, pinned, repository, state, title, type, unread,
updated_at, url`.
- `list [--status unread,read,pinned] [--type ...] [--since/--before when]
[-L n] [--page n] [--this-repo]` (alias `ls`)
- `view <id> [--this-repo]` — marks unread as read.
- `mark-read [<id>...] [--all] [--status ...] [--before when] [--this-repo]`,
`mark-unread`, `pin`, `unpin`.
- `watch [--type ...] [--status ...] [--interval 5s] [--timeout d] [--json]` —
streams as they arrive; on a terminal runs until Ctrl-C, otherwise stops after
1 minute unless `--timeout` is given.
```bash
gt notification list
gt notification list --type pull --since 24h
gt notification mark-read --all -R alice/project
gt notification watch --type pull --json id,repository,title --timeout 0 | ./notify.sh
```
---
## search
```text
gt search <command>
issue pr repo
```
Searches the selected instance within what your account can see. Words match
titles and bodies.
- `search repo [<query>...] [--topic] [--owner OWNER] [--type {fork|source|mirror}]
[--archived[=false]] [--private[=false]] [--sort {alpha|created|updated|size|id}]
[--order {asc|desc}] [-L n] [--page n]`
- `search issue [<query>...] [--assigned] [--authored] [--mentioned]
[-A author] [-l label] [-m milestone] [--owner] [--team team] [-s state]
[--since/--until when] [-L n] [--page n]` (alias `search issues`)
- `search pr [<query>...]` — like issue plus `--review-requested`, `--reviewed`
(instance-wide) (alias `search prs`).
`search issue`/`pr` JSON: `author, body, created_at, id, number, repository,
state, title, type, updated_at, url`.
```bash
gt search repo command line
gt search repo --owner acme --archived
gt search issue "login error"
gt search issue crash -R alice/project --label bug --milestone v1.0
gt search pr --review-requested
```
---
## status
```text
gt status [flags]
```
Open issues and PRs assigned to you, reviews requested from you, and discussions
mentioning you; in a clone it also lists failing Actions runs. `-R` scopes
everything to one repository.
Flags: `--limit n` (1..100, default 30), `--runs` (default true).
JSON: `assigned_issues, failing_runs, host, mentions, pull_requests,
repository, runs_included, runs_repository, user`.
```bash
gt status
gt status -R alice/project --runs=false
```
---
## time
```text
gt time <command>
create delete list reset
```
Log time on issues/PRs. Durations use `h`, `m`, `s` (`1h25m` or `"1h 25m"`).
`create` aliases `add`/`log`; `list` aliases `ls`; `delete` aliases `rm`.
**JSON fields:** `created_at, id, issue_number, issue_title, issue_url,
repository, seconds, user`.
- `create {issue} <duration>`
- `list [--issue N|URL] [--mine] [--username user|@me] [--since/--until when]
[--total] [-L n] [--page n]`
- `delete {issue} <time-id> [-y]`
- `reset {issue}` — delete your logged time on an issue.
```bash
gt time create 12 1h25m
gt time list --issue 12
gt time list --mine --since 168h
gt time delete 12 8
```
---
## webhook
```text
gt webhook <command>
create delete edit list view
```
Scope: repository (default), organization (`--org`), your account (`--account`),
or the instance (`--global`, administrators). Delivery URLs are shown without
credentials/path unless `view --reveal-url`. Signing secrets and authorization
headers are never shown.
**JSON fields:** `active, branch_filter, content_type, created_at, events, id,
type, updated_at, url`.
- `create [<url>] [--url URL] [--type {gitea|gogs|slack|discord|dingtalk|telegram|msteams|feishu|matrix|wechatwork|packagist}]
[--events push,issues,...] [--branch-filter glob] [--active[=false]]
[--secret-file file|-] [--authorization-header-file file|-] [--config k=v]`
- `list [-L n] [--page n]` (alias `ls`)
- `view <id> [--reveal-url]`, `edit <id>`, `delete <id>`
Events include: `create, delete, fork, push, issues, issues_only,
issue_assign, issue_label, issue_milestone, issue_comment, pull_request,
pull_request_only, pull_request_assign, pull_request_label,
pull_request_milestone, pull_request_comment, pull_request_review,
pull_request_sync, pull_request_review_request, wiki, repository, release,
package, status, workflow_run, workflow_job`.
```bash
gt webhook create https://ci.example.com/hook --events push,pull_request --secret-file secret.txt
gt webhook list --org acme
gt webhook view 3 --reveal-url
```
---
## wiki
```text
gt wiki <command>
create delete edit list revisions view
```
**JSON fields (page):** `author, body, commit_count, footer, sha, sidebar,
title, updated_at, url`; `list` returns `author, sha, title, updated_at, url`.
- `create [<title>] [-t title] [-b body] [-F file|-] [-e] [-m message]`
- `edit <title> [...]`, `view <title>`, `delete <title>`,
`list [-L n] [--page n]` (alias `ls`), `revisions <title>`
```bash
gt wiki create "Getting Started" --body-file docs/start.md
gt wiki list -R alice/project --json title,url
gt wiki view Home
```
---
## ssh-key
```text
gt ssh-key <command>
create delete list view
```
Manage the SSH public keys of your account. `create` aliases `add`; `list`
aliases `ls`.
**JSON fields:** `created_at, fingerprint, id, key, read_only, title`.
- `create [<file>|-] [-t|--title TITLE]` — without a file, reads stdin.
- `list [-L n] [--page n]`, `view <id>`, `delete <id>`
```bash
gt ssh-key add ~/.ssh/id_ed25519.pub --title "Work laptop"
gt ssh-key list --json title,fingerprint
```
---
## api
```text
gt api <endpoint> [flags]
```
Authenticated request to the instance API (path under `/api/v1`, or a full API
URL). `{owner}`, `{repo}` expand to the selected repository; `{branch}` to the
checked-out branch.
| Flag | Meaning |
| --- | --- |
| `-X, --method` | HTTP method (default GET; POST when a body is supplied) |
| `-f, --raw-field k=v` | String parameter (query for GET/HEAD, JSON body otherwise) |
| `-F, --field k=v` | Typed value: `true`/`false`/`null`, numbers, arrays, `@FILE`, `@-` |
| `-H, --header name:value` | Request header |
| `--input file` | Request body from a file, or `-` |
| `--paginate`, `--max-pages n` | Follow next-page links / list paging |
| `-i, --include` | Print status/headers to stderr |
| `--output-file file` | Write the whole response to a file |
| `--jq expr` | Filter each JSON response (jq not required) |
| `--silent`, `--verbose` | No body / request+response to stderr |
Non-2xx responses print the body and fail with the HTTP status.
```bash
gt api repos/{owner}/{repo}/issues -f state=open
gt api user -F name=alice -F admin=true
gt api repos/{owner}/{repo}/branches --paginate --jq '.[].name'
```
---
## config
```text
gt config <command>
get list path set
```
Preferences live in `config.yml`, instance settings in `hosts.yml`, in the
configuration directory (`$GITEA_CLI_CONFIG_DIR`, else `gitea-cli` under the XDG
config dir). `gt config path` prints both files.
- `get <key> [--show-source]`, `list` (alias `ls`, add `--host` for instance
settings), `set <key> <value> [--host URL] [--user NAME]`.
- Keys: `default_host`, `git_protocol`, `editor`, `prompt`, `pager`, `browser`,
`color`, `hyperlinks`, `markdown`, `remote`, `http_timeout`; instance:
`user`, `ssh_host`, `insecure`, `git_protocol`, `oauth_client_id`, `headers`,
`client_cert`, `client_key`; account: `ssh_key`, `ssh_agent`,
`ssh_certificate_principal`, `ssh_key_fingerprint`.
```bash
gt config path
gt config set editor "code --wait"
gt config set ssh_host git.example.com:2222 --host https://example.com
gt config get default_host --show-source
```
---
## alias
```text
gt alias <command>
delete list set
```
An alias expands to a `gt` command with arguments, before `gt` runs it. `$1`,
`$2`, ... take positional arguments; other arguments follow the expansion. No
shell is run; built-ins always win.
- `set <name> <expansion> [--clobber]`
- `list` (alias `ls`), `delete [<name>...] [--all]` (alias `rm`)
```bash
gt alias set il "issue list --label bug"
gt alias set review 'pr review $1 --approve'
gt alias list
```
---
## completion
```text
gt completion <command>
bash fish powershell zsh
```
Generate the shell completion script. Completion offers `--json` field names.
```bash
gt completion bash > /etc/bash_completion.d/gt
gt completion zsh > "${fpath[1]}/_gt"
```