Files
gitea-axi/.claude/gitea-vs-github.md

17 KiB

Gitea vs GitHub: API Feature Comparison for CLI Agent Tooling

Focus: features relevant to gitea-axi — issues, pull requests, labels, reviews, comments, auth, and API mechanics. Sources: Gitea OpenAPI spec (docs.gitea.com/api/1.21), GitHub REST docs, Gitea source structs (modules/structs/).


API Style

Feature GitHub Gitea Notes
REST API Yes — /api/v1 (actually /repos/... at api.github.com) Yes — /api/v1/repos/... Gitea mirrors GitHub's path structure closely
GraphQL API Yes — api.github.com/graphql No Gitea is REST-only; no GraphQL endpoint exists
OpenAPI spec Unofficial/community Yes — /api/swagger on every instance Gitea ships a first-class Swagger UI and JSON spec
TypeScript client @octokit/rest (hand-written) gitea-js (generated from OpenAPI) gitea-js types are auto-generated and stay in sync with the spec
API versioning api-version header (2026-03-10) Path-prefixed (/api/v1) GitHub uses a header; Gitea uses path versioning

Authentication

Feature GitHub Gitea Notes
Personal access tokens (classic) Yes — broad scope-based Yes — scope-based (read:issue, write:repository, etc.) Gitea scopes map to API route groups
Fine-grained PATs Yes — per-repo permissions, expiry required No — scopes are coarser (category-level, not per-repo) GitHub fine-grained tokens are more restrictive by default
Token creation via API No (web only for fine-grained) YesPOST /user/tokens Gitea allows programmatic token creation with BasicAuth
Token listing/deletion via API No YesGET /user/tokens, DELETE /user/tokens/{id} Gitea exposes full token lifecycle over the API
OAuth App device flow Yes No — only Authorization Code (+ PKCE) GitHub device flow is essential for headless CLI auth; Gitea lacks it
OAuth App web flow Yes Yes Both support standard Authorization Code grant
OAuth App management via API No YesGET/POST/PATCH/DELETE /user/applications/oauth2 Gitea lets users manage their own OAuth apps via API
GitHub Apps / installation tokens Yes No — no GitHub Apps concept Gitea has no equivalent of GitHub Apps or installation tokens
GITHUB_TOKEN in Actions Yes No (GITEA_TOKEN in Gitea Actions is similar but not identical) Gitea Actions has a built-in GITEA_TOKEN but it is instance-specific
HTTP Signatures (SSH key auth) No Yes Gitea accepts signatures per draft-cavage-http-signatures
Basic auth Deprecated/removed Yes (for token creation only; not recommended for general use)
Sudo (act-as) No Yes?sudo=username for admins Admin-only; useful for automation
SAML SSO token authorization Yes (org-enforced) No Gitea has no SAML SSO concept

Pagination

Feature GitHub Gitea Notes
Offset/page pagination Yes — ?page=N&per_page=N (max 100) Yes — ?page=N&limit=N Same concept; parameter names differ (per_page vs limit)
Cursor-based pagination Some endpoints (before/after) No Gitea is page-offset only
Link header (RFC 5988) Yesnext, prev, last, first Yes — same format Both provide Link headers for navigation
X-Total-Count response header No Yes Gitea returns total count in every list response; GitHub does not
x-total-count in gitea-js n/a Available as a parsed header The gitea-js client exposes this alongside the response body
Maximum per-page results 100 Configurable (instance default ~50, max configurable) Gitea's max is admin-controlled; no hard 100 cap in the API

Rate Limiting

Feature GitHub Gitea Notes
Per-user rate limit 5,000 req/hr (authenticated) No standard rate limiting Gitea uses QoS concurrency throttling, not per-user counters
X-RateLimit-* headers Yes — Limit, Remaining, Used, Reset No Gitea does not emit rate-limit headers
Secondary limits Yes (content creation, concurrency) No
QoS / overload protection No Yes — configurable [qos] section Gitea drops or queues requests under load rather than rate-limiting

Issue Management

