Author SHA1 Message Date
bircni 31cd47a65c docs: shorten the gt guides
Cover what users need to get going and leave the details to
gt <command> --help and gt help.

Signed-off-by: bircni <[email protected]>
2026-10-22 18:34:04 +02:00
bircni 540757fe56 docs: drop the generated gt reference
The per-command reference made the pages long and repeated what
gt <command> --help shows. Keep the guides and remove the generator,
its workflow and the sidebar handling it needed.

Signed-off-by: bircni <[email protected]>
2026-10-22 18:31:31 +02:00
bircni 011651ad16 docs: add the gt guides
Signed-off-by: bircni <[email protected]>
2026-10-22 11:28:15 +02:00
bircni 55c3a392a1 feat: generate the gt command reference from gitea/cli
update_cli_docs.sh runs gt's own generator and lays the pages out for the
site: one directory per command group, front matter, titles, sidebar
order, fenced help text and rewritten links. --released succeeds while no
series is documented. A weekly workflow proposes updates like the runner's.

Signed-off-by: bircni <[email protected]>
2026-10-22 11:28:15 +02:00
bircni fe618c42be feat: add a cli product for the gt documentation
gt, the Gitea CLI, gets its own product next to the runner: the CLI entry
in the header, its own sidebars, search scope, crawler start url and
redirects, and `make cut-version PRODUCT=cli`. Until a release series is
listed, the develop docs are served at /cli/ without the unreleased banner.

A directory with an index page and no _category_.json now takes its
sidebar label and position from that page, which leads the group, so the
generated reference can be grouped by command.

Signed-off-by: bircni <[email protected]>
2026-10-22 11:28:15 +02:00
17 changed files with 314 additions and 35 deletions

No files matched your search

