About gitea
gitea is a skill for operating Gitea instances through the REST API, intended for development workflows involving repositories, issues, and CI. It uses direct HTTP requests and credential helper scripts, without depending on an MCP server.
Key features
- 01Repository, branch, and file operations
- 02Manage issues, comments, and pull requests
- 03Search users, organizations, and repositories
- 04Operate Actions workflows and runs
- 05Manage labels, milestones, and wikis
Use cases
- 01Creating or updating repository files in Gitea
- 02Tracking issues and reviewing pull requests
- 03Checking CI runs or managing repository packages
MCP support
The skill does not depend on an MCP server; it calls the Gitea REST API directly over HTTP.
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ zzci/ skills --skill giteaAfter installing, type/giteain Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
agents/openai.yamlreferences/api-cicd.mdapi-discovery.mdapi-issues-prs.mdapi-project.mdapi-repo.mdsetup.mdscripts/gitea.shscripts/tests/gitea.test.shDetails
From the project READMEGitea (REST API)
Operate Gitea by sending HTTP requests to $GITEA_URL/api/v1/... authenticated
by $GITEA_TOKEN. This skill does NOT depend on any MCP server — every
operation is a direct curl call.
Keep this entry file small. Load only the reference pack the current turn needs.
Always-On Rules
- Forced forge routing. Before any forge work, run
git remote get-url originand parse the host. If the host isgithub.com, this skill does not apply — usegh, including for internal GitHub organizations. For any other host, treat it as a Gitea candidate: derivehttps://<host>as the probe base URL, runcurl -fsS --max-time 5 "https://<host>/api/v1/version", and use this skill only if HTTP 200 returns JSON with aversionfield. If the probe fails or times out, ask the user; do not guess another forge. - Resolve
$GITEA_URL+$GITEA_TOKENfrom named env pairs, not from the user. Sourcescripts/gitea.sh, then callgitea_autoto select the pair whose URL matches the current repo'sorigin; it falls back to the unaliasedGITEA_URL/GITEA_TOKEN, then to the legacyGITEA_HOST/GITEA_ACCESS_TOKEN, then asks the user.$GITEA_URLis always the base URL without the/apisuffix. - Send
Authorization: token $GITEA_TOKENon every request. Never put the token in the query string (?token=) — it would be logged. Prefergitea/gitea_json: they pass the header through a file descriptor, so the token stays out of the process list; the rawcurl "${AUTH[@]}"examples expose it to other local users viaps. - Prefer
curl -spiped tojqso results are easy to inspect. Always include-o /dev/null -w '%{http_code}\n'(or--fail-with-body) when verifying success on write/delete calls — Gitea returns success bodies on 2xx and a{ "message": "...", "url": "..." }error envelope on 4xx/5xx. - Never interpolate user or free-form text into inline JSON. Build the body with
jq -ninto amktempfile, then callgitea_json METHOD PATH FILE; it validates JSON and sends it with--data-binary @file. Fixed, trusted literal bodies may use-d. - Respect destructiveness. Any
DELETEagainst/branches,/contents,/releases,/tags, labels, milestones, packages, secrets, variables, or wiki pages is irreversible. State exactly what will be removed and confirm with the user unless explicitly authorized. - Pagination: most list endpoints take
?page=N&limit=M(defaultpage=1,limit=30, server max usually 50). A few older endpoints acceptper_page=as an alias. Loop pages until the response is empty orLink: rel="next"is absent. PUT /repos/{owner}/{repo}/contents/{path}(create/update file):contentmust be base64-encoded. Omitshato create; pass the current fileshato update.- Endpoint responses are the resource directly — Gitea does not wrap them in
{ success, data }. Errors come back with HTTP 4xx/5xx plus{ "message": "...", "url": "..." }.
Core Workflow
Environment
Credentials live in named pairs — GITEA_<ALIAS>_URL + GITEA_<ALIAS>_TOKEN — one pair per Gitea instance. gitea_auto matches the current repo's origin host to one of the URLs and loads that pair into $GITEA_URL + $GITEA_TOKEN. Full discovery order and helper code: setup.md.
# Example user-side ~/.bashrc:
# export GITEA_ORGA_URL=https://git.orga.com GITEA_ORGA_TOKEN=...
# export GITEA_ORGB_URL=https://git.orgb.local GITEA_ORGB_TOKEN=...
# export GITEA_URL=https://gitea.com GITEA_TOKEN=...
# Per-shell bootstrap; replace <gitea-skill> with this skill's directory:
source <gitea-skill>/scripts/gitea.sh
gitea_auto || { echo "no Gitea credentials (set GITEA_<ALIAS>_URL + GITEA_<ALIAS>_TOKEN, or GITEA_URL + GITEA_TOKEN)" >&2; exit 1; }
AUTH=(-H "Authorization: token $GITEA_TOKEN")
JSON=(-H 'Content-Type: application/json')
Env-var contract:
GITEA_<ALIAS>_URL+GITEA_<ALIAS>_TOKEN— one named pair per instance.<ALIAS>is uppercase letters/digits/underscores;GITEA_<ALIAS>_TOKEN_FILEis accepted when_TOKENis not exported.GITEA_URL+GITEA_TOKEN— unaliased single-instance fallback.$GITEA_URLis the base URL without the/apisuffix.GITEA_HOST+GITEA_ACCESS_TOKEN— gitea-mcp legacy fallback.
The helpers (gitea_list_aliases, gitea_use, gitea_auto, gitea, and gitea_json) live only in scripts/gitea.sh; source that file in every fresh shell. For SSH remotes, the HTTPS port is unknowable. If multiple aliases share a host on different ports, gitea_auto fails safely and requires gitea_use <ALIAS>.
Simple single-instance case (only GITEA_URL + GITEA_TOKEN exported): skip the helpers entirely and call curl directly:
curl -s -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user" | jq
Two usage patterns:
- Inside a repo, no env set:
gitea_autoparsesoriginand finds the alias whoseGITEA_<ALIAS>_URLhost matches. - Outside a repo, or targeting a different instance:
export GITEA_URL=https://git.aaa.comfirst, thengitea_autowill matchgit.aaa.comagainst the configured aliases and pull the right token. No need to remember which alias corresponds to which host.
Hard override: gitea_use ORGA activates the ORGA pair regardless of URL.
gitea helper
After resolving env, the sourced script provides both gitea and gitea_json. Every api-*.md example assumes they are in scope:
gitea GET /version # health
gitea GET /user # token identity
gitea GET '/repos/foo/bar/issues?state=closed&limit=50' # list with query
gitea POST /repos/foo/bar/issues -d '{"title":"x"}' # write
gitea DELETE /repos/foo/bar/releases/42 # destructive
The helper auto-injects $GITEA_URL/api/v1, the auth header, and
Content-Type: application/json; surfaces curl transport failures and HTTP
4xx/5xx (with the {message, url} envelope) on stderr and returns 1;
pretty-prints success bodies via jq.
Single issue create + comment (canonical write flow)
BODY_FILE=$(mktemp)
trap 'rm -f "$BODY_FILE"' EXIT
jq -n --arg title "$TITLE" --arg body "$BODY" \
'{title: $title, body: $body}' > "$BODY_FILE"
ISSUE=$(gitea_json POST /repos/{owner}/{repo}/issues "$BODY_FILE") || exit 1
NUM=$(echo "$ISSUE" | jq -r '.number')
jq -n --arg body "$COMMENT" '{body: $body}' > "$BODY_FILE"
gitea_json POST "/repos/{owner}/{repo}/issues/$NUM/comments" "$BODY_FILE"
Reference Packs
Load only the pack that covers the task at hand. Each pack lists every endpoint with method, path, key params, and a curl example.
references/setup.mdEnv vars, auth, /api/v1/version probe, PAT scopes, pagination, error envelope, common gotchas.references/api-repo.md— ~23 operations Repos & forks, branches, tags, commits, repo tree, file contents (read / create / update / delete), releases.references/api-issues-prs.md— issue + PR endpointslist/get/create/update issues, comments, labels-on-issue; PRlist/get/diff/files/status/reviews/create/update/close/merge/update-branch/add-reviewers; review submit/dismiss.references/api-project.md— labels, milestones, time tracking, wiki Repo & org labels (CRUD), milestones (CRUD), stopwatches + tracked time entries, wiki pages + revisions.references/api-discovery.md— users, orgs, search, notifications, version/user,/user/orgs,/users/search,/orgs/{org}/teams/search,/repos/search,/repos/issues/search, notifications list/get/mark-read,/version.references/api-cicd.md— actions & packages Workflows + runs + jobs + logs, dispatch/cancel/rerun runs, repo/org Actions secrets + variables CRUD, packages list/versions/get/delete.
Quick Routing
- Connection refused, 401, 403, missing token, PAT scopes:
references/setup.md. - Clone / fork / create repo, read or commit a file, branch / tag, release:
references/api-repo.md. - File issues, comment, manage PRs, request/submit reviews, merge:
references/api-issues-prs.md. - Labels, milestones, time tracking, wiki pages:
references/api-project.md. - "Who am I", search repos/users/issues, org list, notifications:
references/api-discovery.md. - CI runs/workflows, secrets/variables, packages:
references/api-cicd.md.
Reminder (rule 0): github.com -> use gh; failed /api/v1/version probe -> ask the user, do not guess another forge.