Feature GitHub Gitea Notes
Create issue Yes — POST /repos/{owner}/{repo}/issues Yes — same path pattern
List issues Yes Yes
Get single issue Yes Yes
Edit issue Yes Yes
Delete issue No (close only) YesDELETE /repos/{owner}/{repo}/issues/{index} Gitea allows hard deletion
Issue state open / closed open / closed Same values
state_reason Yescompleted, not_planned, duplicate, reopened No Gitea has no close-reason concept
Issue type Yes — first-class type field on create/edit No GitHub supports issue type classification; Gitea does not
duplicate_issue_id Yes No
Issue dependencies (blocking) No (sub-issue relationships only) YesPOST /repos/{owner}/{repo}/issues/{index}/dependencies Gitea has explicit blocking/blocked-by relationships between issues
Issue blocking list No YesGET /repos/{owner}/{repo}/issues/{index}/blocked-by
Pin issue Partial (read-only in API response) YesPOST/DELETE /repos/{owner}/{repo}/issues/{index}/pin, position reorder Gitea has full pin CRUD including ordering
Issue timeline Yes — 30+ event types (labels, assignments, reviews, etc.) Yes — GET /repos/{owner}/{repo}/issues/{index}/timeline (comments + events) GitHub's timeline is richer in event type variety
Reactions on issues Yes — 8 types Yes — same types
Reactions on issue comments Yes Yes
Lock/unlock conversation Yes — with lock_reason (off-topic, too heated, resolved, spam) No — issues have IsLocked field but no dedicated lock endpoint visible
Subscriptions (watching) Via notifications API Yes — explicit PUT/DELETE /repos/{owner}/{repo}/issues/{index}/subscriptions Gitea exposes subscribe/unsubscribe directly on issues
Issue search (cross-repo) Yes — GET /search/issues with qualifiers Yes — GET /issues/search Both support cross-repo search
Custom field values Yes (org repos) No GitHub-specific feature
Time tracking (estimate) No YesTimeEstimate field on Issue struct Gitea has built-in time tracking
Content versioning (conflict detect) No YesContentVersion field on create/edit Gitea supports optimistic locking for concurrent edits
Original author tracking (migrations) No YesOriginalAuthor / OriginalAuthorID fields Preserved when importing from other platforms
Issue Ref field No Yes — git ref associated with issue

Milestones

Feature GitHub Gitea Notes
Milestone CRUD Yes — GET/POST/PATCH/DELETE /repos/{owner}/{repo}/milestones Yes — same path pattern
Milestone on issues Yes Yes
Milestone on PRs Yes Yes — milestone field in CreatePullRequestOption and EditPullRequestOption
Milestone properties title, description, state, due_on Same
Org-level milestones No No Neither supports org-level milestones

Label Management

Feature GitHub Gitea Notes
Repo label CRUD Yes — GET/POST/PATCH/DELETE /repos/{owner}/{repo}/labels Yes — same path pattern
Org-level labels No YesGET/POST/PATCH/DELETE /orgs/{org}/labels Gitea supports organization-scoped labels
Label properties name, color, description name, color, description
Add/remove labels on issue Yes Yes
Add/remove labels on PR Yes Yes
Replace all labels Yes Yes

Pull Request Management

Feature GitHub Gitea Notes
Create PR Yes Yes
List PRs Yes Yes
Get PR Yes Yes
Edit PR Yes Yes
Delete PR No No Neither allows hard deletion
Draft PRs Yesdraft: true on create YesDraft bool field Both support drafts
Draft PR filter in list Yes Yes — draft query param available
maintainer_can_modify Yes YesAllowMaintainerEdit field Same concept, different name
ContentVersion conflict detection No Yes Same optimistic-locking field as issues
Pin PR No Yes — same pin endpoints as issues, PinOrder field
Get PR diff Yes — Accept: application/vnd.github.diff YesGET /repos/{owner}/{repo}/pulls/{index}/diff Gitea returns raw diff text
Get PR patch Yes — Accept: application/vnd.github.patch Yes — GET /repos/{owner}/{repo}/pulls/{index}/diff with format param
List PR files (structured) Yes — GET /pulls/{number}/files YesGET /repos/{owner}/{repo}/pulls/{index}/files Returns file list with additions/deletions
List PR commits Yes YesGET /repos/{owner}/{repo}/pulls/{index}/commits
Mergeable status Yes — mergeable field YesMergeable bool field on PR
Merge strategies merge, squash, rebase merge, squash, rebase, rebase-merge (rebase + no-ff), fast-forward-only Gitea has more merge strategies
Squash merge Yes Yes
Rebase merge Yes Yes
Fast-forward-only No Yes
Rebase + explicit merge commit No Yesrebase-merge style
Auto-merge (merge when checks pass) Yes YesMergeWhenChecksSucceed field Both support scheduling a merge after CI passes
Cancel auto-merge Yes Yes — DELETE /repos/{owner}/{repo}/pulls/{index}/merge
Delete branch after merge Yes YesDeleteBranchAfterMerge field on merge request
Force merge Limited (bypass protections with permissions) YesForceMerge bool field Gitea has an explicit force-merge flag
Manually merged (mark as merged) No YesDo: "manually-merged" + MergeCommitID field Gitea allows recording a manual merge after the fact
HeadCommitSHA validation on merge No YesHeadCommitID field for merge safety
PR merge commit message/title Yes — commit_title, commit_message YesMergeTitleField, MergeMessageField
Pinned PRs list No YesGET /repos/{owner}/{repo}/pulls/pinned

Review Management

