237e776951
CI / lint (push) Successful in 20s
CI / quality (push) Successful in 20s
CI / helm (push) Successful in 24s
CI / build (push) Successful in 24s
CI / push-validation (push) Successful in 39s
CI / security (push) Successful in 1m1s
CI / e2e_tests (push) Successful in 3m13s
CI / typecheck (push) Successful in 4m23s
CI / unit_tests (push) Successful in 6m44s
CI / integration_tests (push) Successful in 6m49s
CI / docker (push) Successful in 11s
CI / coverage (push) Successful in 6m56s
CI / status-check (push) Successful in 0s
Adds a comprehensive opencode skill under .opencode/skills/forgejo-api/
covering all 473 Forgejo REST API endpoints across 25 reference categories.
- 78 files, 23,000+ lines, 149 distinct path parameter types
- Every curl command parameterised ({owner}/{repo}/{index}/etc) and
tested against the live git.cleverthis.com server
- SKILL.md: 917-line entry point with quick-answer curl commands (35),
jq cheat sheet for chaining API calls, 14 decision trees, 12 critical
concepts (exclusive labels, lazy mergeability, SHA locking, auto-close
keywords, search envelope differences, 412 stale-edit protection), full
HTTP status code table, and environment variable reference
- references/pull-requests/: CRUD, 6 merge styles, automerge, server-side
rebase without local clone, inline review comments, diff/patch
- references/issues/: comments, reactions, attachments, dependencies,
time tracking, stopwatches, pinning
- references/labels/: repo + org labels, exclusive label groups,
GET/POST/PUT/DELETE on issues and PRs
- references/ci-actions/ + references/commit-statuses/: workflow runs,
dispatch, secrets, variables, quality gate verification
- references/web-interface/ci-logs.md: step-by-step CI log access via
CSRF web session (not available through REST API)
- references/complex-workflows/: 10 multi-step recipes including
PR review cycle, issue lifecycle, CI status check, server-side rebase,
automerge, release workflow, org setup, fork contribution
Git Objects API
Blobs
Get Blob
GET /api/v1/repos/{owner}/{repo}/git/blobs/{sha}
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
shas |
string | Comma-separated list of blob SHAs to retrieve (batch mode) |
# Get a single blob
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/blobs/abc123def456" \
-H "Authorization: token ${FORGEJO_PAT}"
# Batch retrieve multiple blobs
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/blobs/?shas={sha1},{sha2},{sha3}" \
-H "Authorization: token ${FORGEJO_PAT}"
Response:
{
"sha": "abc123def456...",
"size": 1234,
"encoding": "base64",
"content": "cGFja2FnZSBtYWlu...",
"url": "https://{FORGEJO_HOST}/api/v1/repos/{owner}/{repo}/git/blobs/abc123def456"
}
Commits
Get Commit by SHA
GET /api/v1/repos/{owner}/{repo}/git/commits/{sha}
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/commits/{sha}" \
-H "Authorization: token ${FORGEJO_PAT}"
Get Commit Diff or Patch
GET /api/v1/repos/{owner}/{repo}/git/commits/{sha}.{diffType}
diffType can be diff or patch.
# Get diff
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/commits/{sha}.diff" \
-H "Authorization: token ${FORGEJO_PAT}"
# Get patch
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/commits/{sha}.patch" \
-H "Authorization: token ${FORGEJO_PAT}"
List Commits
GET /api/v1/repos/{owner}/{repo}/commits
Parameters:
| Parameter | Type | Description |
|---|---|---|
sha |
string | SHA or branch to start from |
path |
string | Filter commits by file/directory path |
stat |
boolean | Include diff stats |
verification |
boolean | Include GPG verification info |
files |
boolean | Include list of changed files |
not |
string | Commits matching this specifier will not be listed (exclude pattern) |
page |
integer | Page number (1-based) |
limit |
integer | Page size |
# List recent commits on default branch
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/commits" \
-H "Authorization: token ${FORGEJO_PAT}"
# List commits on a specific branch
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/commits?sha={branch_or_sha}" \
-H "Authorization: token ${FORGEJO_PAT}"
# List commits for a specific file
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/commits?path=src/main.go" \
-H "Authorization: token ${FORGEJO_PAT}"
# Include diff stats and file list
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/commits?stat=true&files=true" \
-H "Authorization: token ${FORGEJO_PAT}"
# Include GPG verification
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/commits?verification=true" \
-H "Authorization: token ${FORGEJO_PAT}"
# Paginated
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/commits?page=2&limit=20" \
-H "Authorization: token ${FORGEJO_PAT}"
Get PR Associated with Commit
GET /api/v1/repos/{owner}/{repo}/commits/{sha}/pull
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/commits/{sha}/pull" \
-H "Authorization: token ${FORGEJO_PAT}"
References
List References
GET /api/v1/repos/{owner}/{repo}/git/refs
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/refs" \
-H "Authorization: token ${FORGEJO_PAT}"
Get Reference
GET /api/v1/repos/{owner}/{repo}/git/refs/{ref}
# Get a branch ref
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/refs/heads/{branch}" \
-H "Authorization: token ${FORGEJO_PAT}"
# Get a tag ref
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/refs/tags/{tag}" \
-H "Authorization: token ${FORGEJO_PAT}"
Response:
{
"ref": "refs/heads/main",
"url": "https://{FORGEJO_HOST}/api/v1/repos/{owner}/{repo}/git/refs/heads/{branch}",
"object": {
"type": "commit",
"sha": "abc123def456...",
"url": "https://{FORGEJO_HOST}/api/v1/repos/{owner}/{repo}/git/commits/{sha}"
}
}
Tags
Get Annotated Tag
GET /api/v1/repos/{owner}/{repo}/git/tags/{sha}
Returns the tag object for annotated tags (not lightweight tags).
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/tags/{sha}" \
-H "Authorization: token ${FORGEJO_PAT}"
Response:
{
"sha": "abc123def456...",
"tag": "v1.0.0",
"message": "Release v1.0.0",
"url": "https://{FORGEJO_HOST}/api/v1/repos/{owner}/{repo}/git/tags/{sha}",
"tagger": {
"name": "{author_name}",
"email": "{email}",
"date": "2024-03-15T10:00:00Z"
},
"object": {
"type": "commit",
"sha": "def789...",
"url": "https://{FORGEJO_HOST}/api/v1/repos/{owner}/{repo}/git/commits/{sha}"
},
"verification": {
"verified": false
}
}
Trees
Get Tree
GET /api/v1/repos/{owner}/{repo}/git/trees/{sha}
Parameters:
| Parameter | Type | Description |
|---|---|---|
recursive |
boolean | Get tree recursively |
page |
integer | Page number (1-based) |
per_page |
integer | Items per page |
# Get top-level tree
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/trees/{branch_or_sha}" \
-H "Authorization: token ${FORGEJO_PAT}"
# Get recursive tree (all files)
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/trees/{branch_or_sha}?recursive=true" \
-H "Authorization: token ${FORGEJO_PAT}"
# Paginated recursive tree
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/trees/{branch_or_sha}?recursive=true&page=1&per_page=100" \
-H "Authorization: token ${FORGEJO_PAT}"
Response:
{
"sha": "abc123...",
"url": "https://{FORGEJO_HOST}/api/v1/repos/{owner}/{repo}/git/trees/abc123",
"tree": [
{
"path": "README.md",
"mode": "100644",
"type": "blob",
"size": 1234,
"sha": "def456...",
"url": "https://{FORGEJO_HOST}/api/v1/repos/{owner}/{repo}/git/blobs/{sha}"
},
{
"path": "src",
"mode": "040000",
"type": "tree",
"sha": "ghi789...",
"url": "https://{FORGEJO_HOST}/api/v1/repos/{owner}/{repo}/git/trees/{sha}"
}
],
"truncated": false,
"page": 1,
"total_count": 42
}
Git Notes
Get Note for Commit
GET /api/v1/repos/{owner}/{repo}/git/notes/{sha}
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/notes/abc123def456" \
-H "Authorization: token ${FORGEJO_PAT}"
Create or Update Note
POST /api/v1/repos/{owner}/{repo}/git/notes/{sha}
curl -s -X POST "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/notes/abc123def456" \
-H "Authorization: token ${FORGEJO_PAT}" \
-H "Content-Type: application/json" \
-d '{"message": "Reviewed and approved by QA team"}'
Delete Note
DELETE /api/v1/repos/{owner}/{repo}/git/notes/{sha}
curl -s -X DELETE "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/notes/abc123def456" \
-H "Authorization: token ${FORGEJO_PAT}"
Language Statistics
Get Repository Languages
GET /api/v1/repos/{owner}/{repo}/languages
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/languages" \
-H "Authorization: token ${FORGEJO_PAT}"
Response:
{
"Go": 45678,
"JavaScript": 12345,
"CSS": 6789,
"HTML": 3456,
"Shell": 890
}
Values are byte counts for each language.
Common Patterns
Get full file tree for a branch
# Get the recursive tree to see all files
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/trees/{branch_or_sha}?recursive=true" \
-H "Authorization: token ${FORGEJO_PAT}" \
| jq '.tree[] | select(.type == "blob") | .path'
Get a file's content by path (via tree + blob)
# 1. Find the blob SHA from the tree
BLOB_SHA=$(curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/trees/{branch_or_sha}?recursive=true" \
-H "Authorization: token ${FORGEJO_PAT}" \
| jq -r '.tree[] | select(.path == "src/main.go") | .sha')
# 2. Get the blob content
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/git/blobs/${BLOB_SHA}" \
-H "Authorization: token ${FORGEJO_PAT}" \
| jq -r '.content' | base64 -d
Get commit history for a specific file
curl -s "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/commits?path=src/main.go&stat=true" \
-H "Authorization: token ${FORGEJO_PAT}" \
| jq '.[] | {sha: .sha, message: .commit.message, date: .commit.committer.date}'