+1 -1
View File
@@ -92,7 +92,7 @@ update-runner-docs:
update-runner-docs-released:
./update_runner_docs.sh --released
# freezes the current docs or runner tree as a new version, see
# freezes the current docs, runner or cli tree as a new version, see
# scripts/cut-version.mjs
.PHONY: cut-version
cut-version:
+20 -1
View File
@@ -3,13 +3,14 @@
The sources of [docs.gitea.com](https://docs.gitea.com), built with
[Astro](https://astro.build) and [Starlight](https://starlight.astro.build).
The site covers three products, all served from this repository:
The site covers four products, all served from this repository:
| Product | Content | Versions | Languages |
| --- | --- | --- | --- |
| Docs | `docs/`, `versioned_docs/`, `i18n/` | next, 28, 1.27 … 1.22 | English, 简体中文, 繁體中文 |
| API | `static/swagger-*.json`, `static/openapi3-*.json` | next, 28, 1.27 … 1.22 | English |
| Runner | `runner-docs/`, `runner-docs_versioned_docs/` | develop, 5 … 0 | English |
| CLI | `cli-docs/`, `cli-docs_versioned_docs/` | develop | English |
The enterprise documentation is built and deployed from its own repository and
reached through `/enterprise/`, which a Cloudflare worker maintained elsewhere
@@ -53,6 +54,7 @@ group from the `_category_.json` of its directory.
```shell
make cut-version PRODUCT=docs VERSION=1.28
make cut-version PRODUCT=runner VERSION=6
make cut-version PRODUCT=cli VERSION=0.1
```
This freezes the current tree, its translations and its sidebar. The label of
@@ -115,6 +117,23 @@ workflow runs weekly and opens a pull request whenever the runner's CLI or
example configuration changed. Generating them needs Go, since the script builds
the runner binary.
## CLI docs
The documentation of `gt`, the Gitea CLI from
[gitea/cli](https://gitea.com/gitea/cli), is laid out like the runner docs:
| Version | Content | URL |
| --- | --- | --- |
| develop | `cli-docs/` | `/cli/` until the first release, then `/cli/develop/` |
| current series | `cli-docs_versioned_docs/version-<series>/` | `/cli/` |
| older series | `cli-docs_versioned_docs/version-<series>/` | `/cli/<series>/` |
No series is documented yet. Once a release exists, cut its series with
`make cut-version PRODUCT=cli VERSION=0.1`, then list it in `cliSeries` in
`packages/content-loader/src/products.ts`; the develop docs then move to
`/cli/develop/`. Its sidebar is written by hand in `cli-sidebars.js`. The
guides do not repeat every flag: `gt <command> --help` documents each command.
## Deployment
`main` is built and published by the `Build and Publish Docs site` workflow, to
+57
View File
@@ -0,0 +1,57 @@
---
sidebar_position: 3
---
# Logging in
On a terminal, `gt auth login` asks for the instance and how to log in. gt never asks for
your password.
## OAuth in a browser
```bash
gt auth login --host https://gitea.example.com --oauth
```
gt opens the instance's authorization page, so single sign-on and two-factor
authentication work as on the web. The browser has to run on the same machine as gt.
`--scopes` limits the token to fewer [scopes](/development/oauth2-provider#scopes); gt
refreshes OAuth tokens on its own.
## Access token
Create a token under **Settings > Applications** on the instance and pass it on stdin:
```bash
gt auth login --host https://gitea.example.com --with-token < token.txt
```
The token needs `read:user`, and the scopes of what you do with gt, such as
`write:repository` and `write:issue` for working on pull requests.
## SSH key
gt can sign its requests with an SSH key registered for your account instead of using a
token:
```bash
gt auth login --host https://gitea.example.com --ssh-key ~/.ssh/id_ed25519
```
## Where credentials are kept
Tokens go to the system keyring by default. `--credential-store file` keeps them in gt's
configuration directory instead, for machines without a keyring. `gt auth status` lists
your accounts and `gt auth logout` removes one.
## Git over HTTPS
`gt auth setup-git` lets `git push` and `git fetch` over HTTPS use gt's login. gt's own
clone and checkout commands need no setup.
## Several instances and accounts
Run `gt auth login` for each instance and account. gt picks the instance from the
repository's remote or `--host`, and the account with `gt auth switch` or `--user`.
For instances behind an access proxy, `--header` and `--client-cert` add headers and a
client certificate; see `gt auth login --help`.
+36
View File
@@ -0,0 +1,36 @@
---
sidebar_position: 4
---
# Using gt in CI
Give gt a token and an instance through the environment, and turn prompts off:
| Variable | Description |
| --- | --- |
| `GITEA_TOKEN` | Access token; gt never stores it |
| `GITEA_CLI_HOST` or `GITEA_INSTANCE_URL` | URL of the instance |
| `GITEA_CLI_REPO` | Repository, like `--repo` |
`--no-input` makes a command fail instead of prompting, and `--yes` confirms changes in
advance.
## Gitea Actions
Gitea does not allow secret names that start with `GITEA_`, so store the token as, for
example, `GT_TOKEN`:
```yaml
jobs:
deploy:
runs-on: ubuntu-latest
env:
GITEA_TOKEN: ${{ secrets.GT_TOKEN }}
GITEA_CLI_HOST: ${{ gitea.server_url }}
GITEA_CLI_REPO: ${{ gitea.repository }}
steps:
- run: curl -fsSL https://gitea.com/gitea/cli/raw/branch/main/scripts/install.sh | sh
- run: gt workflow run deploy.yml --ref main --field env=staging --no-input
```
`gt run watch` and `gt pr checks --watch` wait for runs and checks and fail when they do.
+39
View File
@@ -0,0 +1,39 @@
---
sidebar_position: 1
slug: /
---
# Gitea CLI
[gt](https://gitea.com/gitea/cli) is the official command line client for Gitea. It works
with repositories, issues, pull requests, releases, Actions and the other resources of a
Gitea instance, from a terminal or a script.
:::info Development version
These pages describe builds from the `main` branch of gitea/cli.
:::
gt needs Gitea 28 or later, and Git for the commands that clone, check out or push.
## Getting started
1. [Install gt](installation.md).
2. [Log in](authentication.md):
```bash
gt auth login
```
3. Run commands in a clone of a repository on that instance, or select one with `--repo`:
```bash
gt issue list --label bug
gt pr checkout 13
gt issue view 42 --repo gitea.com/gitea/cli
```
`gt doctor` checks your setup and suggests a fix for each problem it finds.
Every command documents itself with `--help`. `gt help environment`, `gt help formatting`
and `gt help exit-codes` cover global flags and environment variables, JSON output, and
exit codes.
+37
View File
@@ -0,0 +1,37 @@
---
sidebar_position: 2
---
# Installation
gt is a single binary for Linux, macOS, Windows and FreeBSD.
## Install script
The install script downloads gt from [dl.gitea.com](https://dl.gitea.com/gitea-cli/),
verifies its checksum and installs it.
```bash
# Linux, macOS, FreeBSD
curl -fsSL https://gitea.com/gitea/cli/raw/branch/main/scripts/install.sh | sh
```
```powershell
# Windows
irm https://gitea.com/gitea/cli/raw/branch/main/scripts/install.ps1 | iex
```
Set `GITEA_CLI_VERSION` to install a specific version, or `nightly` for the latest build
of `main`.
## Other ways
- **Binaries:** download them from [dl.gitea.com/gitea-cli](https://dl.gitea.com/gitea-cli/).
- **Docker:** the [`gitea/gitea-cli`](https://hub.docker.com/r/gitea/gitea-cli) image runs
`gt` as its entry point.
- **Go:** `go install gitea.dev/cli/cmd/gt@latest`
## Shell completion and man pages
`gt completion <shell>` prints the completion script for bash, zsh, fish or PowerShell;
`gt completion <shell> --help` shows how to load it. `gt man` prints the manual.
+22
View File
@@ -0,0 +1,22 @@
---
sidebar_position: 5
---
# Output and scripting
Scripts should read JSON: the text output is meant for people and may change.
```bash
gt pr view 123 --json number,title,state
gt issue list --json number,title --jq '.[] | "\(.number)\t\(.title)"'
```
`--json` prints all fields or the ones you list; the **JSON FIELDS** section of a command's
`--help` names them. `--jq` filters the result without needing jq installed. Piped lists
print as tab-separated values.
gt exits with 0 on success, 1 when a command fails, 2 on a usage error and 4 when
authentication is missing or rejected; `gt help exit-codes` lists all codes.
`gt api` calls any API endpoint with gt's login, and `gt alias set` defines shortcuts for
commands you use often.
+1
View File
@@ -0,0 +1 @@
[]
+16
View File
@@ -0,0 +1,16 @@
// Sidebar of the gt (Gitea CLI) documentation (develop version).
// Released versions carry their own copy in
// cli-docs_versioned_sidebars/version-<version>-sidebars.json.
module.exports = {
cli: [
{
type: 'doc',
id: 'index',
label: 'What is gt?',
},
'installation',
'authentication',
'ci',
'scripting',
],
};
+4 -2
View File
@@ -1,11 +1,13 @@
# Redirects for legacy URLs and routes the site no longer serves directly.
# The api reference and the runner docs are separate products, published in
# english only, so they have no localized copy.
# The api reference, the runner and the cli docs are separate products,
# published in english only, so they have no localized copy.
/zh-cn/api/* /api/:splat 301
/zh-tw/api/* /api/:splat 301
/zh-cn/runner/* /runner/:splat 301
/zh-tw/runner/* /runner/:splat 301
/zh-cn/cli/* /cli/:splat 301
/zh-tw/cli/* /cli/:splat 301
# The version served at the root of a product is also reachable under its
# number, which is what the release notes and old links use.
+3 -1
View File
@@ -7,6 +7,7 @@
"https://docs.gitea.com/zh-cn/",
"https://docs.gitea.com/zh-tw/",
"https://docs.gitea.com/runner/",
"https://docs.gitea.com/cli/",
"https://docs.gitea.com/api/",
"https://docs.gitea.com/enterprise/"
],
@@ -15,7 +16,8 @@
"https://docs.gitea.com/1.2*/**",
"https://docs.gitea.com/*/1.2*/**",
"https://docs.gitea.com/api/1.2*/**",
"https://docs.gitea.com/runner/[0-9]/**"
"https://docs.gitea.com/runner/[0-9]/**",
"https://docs.gitea.com/cli/[0-9]*/**"
],
"selectors": {
"lvl0": { "selector": "//nav[contains(@aria-labelledby,'starlight__sidebar')]//a[@aria-current='page']/ancestor::details//summary//span", "type": "xpath", "global": true, "default_value": "Documentation" },
+45 -2
View File
@@ -8,7 +8,7 @@
export type LocaleId = 'en-us' | 'zh-cn' | 'zh-tw';
export type ProductId = 'docs' | 'api' | 'runner' | 'enterprise';
export type ProductId = 'docs' | 'api' | 'runner' | 'cli' | 'enterprise';
/** Values substituted for `@name@` placeholders in the markdown sources. */
export interface VersionVariables {
@@ -246,6 +246,43 @@ const runnerProduct: ProductDef = {
],
};
/**
* gt, the Gitea CLI: one directory per release series, english only, like the
* runner. The label is the newest release of the series, which is also the tag
* the generated reference pages of that directory come from.
*
* Until the first series is listed here the develop docs are served at the
* product root, without the unreleased banner, since there is no release to
* point to. Listing a series moves them to `/cli/develop/`.
*/
const cliSeries: { id: string; latestRelease: string }[] = [];
const cliProduct: ProductDef = {
id: 'cli',
label: 'CLI',
base: 'cli',
locales: ['en-us'],
versions: [
{
id: 'develop',
label: 'develop',
sources: { 'en-us': 'cli-docs' },
...(cliSeries.length > 0
? { path: 'develop', banner: 'unreleased' as const }
: { path: '', latest: true }),
},
...cliSeries.map(
({ id, latestRelease }, index): VersionDef => ({
id,
label: latestRelease,
path: index === 0 ? '' : id,
latest: index === 0,
sources: { 'en-us': `cli-docs_versioned_docs/version-${id}` },
}),
),
],
};
/** API reference, rendered from the swagger documents by starlight-openapi. */
const apiProduct: ProductDef = {
id: 'api',
@@ -301,7 +338,13 @@ const enterpriseProduct: ProductDef = {
externalBaseUrl: 'https://docs.gitea.com/enterprise',
};
export const products: ProductDef[] = [docsProduct, apiProduct, runnerProduct, enterpriseProduct];
export const products: ProductDef[] = [
docsProduct,
apiProduct,
runnerProduct,
cliProduct,
enterpriseProduct,
];
export function getProduct(id: ProductId): ProductDef {
const product = products.find((candidate) => candidate.id === id);
+10 -8
View File
@@ -4,10 +4,11 @@
*
* node scripts/cut-version.mjs docs 1.28 # freezes docs/ as 1.28
* node scripts/cut-version.mjs runner 4 # freezes runner-docs/ as 4
* node scripts/cut-version.mjs cli 0.1 # freezes cli-docs/ as 0.1
*
* For the docs it copies the english tree, every translation and the sidebar
* file; for the runner the english tree and its sidebar. The version list
* (`versions.json`, `runner-docs_versions.json`) is updated too.
* file; for the runner and the cli the english tree and its sidebar. The
* version list (`versions.json`, `<product>-docs_versions.json`) is updated too.
*
* The label, the release variables (`@version@`, `@dockerVersion@`, ...) and
* which version is served at the root live in
@@ -21,8 +22,8 @@ import process from 'node:process';
const [product, version] = process.argv.slice(2);
if (!product || !version || !['docs', 'runner'].includes(product)) {
console.error('usage: node scripts/cut-version.mjs <docs|runner> <version>');
if (!product || !version || !['docs', 'runner', 'cli'].includes(product)) {
console.error('usage: node scripts/cut-version.mjs <docs|runner|cli> <version>');
process.exit(1);
}
@@ -52,6 +53,7 @@ async function freeze(from, to) {
async function freezeSidebar(from, to) {
if (await exists(to)) throw new Error(`${to} already exists`);
const sidebar = require(path.join(root, from));
await mkdir(path.join(root, path.dirname(to)), { recursive: true });
await writeFile(path.join(root, to), `${JSON.stringify(sidebar, null, 2)}\n`);
console.log(` ${from} -> ${to}`);
}
@@ -80,12 +82,12 @@ if (product === 'docs') {
await addToVersions('versions.json');
} else {
await freeze('runner-docs', `runner-docs_versioned_docs/version-${version}`);
await freeze(`${product}-docs`, `${product}-docs_versioned_docs/version-${version}`);
await freezeSidebar(
'runner-sidebars.js',
`runner-docs_versioned_sidebars/version-${version}-sidebars.json`,
`${product}-sidebars.js`,
`${product}-docs_versioned_sidebars/version-${version}-sidebars.json`,
);
await addToVersions('runner-docs_versions.json');
await addToVersions(`${product}-docs_versions.json`);
}
console.log(
+11 -8
View File
@@ -1,12 +1,13 @@
# Astro + Starlight site
Renders the gitea documentation with [Starlight](https://starlight.astro.build):
the docs (6 versions x 3 languages), the runner docs (4 series) and the api
reference (7 swagger documents). The enterprise docs stay in their own
the docs (6 versions x 3 languages), the runner docs (4 series), the gt (Gitea
CLI) docs and the api reference (7 swagger documents). The enterprise docs stay in their own
deployment and are linked from the header.
The content directories are the ones the site has always used — `docs/`,
`versioned_docs/`, `i18n/`, `runner-docs/`, `runner-docs_versioned_docs/` and
`versioned_docs/`, `i18n/`, `runner-docs/`, `runner-docs_versioned_docs/`,
`cli-docs/` and
`static/swagger-*.json` (plus `static/openapi3-*.json` since gitea 1.27) — so
the release scripts and the translation workflow stay unchanged.
@@ -40,6 +41,7 @@ pickers, the version banner, the search facets and the api schemas.
| `i18n/zh-cn/docs/version-1.27/` | `/zh-cn/` |
| `runner-docs_versioned_docs/version-3/` | `/runner/` |
| `runner-docs/` | `/runner/develop/` |
| `cli-docs/` | `/cli/`, until a cli series is released |
| `static/openapi3-27.json` | `/api/` |
| `static/openapi3-latest.json` | `/api/next/` |
| `static/swagger-26.json` | `/api/1.26/` |
@@ -60,8 +62,9 @@ of every file, the second normalizes and renders it:
Sidebars are built per (product, version, language) from `_category_.json` and
from the sidebar files (`sidebars.js`, `versioned_sidebars/`,
`runner-sidebars.js`, `runner-docs_versioned_sidebars/`), and selected in
`src/routeData.ts`, since starlight only supports a single static sidebar.
`runner-sidebars.js`, `runner-docs_versioned_sidebars/`, `cli-sidebars.js`),
and selected in `src/routeData.ts`, since starlight only supports a single
static sidebar.
Set `GITEA_DOCS_STRICT_LINKS=true` to fail the build on a broken internal link
instead of warning.
@@ -69,9 +72,9 @@ instead of warning.
## Products and languages
The docs are the site itself, so their language comes first: `/zh-cn/1.26/`.
The runner and the api are separate products and keep their language inside the
product, `/runner/zh-cn/3/`, which is reserved: both are published in english
only today. Starlight builds a fallback page in every configured language for
The runner, the cli and the api are separate products and keep their language
inside the product, `/runner/zh-cn/3/`, which is reserved: all are published in
english only today. Starlight builds a fallback page in every configured language for
every english page, so `/zh-cn/runner/` would exist; the post build integration
removes those directories and `cloudflare/_redirects` sends them to the
english page.
+3 -3
View File
@@ -23,7 +23,7 @@ type Strings = {
const en: Strings = {
versionLabel: 'Version',
languageLabel: 'Language',
products: { docs: 'Docs', api: 'API', runner: 'Runner', enterprise: 'Enterprise' },
products: { docs: 'Docs', api: 'API', runner: 'Runner', cli: 'CLI', enterprise: 'Enterprise' },
footer: { Community: 'Community', Code: 'Code', More: 'More' },
signIn: 'Sign In',
translationNotice: 'This translation may be behind the english original.',
@@ -41,7 +41,7 @@ const strings: Record<string, Strings> = {
'zh-cn': {
versionLabel: '版本',
languageLabel: '语言',
products: { docs: '文档', api: 'API', runner: 'Runner', enterprise: '企业版' },
products: { docs: '文档', api: 'API', runner: 'Runner', cli: 'CLI', enterprise: '企业版' },
footer: { Community: '社区', Code: '开源代码', More: '更多' },
signIn: '登录',
translationNotice: '当前中文文档翻译不是最新版,访问英文版本查看最新内容,或',
@@ -56,7 +56,7 @@ const strings: Record<string, Strings> = {
'zh-tw': {
versionLabel: '版本',
languageLabel: '語言',
products: { docs: '文件', api: 'API', runner: 'Runner', enterprise: '企業版' },
products: { docs: '文件', api: 'API', runner: 'Runner', cli: 'CLI', enterprise: '企業版' },
footer: { Community: '社區', Code: '開源程式碼', More: '更多' },
signIn: '登入',
translationNotice: '當前中文文檔翻譯不是最新版,訪問英文版本查看最新內容,或',
+8 -8
View File
@@ -12,9 +12,9 @@ import { getCollection } from 'astro:content';
import { repoRoot } from '../config/paths';
/**
* Sidebar files: the top level order of the docs and the
* handwritten sidebars of the runner, one per version. Read as is, so cutting a
* version keeps needing no change here.
* Sidebar files: the top level order of the docs and the handwritten sidebars
* of the runner and the cli, one per version. Read as is, so cutting a version
* keeps needing no change here.
*/
function sidebarSources(): Map<string, SidebarSourceItem[]> {
const sidebars = new Map<string, SidebarSourceItem[]>();
@@ -42,18 +42,18 @@ function sidebarSources(): Map<string, SidebarSourceItem[]> {
version.id === 'next'
? 'sidebars.js'
: `versioned_sidebars/version-${version.id}-sidebars.json`;
} else if (product.id === 'runner') {
files[`runner@${version.id}`] =
} else if (product.id === 'runner' || product.id === 'cli') {
files[`${product.id}@${version.id}`] =
version.id === 'develop'
? 'runner-sidebars.js'
: `runner-docs_versioned_sidebars/version-${version.id}-sidebars.json`;
? `${product.id}-sidebars.js`
: `${product.id}-docs_versioned_sidebars/version-${version.id}-sidebars.json`;
}
}
}
for (const [key, file] of Object.entries(files)) {
const config = read(file);
const items = config && (config.docs ?? config.runner ?? Object.values(config)[0]);
const items = config && (config.docs ?? config.runner ?? config.cli ?? Object.values(config)[0]);
if (items) sidebars.set(key, items);
}
return sidebars;
+1 -1
View File
@@ -7,7 +7,7 @@ import { z } from 'astro:content';
* per version sidebars, the version and language pickers and the search facets.
*/
export const giteaMeta = z.object({
product: z.enum(['docs', 'api', 'runner', 'enterprise']),
product: z.enum(['docs', 'api', 'runner', 'cli', 'enterprise']),
version: z.string(),
locale: z.string(),
prefix: z.string(),