Feature GitHub Gitea Notes
List reviews Yes Yes
Create review Yes Yes
Submit pending review Yes Yes
Delete pending review Yes Yes
Dismiss review Yes — POST /pulls/{number}/reviews/{id}/dismissals YesPOST /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/dismiss
Un-dismiss review No YesPOST /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/undismiss Gitea allows undoing a dismissal
Review states APPROVED, REQUEST_CHANGES, COMMENT, PENDING, DISMISSED APPROVED, REQUEST_CHANGES, COMMENT, PENDING, (+ REQUEST_REVIEW) States match; Gitea adds REQUEST_REVIEW as a state type
DISMISSED state Yes — set by dismiss action Yes — Dismissed bool + Stale bool fields
Aggregated reviewDecision field Yes (GraphQL only)APPROVED, CHANGES_REQUESTED, REVIEW_REQUIRED No Gitea has no single aggregated review decision; must be computed from individual reviews
reviewDecision via REST No (GitHub REST also lacks this) No Both REST APIs require client-side aggregation
Official/required review flag No YesOfficial bool field on review Gitea marks reviews from required reviewers as official
Stale review flag No YesStale bool field Gitea marks reviews stale when new commits are pushed
Review request (users) Yes — POST /pulls/{number}/requested_reviewers YesPOST /repos/{owner}/{repo}/pulls/{index}/requested_reviewers
Review request (teams) Yes — team_reviewers param YesTeamReviewers param
Remove review request Yes Yes
List eligible reviewers No (must list repo collaborators separately) YesGET /repos/{owner}/{repo}/pulls/{index}/requested_reviewers returns all eligible users Gitea returns who can be requested, not just who has been
Inline code comments on review Yes — with line, side, path, start_line YesCreatePullReviewComment struct with position/path
Multi-line comment range Yes — start_line/start_side + line/side Partial — position-based rather than line-range GitHub's multi-line range is more explicit
Reply to review comment Yes — POST /pulls/{number}/comments/{id}/replies Yes — reply via in_reply_to reference
List review comments (inline) Yes Yes
Edit/delete review comment Yes Yes
Reactions on review comments Yes No — reactions are on issue comments only, not PR review comments Gitea's reaction support does not extend to PR review comments
commitId on review Yes YesCommitID field

Issue & PR Comments

Feature GitHub Gitea Notes
List issue comments Yes Yes
Create issue comment Yes Yes
Edit comment Yes Yes
Delete comment Yes Yes
Pin/unpin comment YesPUT/DELETE /issues/comments/{id}/pin No GitHub supports pinned comments on issues
Reactions on issue comments Yes — 8 types Yes — same 8 types
Reactions on PR review comments Yes No Gap in Gitea: review comment reactions not supported
body_html / body_text fields Yes No — body is Markdown only GitHub returns rendered HTML variants
author_association field Yes No GitHub classifies commenter relationship to repo

Summary: Key Gaps and Gitea Advantages

Gitea lacks (compared to GitHub)

Missing in Gitea Impact on CLI tooling
No GraphQL API Cannot get aggregated reviewDecision; must compute from review list
No reviewDecision enum (REST or GraphQL) CLI must fold APPROVED/REQUEST_CHANGES reviews client-side
No device flow OAuth Headless login requires PAT or BasicAuth; cannot do browser-less OAuth
No state_reason on issues Cannot distinguish "completed" vs "not planned" close reasons
No issue type (bug/feature classification) Labels must substitute for issue type
No fine-grained per-repo PATs Tokens are category-scoped, not repo-scoped
No X-RateLimit-* headers Cannot back off gracefully on rate limits (no limit signal)
No cursor-based pagination Must use offset pagination; large result sets may drift
No body_html on comments Must render Markdown client-side if HTML is needed
No author_association Cannot determine contributor relationship without separate lookup
No reactions on PR review comments Review comment reactions not possible
No lock/unlock issue endpoint Issue locking is not exposed as an API operation
No GitHub Apps / installation tokens Cannot use app-level auth scoping

Gitea advantages (compared to GitHub REST)

Gitea-only capability Impact on CLI tooling
X-Total-Count response header Accurate totals on every list response; no extra count query needed
Token CRUD via API Programmatic token management without web UI
OAuth app management via API Automation-friendly app registration
Hard delete issues Useful for cleanup automation
Issue dependencies (blocking/blocked-by) Richer workflow modelling
Issue pinning with position reorder Full pin management via API
Issue subscriptions endpoint Subscribe/unsubscribe without using notifications API
Org-level labels Labels shared across all org repos
Official + Stale flags on reviews Richer review state without client-side inference
Undismiss review endpoint Reversible review dismissals
Eligible reviewer list on PR Know who can review before requesting
ForceMerge flag Explicit force-merge without separate branch protection bypass
manually-merged merge style Record out-of-band merges
rebase-merge + fast-forward-only styles More granular merge strategy control
ContentVersion on issues and PRs Optimistic locking for concurrent edits
Time tracking (TimeEstimate) Built-in estimation without third-party integrations
Sudo param (admin) Act-as for admin automation
HTTP Signature auth SSH key based API auth
PinOrder on PRs PRs can also be pinned, not just issues