feat(gitea-skill): Rewrite Gitea agent skill with verified API patterns

Rewrites SKILL.md with patterns verified against live Gitea 1.22.6:
- Milestones as project containers (project board API does not exist)
- Scoped workflow labels with mutual exclusivity
- Issue dependencies using IssueMeta format
- 1Password token retrieval via op read
- Default repo terraphim/agent-tasks with env var overrides

Adds setup-labels.sh for idempotent repo and label creation.
Includes research and design documents from disciplined development.
Adds pre-commit config adapted for infrastructure project.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-18 12:41:19 +01:00
parent 776b8a618e
commit c6d425be63
6 changed files with 1838 additions and 309 deletions
+409 -309
View File
@@ -1,365 +1,465 @@
---
name: gitea
description: |
AI agent skill for interacting with Gitea. Manages users, organizations,
repositories, issues, pull requests, and project boards via Gitea API.
Supports both REST API and Gitea admin CLI operations.
AI agent skill for Gitea project and task management. Provides authentication,
milestone-based project tracking, issue lifecycle with scoped workflow labels,
and shell helpers for agent automation. Targets Gitea 1.22.6.
license: Apache-2.0
version: "2.0"
gitea_version: "1.22.6"
---
You are an AI agent specializing in Gitea administration and automation. Your role is to help manage users, organizations, repositories, issues, and projects using the Gitea API and CLI tools.
You are an AI agent specializing in Gitea project and task management. You manage milestones (projects), issues (tasks), workflow labels, and dependencies via the Gitea REST API.
## Configuration
**Gitea Instance:** https://git.terraphim.cloud
**Gitea Instance:** https://git.terraphim.cloud (Gitea 1.22.6)
**Access Methods:**
1. **REST API** - Preferred for automation and scripting
2. **Admin CLI** - For user creation and administrative tasks inside container
**Default Task Repository:** `terraphim/agent-tasks`
**Required Environment Variables:**
- `GITEA_URL` - Gitea instance URL (default: https://git.terraphim.cloud)
- `GITEA_TOKEN` - API token for authentication
**Environment Variables:**
```bash
GITEA_URL="${GITEA_URL:-https://git.terraphim.cloud}"
GITEA_OWNER="${GITEA_OWNER:-terraphim}"
GITEA_REPO="${GITEA_REPO:-agent-tasks}"
GITEA_TOKEN="$(op read 'op://TerraphimPlatform/git.terraphim.cloud-admin-token/credential')"
```
## Authentication
### Get API Token
1. Login to Gitea web UI
2. Go to Settings → Applications
3. Create new token with appropriate scopes
### 1Password Token Retrieval
### Using the Token
```bash
export GITEA_TOKEN="your-token-here"
# Load 1Password service account
source ~/op_zesticai_non_prod.sh
# Read the Gitea admin token
export GITEA_TOKEN=$(op read "op://TerraphimPlatform/git.terraphim.cloud-admin-token/credential")
```
## Core Operations
**Token scopes required:** `repo`, `admin:org`, `write:user`, `read:user`
**Security rules:**
- Never echo or log `$GITEA_TOKEN`
- Never hardcode tokens in scripts or commit them
- Always use `op read` at runtime
### Verify Authentication
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user" | jq '{login, is_admin}'
```
## Base API Helper
All operations use this helper. It outputs JSON to stdout and errors to stderr.
```bash
gitea_api() {
local method="$1" endpoint="$2" data="${3:-}"
local args=(-s -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json")
if [ -n "$data" ]; then
args+=(-X "$method" -d "$data")
else
args+=(-X "$method")
fi
curl "${args[@]}" "$GITEA_URL/api/v1$endpoint"
}
```
## Initial Setup
Run once per repository to create labels:
```bash
./setup-labels.sh # Uses defaults: terraphim/agent-tasks
./setup-labels.sh myorg myrepo # Custom repo
GITEA_OWNER=zestic-ai GITEA_REPO=tasks ./setup-labels.sh # Via env vars
```
This creates the repo (if missing) and 12 scoped labels (workflow, priority, type).
## Project Management (Milestones)
Gitea 1.22.6 has no project board API. Milestones serve as project containers with built-in progress tracking.
### Create Project
```bash
gitea_create_project() {
local title="$1" desc="${2:-}" due="${3:-}"
local owner="${4:-$GITEA_OWNER}" repo="${5:-$GITEA_REPO}"
local data
data=$(jq -n --arg t "$title" --arg d "$desc" --arg due "$due" \
'{title: $t, description: $d} + (if $due != "" then {due_on: $due} else {} end)')
gitea_api POST "/repos/$owner/$repo/milestones" "$data"
}
# Example:
gitea_create_project "Sprint 2026-W08" "Weekly sprint" "2026-02-28T00:00:00Z"
```
### List Projects
```bash
gitea_api GET "/repos/$GITEA_OWNER/$GITEA_REPO/milestones?state=open" | \
jq '.[] | {id, title, open_issues, closed_issues}'
```
### Get Project Progress
```bash
gitea_progress() {
local milestone="${1:-}" owner="${2:-$GITEA_OWNER}" repo="${3:-$GITEA_REPO}"
if [ -n "$milestone" ]; then
gitea_api GET "/repos/$owner/$repo/milestones/$milestone" | jq '{
milestone: .title,
open: .open_issues,
closed: .closed_issues,
total: (.open_issues + .closed_issues),
percent_complete: (if (.open_issues + .closed_issues) > 0
then (.closed_issues * 100 / (.open_issues + .closed_issues))
else 0 end),
due_on: .due_on,
state: .state
}'
else
gitea_api GET "/repos/$owner/$repo/milestones?state=open" | \
jq '[.[] | {id, title, open: .open_issues, closed: .closed_issues,
pct: (if (.open_issues + .closed_issues) > 0
then (.closed_issues * 100 / (.open_issues + .closed_issues))
else 0 end)}]'
fi
}
```
### Close Project
```bash
gitea_api PATCH "/repos/$GITEA_OWNER/$GITEA_REPO/milestones/{id}" '{"state": "closed"}'
```
## Task Management (Issues)
### Create Task
```bash
gitea_create_task() {
local title="$1" body="$2" milestone="$3"
local labels="${4:-}" owner="${5:-$GITEA_OWNER}" repo="${6:-$GITEA_REPO}"
local data
data=$(jq -n --arg t "$title" --arg b "$body" --argjson m "$milestone" \
'{title: $t, body: $b, milestone: $m}')
if [ -n "$labels" ]; then
data=$(echo "$data" | jq --argjson l "[$labels]" '. + {labels: $l}')
fi
gitea_api POST "/repos/$owner/$repo/issues" "$data"
}
# Example -- create task in milestone 1 with "workflow:ready" (id=4) and "type:task" (id=14):
gitea_create_task "Implement auth module" "Design and implement OAuth2 flow" 1 "4,14"
```
### List Tasks by Milestone
```bash
gitea_api GET "/repos/$GITEA_OWNER/$GITEA_REPO/issues?milestones=Sprint+2026-W08&state=all" | \
jq '[.[] | {number, title, state, labels: [.labels[].name]}]'
```
### List Tasks by Workflow State
```bash
# Ready tasks (available for agents to claim)
gitea_api GET "/repos/$GITEA_OWNER/$GITEA_REPO/issues?labels=workflow:ready&state=open" | \
jq '[.[] | {number, title, labels: [.labels[].name]}]'
# In-progress tasks
gitea_api GET "/repos/$GITEA_OWNER/$GITEA_REPO/issues?labels=workflow:in-progress&state=open" | \
jq '[.[] | {number, title, assignees: [.assignees[].login]}]'
# Blocked tasks
gitea_api GET "/repos/$GITEA_OWNER/$GITEA_REPO/issues?labels=workflow:blocked&state=open" | \
jq '[.[] | {number, title}]'
```
### Update Task Labels
```bash
gitea_set_labels() {
local index="$1" labels="$2"
local owner="${3:-$GITEA_OWNER}" repo="${4:-$GITEA_REPO}"
gitea_api PUT "/repos/$owner/$repo/issues/$index/labels" "{\"labels\": [$labels]}"
}
```
### Add Comment
```bash
gitea_api POST "/repos/$GITEA_OWNER/$GITEA_REPO/issues/{index}/comments" \
"$(jq -n --arg b "Progress update: completed auth module" '{body: $b}')"
```
## Agent Workflow
Inspired by the br (beads_rust) pattern: ready -> claim -> implement -> close.
```
create_task
|
v
+---------------+
| workflow:ready |<--------+
+-------+-------+ |
| |
gitea_claim (unblock)
| |
v |
+--------------------+ +-----------------+
| workflow:in-progress|->| workflow:blocked |
+---------+----------+ +-----------------+
|
gitea_close_task
|
v
+---------------+
| workflow:done |
| (issue closed) |
+---------------+
```
Scoped labels enforce mutual exclusivity: applying `workflow:in-progress` auto-removes `workflow:ready`.
### Mark Ready
```bash
gitea_ready() {
local index="$1" owner="${2:-$GITEA_OWNER}" repo="${3:-$GITEA_REPO}"
local ready_id
ready_id=$(gitea_api GET "/repos/$owner/$repo/labels" | \
jq -r '.[] | select(.name=="workflow:ready") | .id')
gitea_api POST "/repos/$owner/$repo/issues/$index/labels" "{\"labels\": [$ready_id]}"
}
```
### Claim Task
```bash
gitea_claim() {
local index="$1" user="${2:-}" owner="${3:-$GITEA_OWNER}" repo="${4:-$GITEA_REPO}"
local ip_id
ip_id=$(gitea_api GET "/repos/$owner/$repo/labels" | \
jq -r '.[] | select(.name=="workflow:in-progress") | .id')
gitea_api POST "/repos/$owner/$repo/issues/$index/labels" "{\"labels\": [$ip_id]}"
if [ -n "$user" ]; then
gitea_api POST "/repos/$owner/$repo/issues/$index/assignees" "{\"assignees\": [\"$user\"]}"
fi
}
```
### Close Task
```bash
gitea_close_task() {
local index="$1" comment="${2:-}" owner="${3:-$GITEA_OWNER}" repo="${4:-$GITEA_REPO}"
local done_id
done_id=$(gitea_api GET "/repos/$owner/$repo/labels" | \
jq -r '.[] | select(.name=="workflow:done") | .id')
gitea_api POST "/repos/$owner/$repo/issues/$index/labels" "{\"labels\": [$done_id]}"
gitea_api PATCH "/repos/$owner/$repo/issues/$index" '{"state": "closed"}'
if [ -n "$comment" ]; then
gitea_api POST "/repos/$owner/$repo/issues/$index/comments" \
"$(jq -n --arg b "$comment" '{body: $b}')"
fi
}
```
### Workflow Command Reference
| br Command | Gitea Equivalent | Description |
|------------|------------------|-------------|
| `br ready` | `gitea_ready 1` | Mark task #1 ready |
| `br update ID --status in_progress` | `gitea_claim 1 root` | Claim task #1 |
| `br close ID` | `gitea_close_task 1 "Done"` | Complete task #1 |
| `br list --status ready` | List issues `?labels=workflow:ready` | Ready tasks |
| `br status` | `gitea_progress 1` | Milestone progress |
## Issue Dependencies
Dependencies express task ordering. Gitea uses `IssueMeta` format: `{owner, repo, index}`.
### Add Dependency
```bash
# Make issue #3 depend on issue #2 (issue #2 blocks issue #3)
gitea_api POST "/repos/$GITEA_OWNER/$GITEA_REPO/issues/3/dependencies" \
"{\"owner\": \"$GITEA_OWNER\", \"repo\": \"$GITEA_REPO\", \"index\": 2}"
```
### List Dependencies
```bash
# What blocks issue #3?
gitea_api GET "/repos/$GITEA_OWNER/$GITEA_REPO/issues/3/dependencies" | \
jq '[.[] | {number, title, state}]'
# What does issue #2 block?
gitea_api GET "/repos/$GITEA_OWNER/$GITEA_REPO/issues/2/blocks" | \
jq '[.[] | {number, title}]'
```
### Remove Dependency
```bash
gitea_api DELETE "/repos/$GITEA_OWNER/$GITEA_REPO/issues/3/dependencies" \
"{\"owner\": \"$GITEA_OWNER\", \"repo\": \"$GITEA_REPO\", \"index\": 2}"
```
## Label Scheme
All labels use scoped naming (`scope:name`) with `exclusive: true` for mutual exclusivity within each scope.
### Workflow Labels
| Label | Color | Description |
|-------|-------|-------------|
| `workflow:ready` | `#0e8a16` green | Ready for an agent to pick up |
| `workflow:in-progress` | `#fbca04` yellow | Actively being worked on |
| `workflow:blocked` | `#d93f0b` red | Blocked by a dependency |
| `workflow:done` | `#6f42c1` purple | Complete |
### Priority Labels
| Label | Color | Description |
|-------|-------|-------------|
| `priority:critical` | `#b60205` dark red | Immediate |
| `priority:high` | `#d93f0b` red | This cycle |
| `priority:medium` | `#fbca04` yellow | Normal |
| `priority:low` | `#0e8a16` green | Nice to have |
### Type Labels
| Label | Color | Description |
|-------|-------|-------------|
| `type:feature` | `#1d76db` blue | New functionality |
| `type:bug` | `#d93f0b` red | Defect fix |
| `type:task` | `#5319e7` violet | General task |
| `type:research` | `#006b75` teal | Investigation |
## Time Tracking
```bash
# Start stopwatch
gitea_api POST "/repos/$GITEA_OWNER/$GITEA_REPO/issues/{index}/stopwatch/start"
# Stop stopwatch
gitea_api POST "/repos/$GITEA_OWNER/$GITEA_REPO/issues/{index}/stopwatch/stop"
# Get tracked times
gitea_api GET "/repos/$GITEA_OWNER/$GITEA_REPO/issues/{index}/times" | jq '.[].time'
```
## MCP Integration (Optional)
The official Gitea MCP Server provides ~80 tools for repos, issues, PRs, files, and CI/CD.
It does NOT cover milestones or workflow labels -- use the shell helpers above for those.
### Claude Code Setup
```bash
claude mcp add --transport stdio --scope user gitea \
--env GITEA_ACCESS_TOKEN="$(op read 'op://TerraphimPlatform/git.terraphim.cloud-admin-token/credential')" \
--env GITEA_HOST=https://git.terraphim.cloud \
-- go run gitea.com/gitea/gitea-mcp@latest -t stdio
```
### Available MCP Tools
Repos, branches, tags, releases, files, commits, issues (CRUD + comments), PRs (CRUD + reviews + merge), org labels, CI/CD actions (secrets, variables, workflows, runs, jobs), wiki pages.
**Not covered by MCP:** milestones, repo labels, issue dependencies, time tracking, workflow labels.
## Core API Reference (Gitea 1.22.6)
### Users
#### Create Admin User (requires admin CLI)
```bash
# Inside Gitea container
# Create admin (CLI inside container)
docker exec gitea gitea admin user create \
--username <username> \
--password <password> \
--email <email> \
--admin \
--access-token
```
--username <user> --password <pass> --email <email> --admin --access-token
#### List Users (API)
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/admin/users"
```
# List users
gitea_api GET "/admin/users"
#### Get User Info
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/users/{username}"
# Get user
gitea_api GET "/users/{username}"
```
### Organizations
#### Create Organization
```bash
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/orgs" \
-d '{
"username": "myorg",
"full_name": "My Organization",
"description": "Organization description",
"visibility": "private"
}'
```
# Create org
gitea_api POST "/orgs" '{"username":"myorg","full_name":"My Org","visibility":"private"}'
#### List Organization Repos
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/orgs/{org}/repos"
# List org repos
gitea_api GET "/orgs/{org}/repos"
```
### Repositories
#### Create Repository
```bash
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/user/repos" \
-d '{
"name": "my-repo",
"description": "Repository description",
"private": true,
"auto_init": true,
"gitignores": "Rust",
"license": "MIT"
}'
```
# Create user repo
gitea_api POST "/user/repos" '{"name":"my-repo","auto_init":true,"private":true}'
#### Create Repository in Organization
```bash
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/orgs/{org}/repos" \
-d '{
"name": "my-repo",
"description": "Repository description",
"private": false
}'
```
# Create org repo
gitea_api POST "/orgs/{org}/repos" '{"name":"my-repo","private":false}'
#### Delete Repository
```bash
curl -s -X DELETE -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}"
```
# Delete repo
gitea_api DELETE "/repos/{owner}/{repo}"
#### List User Repositories
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/user/repos"
```
### Issues
#### Create Issue
```bash
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/issues" \
-d '{
"title": "Issue title",
"body": "Issue description",
"assignees": ["username"]
}'
```
#### List Issues
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/issues?state=all"
```
#### Get Issue
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/issues/{index}"
```
#### Update Issue
```bash
curl -s -X PATCH -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/issues/{index}" \
-d '{
"title": "New title",
"body": "Updated body",
"state": "open"
}'
```
#### Close/Reopen Issue
```bash
# Close issue
curl -s -X PATCH -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/issues/{index}" \
-d '{"state": "closed"}'
# Reopen issue
curl -s -X PATCH -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/issues/{index}" \
-d '{"state": "open"}'
```
#### Add Issue Comment
```bash
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/issues/{index}/comments" \
-d '{"body": "Comment text"}'
```
#### Add/Remove Issue Labels
```bash
# Add labels
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/issues/{index}/labels" \
-d '{"labels": [1, 2, 3]}'
# List available labels
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/labels"
# List user repos
gitea_api GET "/user/repos"
```
### Pull Requests
#### List Pull Requests
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/pulls?state=all"
# List PRs
gitea_api GET "/repos/{owner}/{repo}/pulls?state=all"
# Get PR
gitea_api GET "/repos/{owner}/{repo}/pulls/{index}"
# Merge PR
gitea_api POST "/repos/{owner}/{repo}/pulls/{index}/merge" '{"do":"merge"}'
```
#### Get Pull Request
### Releases
```bash
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/pulls/{index}"
```
#### Merge Pull Request
```bash
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/pulls/{index}/merge" \
-d '{"do": "merge", "merge_message": "Merge PR #1"}'
```
### Projects
#### Create Project
```bash
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/user/projects" \
-d '{
"name": "Project Name",
"description": "Project description",
"visibility": "private"
}'
```
#### Create Organization Project
```bash
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/orgs/{org}/projects" \
-d '{
"name": "Project Name",
"description": "Project description"
}'
```
#### List Projects
```bash
# User projects
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/user/projects"
# Organization projects
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/orgs/{org}/projects"
```
#### Add Issue to Project
```bash
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/projects/{project_id}/issues" \
-d '{"issue_id": 123}'
```
### Labels
#### Create Label
```bash
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/labels" \
-d '{
"name": "bug",
"color": "fc2929",
"description": "Bug report"
}'
```
### Release Notes
#### Create Release
```bash
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/repos/{owner}/{repo}/releases" \
-d '{
"tag_name": "v1.0.0",
"name": "Release v1.0.0",
"body": "Release notes",
"draft": false,
"prerelease": false
}'
```
## Helper Functions
### Bash Alias for Common Operations
Add to your shell profile:
```bash
gitea() {
local cmd="$1"
shift
case "$cmd" in
repos)
curl -s -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user/repos" | jq -r '.[].full_name'
;;
issues)
local owner="$1" repo="$2"
curl -s -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$owner/$repo/issues?state=all" | \
jq -r '.[] | "#\(.number) [\(.state)] \(.title)"'
;;
create-issue)
local owner="$1" repo="$2" title="$3" body="${4:-}"
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_URL/api/v1/repos/$owner/$repo/issues" \
-d "{\"title\": \"$title\", \"body\": \"$body\"}"
;;
*)
echo "Usage: gitea {repos|issues|create-issue}"
;;
esac
}
gitea_api POST "/repos/{owner}/{repo}/releases" \
'{"tag_name":"v1.0.0","name":"Release v1.0.0","body":"Release notes"}'
```
## Error Handling
- Check HTTP status codes (200 = success, 201 = created, 404 = not found, 401 = unauthorized)
- Use `jq` to parse JSON responses
- Rate limiting: Gitea doesn't enforce strict rate limits but be reasonable
- Token scopes: Ensure token has required permissions (repo, read:user, write:user, etc.)
## Common Use Cases
### Automated Issue Tracking
1. Create issues for task tracking
2. Add labels for categorization
3. Assign to team members
4. Link to projects for board view
5. Update status via comments
### Project Management
1. Create organization for team
2. Create project board
3. Add repositories to project
4. Add issues to project columns
5. Track progress via project API
### Repository Automation
1. Initialize repositories with templates
2. Configure branch protection
3. Add deploy keys
4. Set up webhooks
5. Mirror from GitHub
| HTTP Code | Meaning | Action |
|-----------|---------|--------|
| 200 | Success | Parse JSON response |
| 201 | Created | Resource created successfully |
| 204 | No Content | Delete succeeded |
| 401 | Unauthorized | Check GITEA_TOKEN; re-read from 1Password |
| 403 | Forbidden | Token lacks required scope |
| 404 | Not Found | Check owner/repo/index; resource may not exist |
| 409 | Conflict | Resource already exists (labels, repos) |
| 422 | Validation Error | Check request body format |
## Constraints
- Always use HTTPS in production
- Always use HTTPS
- Never commit tokens to version control
- Use environment variables for secrets
- Use `op read` for secrets at runtime
- Prefer API over CLI for idempotent operations
- Handle rate limiting gracefully
- Clean up temporary resources
- Project board API does NOT exist in Gitea 1.22.6 -- use milestones
- Issue dependency body uses `IssueMeta` format: `{owner, repo, index}`
- Scoped labels require the `exclusive: true` flag on creation
+132
View File
@@ -0,0 +1,132 @@
#!/usr/bin/env bash
# setup-labels.sh -- Idempotent setup of Gitea repo and workflow labels
# Creates the default agent-tasks repo (if missing) and 12 scoped labels.
#
# Usage:
# source ~/op_zesticai_non_prod.sh # load OP_SERVICE_ACCOUNT_TOKEN
# export GITEA_TOKEN=$(op read "op://TerraphimPlatform/git.terraphim.cloud-admin-token/credential")
# ./setup-labels.sh [OWNER] [REPO]
#
# Environment:
# GITEA_URL -- Gitea instance (default: https://git.terraphim.cloud)
# GITEA_TOKEN -- API token (required)
# GITEA_OWNER -- Org or user (default: terraphim)
# GITEA_REPO -- Repository (default: agent-tasks)
set -euo pipefail
GITEA_URL="${GITEA_URL:-https://git.terraphim.cloud}"
GITEA_OWNER="${1:-${GITEA_OWNER:-terraphim}}"
GITEA_REPO="${2:-${GITEA_REPO:-agent-tasks}}"
if [ -z "${GITEA_TOKEN:-}" ]; then
echo '{"error": "GITEA_TOKEN is not set"}' >&2
exit 1
fi
gitea_api() {
local method="$1" endpoint="$2" data="${3:-}"
local args=(-s -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json")
if [ -n "$data" ]; then
args+=(-X "$method" -d "$data")
else
args+=(-X "$method")
fi
curl "${args[@]}" "$GITEA_URL/api/v1$endpoint"
}
# --- Ensure repo exists (idempotent) ---
ensure_repo() {
local http_code
http_code=$(curl -s -o /dev/null -w '%{http_code}' \
-H "Authorization: token $GITEA_TOKEN" \
"$GITEA_URL/api/v1/repos/$GITEA_OWNER/$GITEA_REPO")
if [ "$http_code" = "200" ]; then
echo "{\"repo\": \"$GITEA_OWNER/$GITEA_REPO\", \"action\": \"exists\"}"
return 0
fi
# Try creating under org first, fall back to user repo
local result
result=$(gitea_api POST "/orgs/$GITEA_OWNER/repos" \
"{\"name\": \"$GITEA_REPO\", \"description\": \"AI agent task tracking\", \"auto_init\": true, \"private\": false}" 2>&1)
if echo "$result" | jq -e '.id' > /dev/null 2>&1; then
echo "{\"repo\": \"$GITEA_OWNER/$GITEA_REPO\", \"action\": \"created\"}"
return 0
fi
# Fall back to user repo
result=$(gitea_api POST "/user/repos" \
"{\"name\": \"$GITEA_REPO\", \"description\": \"AI agent task tracking\", \"auto_init\": true, \"private\": false}" 2>&1)
if echo "$result" | jq -e '.id' > /dev/null 2>&1; then
echo "{\"repo\": \"$GITEA_OWNER/$GITEA_REPO\", \"action\": \"created\"}"
return 0
fi
echo "{\"repo\": \"$GITEA_OWNER/$GITEA_REPO\", \"action\": \"error\", \"detail\": $result}" >&2
return 1
}
# --- Create label if it does not exist ---
ensure_label() {
local name="$1" color="$2" description="$3" exclusive="${4:-false}"
local existing
existing=$(gitea_api GET "/repos/$GITEA_OWNER/$GITEA_REPO/labels" \
| jq -r --arg n "$name" '.[] | select(.name == $n) | .id')
if [ -n "$existing" ]; then
echo "{\"name\": \"$name\", \"id\": $existing, \"action\": \"exists\"}"
return 0
fi
local payload
payload=$(jq -n \
--arg name "$name" \
--arg color "$color" \
--arg desc "$description" \
--argjson excl "$exclusive" \
'{name: $name, color: $color, description: $desc, exclusive: $excl}')
local result
result=$(gitea_api POST "/repos/$GITEA_OWNER/$GITEA_REPO/labels" "$payload")
local label_id
label_id=$(echo "$result" | jq -r '.id // empty')
if [ -n "$label_id" ]; then
echo "{\"name\": \"$name\", \"id\": $label_id, \"action\": \"created\"}"
else
echo "{\"name\": \"$name\", \"action\": \"error\", \"detail\": $result}" >&2
return 1
fi
}
# === Main ===
echo "--- Ensure repo $GITEA_OWNER/$GITEA_REPO ---"
ensure_repo
echo "--- Creating labels ---"
# Workflow labels (mutually exclusive within scope)
ensure_label "workflow:ready" "0e8a16" "Task is ready for an agent to pick up" true
ensure_label "workflow:in-progress" "fbca04" "Task is actively being worked on" true
ensure_label "workflow:blocked" "d93f0b" "Task is blocked by a dependency" true
ensure_label "workflow:done" "6f42c1" "Task is complete" true
# Priority labels (mutually exclusive within scope)
ensure_label "priority:critical" "b60205" "Must be done immediately" true
ensure_label "priority:high" "d93f0b" "Should be done this cycle" true
ensure_label "priority:medium" "fbca04" "Normal priority" true
ensure_label "priority:low" "0e8a16" "Nice to have" true
# Type labels (mutually exclusive within scope)
ensure_label "type:feature" "1d76db" "New functionality" true
ensure_label "type:bug" "d93f0b" "Defect fix" true
ensure_label "type:task" "5319e7" "General task" true
ensure_label "type:research" "006b75" "Investigation or spike" true
echo "--- Done ---"
+611
View File
@@ -0,0 +1,611 @@
# Implementation Plan: Gitea Agent Skill for Project/Task Management
**Phase**: 2 - Disciplined Design
**Date**: 2026-02-18
**Status**: DRAFT - Awaiting Approval
**Research Document**: .docs/RESEARCH-gitea-agent-skill.md
---
## 1. Overview
### Summary
Enhance the existing Gitea AI agent skill to support project and task management
workflows for AI agents. The core insight from Phase 1 research is that Gitea 1.22.6
has NO project board REST API, so milestones serve as the API-backed project container.
Labels implement a workflow state machine inspired by the br (beads_rust) pattern:
ready -> in_progress -> done.
### Approach
Option C from the research document: Dual-mode architecture combining gitea-mcp
(official MCP server with 75+ tools) for standard operations with curl/jq shell
helpers in the skill document for milestone management, issue dependencies, time
tracking, and workflow orchestration -- areas where gitea-mcp has gaps.
### Scope (5/25 Rule Applied)
**Top 5 (Will Do)**:
1. Rewrite SKILL.md with correct API endpoints (remove fake project board endpoints)
2. Add milestone-based project management (create, list, progress tracking)
3. Add label-based workflow state machine (ready/in_progress/blocked/done)
4. Add shell helper functions with JSON output for agent consumption
5. Add integration test script validating all operations against live Gitea
**Next 20 (Will NOT Do)**:
- Custom Gitea plugin for project boards
- Gitea Actions workflow templates
- Webhook-based event processing
- Dashboard or web UI
- Multi-instance Gitea federation
- Custom MCP server wrapping Gitea API
- Kanban board simulation via API
- Automated code review integration
- Release management automation
- CI/CD pipeline integration
---
## 2. Architecture
### Component Diagram
```
+--------------------------------------------------+
| AI Agent |
| (Claude Code / MCP Client) |
+--------+------------------+----------------------+
| |
v v
+----------------+ +------------------+
| gitea-mcp | | SKILL.md |
| (MCP Server) | | (Shell Helpers) |
| - repos | | - milestones |
| - issues CRUD | | - dependencies |
| - PRs | | - workflow labels |
| - users/orgs | | - progress track |
| - branches | | - time tracking |
| - files | | - setup-labels |
+-------+--------+ +--------+---------+
| |
v v
+--------------------------------------------------+
| Gitea REST API v1 |
| https://git.terraphim.cloud/api/v1 |
+--------------------------------------------------+
| Gitea 1.22.6 Instance |
+--------------------------------------------------+
```
### Data Flow
1. Agent reads SKILL.md for available operations and patterns
2. For standard CRUD (repos, issues, PRs): agent uses gitea-mcp tools
3. For milestones, dependencies, workflow: agent uses curl/jq helpers from SKILL.md
4. All helpers use GITEA_TOKEN from 1Password via op read
5. All helpers output JSON for machine-readable agent consumption
6. Labels encode workflow state; milestones encode project containers
### Key Design Decisions
| Decision | Rationale |
|----------|-----------|
| Milestones as projects | Only API-backed grouping in Gitea 1.22.6; project board API does not exist |
| Labels for workflow state | Lightweight, API-accessible, visible in UI, no custom code needed |
| curl/jq helpers (not scripts) | Copy-paste into agent context; no installation; works everywhere |
| JSON output from all helpers | Machine-readable for agent pipelines; parseable with jq |
| 1Password op read for tokens | Consistent with existing infrastructure; no plaintext secrets |
| Dual MCP + skill approach | gitea-mcp covers 80% of operations; skill fills the 20% gap |
### Eliminated Options
| Option | Why Eliminated |
|--------|---------------|
| Option A: Skill-only | Ignores existing gitea-mcp with 75+ tools; duplicates work |
| Option B: MCP-only | gitea-mcp lacks milestones, dependencies, workflow labels |
| Custom Gitea plugin | Over-engineered; requires Go development and Gitea rebuilds |
| GitHub Projects API shim | Wrong abstraction; Gitea is not GitHub |
| Database-backed state | External dependency; Gitea already stores state in issues/labels |
### Simplicity Check
- [x] Could be explained in one paragraph? YES: "Use milestones as projects, labels as workflow states, curl/jq for API calls, gitea-mcp for standard ops"
- [x] Junior developer could implement from this plan? YES: all operations are curl commands with documented endpoints
- [x] No speculative features? YES: every feature maps to a concrete user request from the design brief
- [x] Every component has a clear owner? YES: SKILL.md owned by this repo; gitea-mcp is external dependency
---
## 3. File Changes
### File 1: `.agents/skills/gitea/SKILL.md` (MODIFY)
**What changes**: Complete rewrite. Remove incorrect project board endpoints (lines 222-263).
Restructure into: Configuration, Authentication, Core Operations (repos, issues, PRs, milestones,
labels, releases), Agent Workflow (state machine, helpers), MCP Integration, Error Handling.
**Why**: Current file has non-existent API endpoints. Need milestone-based project management
and workflow state machine for agent task tracking.
**Size estimate**: ~500 lines (currently ~366 lines)
### File 2: `.agents/skills/gitea/setup-labels.sh` (NEW)
**What changes**: Shell script that creates the 12 workflow labels on a Gitea repository.
Idempotent (checks for existing labels before creating). Uses GITEA_TOKEN and GITEA_URL
environment variables.
**Why**: Labels are the foundation of the workflow state machine. Need automated setup
rather than manual UI clicks.
**Size estimate**: ~80 lines
### File 3: `.agents/skills/gitea/test-gitea-skill.sh` (NEW)
**What changes**: Integration test script that validates all skill operations against a
live Gitea instance. Creates a test repo, runs all operations, validates JSON output,
cleans up. Uses real API calls (no mocks).
**Why**: User instructions mandate no mocks. Need to verify all documented endpoints
actually work with Gitea 1.22.6.
**Size estimate**: ~200 lines
---
## 4. API Design
### Environment Variables
```bash
GITEA_URL="https://git.terraphim.cloud" # Gitea instance URL
GITEA_TOKEN="$(op read op://TerraphimPlatform/git.terraphim.cloud-admin-token/credential)" # API token from 1Password
GITEA_OWNER="${GITEA_OWNER:-terraphim}" # Org or user owning the repo
GITEA_REPO="${GITEA_REPO:-agent-tasks}" # Default repo for task tracking (user-overridable)
```
### Shell Helper Functions
All functions output JSON. All functions use these conventions:
- Exit 0 on success, non-zero on failure
- Print JSON to stdout
- Print errors to stderr
- Accept positional arguments (no flags)
#### 4.1 `gitea_api` - Base API caller
```bash
# Usage: gitea_api METHOD ENDPOINT [DATA]
# Returns: JSON response from Gitea API
gitea_api() {
local method="$1" endpoint="$2" data="${3:-}"
local args=(-s -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json")
if [ -n "$data" ]; then
args+=(-X "$method" -d "$data")
else
args+=(-X "$method")
fi
curl "${args[@]}" "$GITEA_URL/api/v1$endpoint"
}
```
#### 4.2 `gitea_create_project` - Create milestone as project
```bash
# Usage: gitea_create_project TITLE [DESCRIPTION] [DUE_DATE] [OWNER] [REPO]
# Returns: JSON milestone object with id, title, state, open_issues, closed_issues
# DUE_DATE format: 2026-03-01T00:00:00Z
# OWNER/REPO default to GITEA_OWNER/GITEA_REPO (terraphim/agent-tasks)
gitea_create_project() {
local title="$1"
local desc="${2:-}" due="${3:-}"
local owner="${4:-$GITEA_OWNER}" repo="${5:-$GITEA_REPO}"
local data
data=$(jq -n --arg t "$title" --arg d "$desc" --arg due "$due" \
'{title: $t, description: $d} + (if $due != "" then {due_on: $due} else {} end)')
gitea_api POST "/repos/$owner/$repo/milestones" "$data"
}
```
#### 4.3 `gitea_create_task` - Create issue with milestone and labels
```bash
# Usage: gitea_create_task TITLE BODY MILESTONE_ID [LABEL_IDS] [OWNER] [REPO]
# LABEL_IDS: comma-separated label IDs (e.g., "1,2,3")
# Returns: JSON issue object
gitea_create_task() {
local title="$1" body="$2" milestone="$3"
local labels="${4:-}"
local owner="${5:-$GITEA_OWNER}" repo="${6:-$GITEA_REPO}"
local data
data=$(jq -n --arg t "$title" --arg b "$body" --argjson m "$milestone" \
'{title: $t, body: $b, milestone: $m}')
if [ -n "$labels" ]; then
data=$(echo "$data" | jq --argjson l "[$labels]" '. + {labels: $l}')
fi
gitea_api POST "/repos/$owner/$repo/issues" "$data"
}
```
#### 4.4 `gitea_set_labels` - Replace all labels on an issue
```bash
# Usage: gitea_set_labels ISSUE_INDEX LABEL_IDS [OWNER] [REPO]
# LABEL_IDS: comma-separated label IDs
# Returns: JSON array of label objects
gitea_set_labels() {
local index="$1" labels="$2"
local owner="${3:-$GITEA_OWNER}" repo="${4:-$GITEA_REPO}"
gitea_api PUT "/repos/$owner/$repo/issues/$index/labels" "{\"labels\": [$labels]}"
}
```
#### 4.5 `gitea_ready` - Mark task as ready for work
```bash
# Usage: gitea_ready ISSUE_INDEX [OWNER] [REPO]
# Adds "workflow:ready" label, removes other workflow labels
gitea_ready() {
local index="$1"
local owner="${2:-$GITEA_OWNER}" repo="${3:-$GITEA_REPO}"
local ready_id
ready_id=$(gitea_api GET "/repos/$owner/$repo/labels" | jq -r '.[] | select(.name=="workflow:ready") | .id')
gitea_set_labels "$owner" "$repo" "$index" "$ready_id"
}
```
#### 4.6 `gitea_claim` - Claim task (mark in-progress, assign self)
```bash
# Usage: gitea_claim ISSUE_INDEX [USERNAME] [OWNER] [REPO]
# Sets "workflow:in-progress" label, assigns user
gitea_claim() {
local index="$1" user="${2:-}"
local owner="${3:-$GITEA_OWNER}" repo="${4:-$GITEA_REPO}"
local ip_id
ip_id=$(gitea_api GET "/repos/$owner/$repo/labels" | jq -r '.[] | select(.name=="workflow:in-progress") | .id')
gitea_set_labels "$owner" "$repo" "$index" "$ip_id"
if [ -n "$user" ]; then
gitea_api POST "/repos/$owner/$repo/issues/$index/assignees" "{\"assignees\": [\"$user\"]}"
fi
}
```
#### 4.7 `gitea_close_task` - Complete task
```bash
# Usage: gitea_close_task ISSUE_INDEX [COMMENT] [OWNER] [REPO]
# Sets "workflow:done" label, closes issue, optionally adds comment
gitea_close_task() {
local index="$1" comment="${2:-}"
local owner="${3:-$GITEA_OWNER}" repo="${4:-$GITEA_REPO}"
local done_id
done_id=$(gitea_api GET "/repos/$owner/$repo/labels" | jq -r '.[] | select(.name=="workflow:done") | .id')
gitea_set_labels "$owner" "$repo" "$index" "$done_id"
gitea_api PATCH "/repos/$owner/$repo/issues/$index" '{"state": "closed"}'
if [ -n "$comment" ]; then
local cdata
cdata=$(jq -n --arg b "$comment" '{body: $b}')
gitea_api POST "/repos/$owner/$repo/issues/$index/comments" "$cdata"
fi
}
```
#### 4.8 `gitea_progress` - Show project progress
```bash
# Usage: gitea_progress [MILESTONE_ID] [OWNER] [REPO]
# Returns: JSON with open/closed counts, percentage, task list
gitea_progress() {
local milestone="${1:-}"
local owner="${2:-$GITEA_OWNER}" repo="${3:-$GITEA_REPO}"
if [ -n "$milestone" ]; then
local ms
ms=$(gitea_api GET "/repos/$owner/$repo/milestones/$milestone")
echo "$ms" | jq '{
milestone: .title,
open: .open_issues,
closed: .closed_issues,
total: (.open_issues + .closed_issues),
percent_complete: (if (.open_issues + .closed_issues) > 0
then (.closed_issues * 100 / (.open_issues + .closed_issues))
else 0 end)
}'
else
gitea_api GET "/repos/$owner/$repo/milestones?state=open"
fi
}
```
---
## 5. Label Scheme
### Workflow Labels (mutually exclusive)
| Label | Color | Description |
|-------|-------|-------------|
| `workflow:ready` | `#0e8a16` (green) | Task is ready for an agent to pick up |
| `workflow:in-progress` | `#fbca04` (yellow) | Task is actively being worked on |
| `workflow:blocked` | `#d93f0b` (red) | Task is blocked by a dependency |
| `workflow:done` | `#6f42c1` (purple) | Task is complete |
### Priority Labels
| Label | Color | Description |
|-------|-------|-------------|
| `priority:critical` | `#b60205` (dark red) | Must be done immediately |
| `priority:high` | `#d93f0b` (red) | Should be done this cycle |
| `priority:medium` | `#fbca04` (yellow) | Normal priority |
| `priority:low` | `#0e8a16` (green) | Nice to have |
### Type Labels
| Label | Color | Description |
|-------|-------|-------------|
| `type:feature` | `#1d76db` (blue) | New functionality |
| `type:bug` | `#d93f0b` (red) | Defect fix |
| `type:task` | `#5319e7` (violet) | General task |
| `type:research` | `#006b75` (teal) | Investigation/spike |
---
## 6. Agent Workflow State Machine
```
create_task
|
v
+---------------+
| workflow:ready |<--------+
+-------+-------+ |
| |
gitea_claim (unblock)
| |
v |
+--------------------+ +------------------+
| workflow:in-progress|->| workflow:blocked |
+---------+----------+ +------------------+
|
gitea_close_task
|
v
+---------------+
| workflow:done |
| (issue closed) |
+---------------+
```
### Workflow Commands (br-inspired)
| br Command | Gitea Equivalent | Description |
|------------|------------------|-------------|
| `br ready` | `gitea_ready 1` | Mark task #1 ready |
| `br update ID --status in_progress` | `gitea_claim 1 myuser` | Claim and start task #1 |
| `br close ID` | `gitea_close_task 1 "Done"` | Complete task #1 |
| `br list --status ready` | `gitea_api GET /repos/$GITEA_OWNER/$GITEA_REPO/issues?labels=workflow:ready` | List ready tasks |
| `br status` | `gitea_progress 1` | Show milestone #1 progress |
All helpers default to `GITEA_OWNER=terraphim` and `GITEA_REPO=agent-tasks`. Override with env vars or trailing arguments.
---
## 7. Test Strategy
### Approach
Integration tests against the live Gitea instance at https://git.terraphim.cloud.
No mocks. Each test creates its own resources and cleans up afterward. Tests run
sequentially to avoid race conditions.
### Test Cases
| # | Test | Validates | Expected Result |
|---|------|-----------|-----------------|
| 1 | Create test repository | `POST /repos` | 201, JSON with repo name |
| 2 | Create labels via setup-labels.sh | `POST /repos/{owner}/{repo}/labels` | 12 labels created |
| 3 | Create milestone (project) | `gitea_create_project` | 201, JSON with milestone id |
| 4 | Create issue (task) with milestone | `gitea_create_task` | 201, JSON with issue number |
| 5 | Mark task ready | `gitea_ready` | Label set to workflow:ready |
| 6 | Claim task | `gitea_claim` | Label set to workflow:in-progress, assignee set |
| 7 | Check project progress | `gitea_progress` | JSON with 0% complete (1 open, 0 closed) |
| 8 | Close task | `gitea_close_task` | Issue state=closed, label=workflow:done |
| 9 | Check progress after close | `gitea_progress` | JSON with 100% complete |
| 10 | Delete test repository | `DELETE /repos/{owner}/{repo}` | 204, cleanup successful |
### Test Runner
```bash
# Run all tests
./test-gitea-skill.sh
# Requirements:
# - GITEA_TOKEN set (or op read available)
# - GITEA_URL set (defaults to https://git.terraphim.cloud)
# - curl, jq installed
```
### Validation Criteria
- All 10 tests pass against live Gitea 1.22.6
- All helper functions return valid JSON (validated with jq)
- Cleanup succeeds (no orphaned test repos)
- No hardcoded secrets in any file
---
## 8. Implementation Steps
### Step 1: Create setup-labels.sh (30 min)
**Files**: `.agents/skills/gitea/setup-labels.sh`
**Actions**:
1. Create `terraphim/agent-tasks` repo if it doesn't exist (idempotent)
2. Write script that creates all 12 labels
3. Make idempotent (check existing labels first)
4. Use GITEA_TOKEN, GITEA_URL, GITEA_OWNER, GITEA_REPO environment variables
5. Output JSON summary of created/existing labels
**Commit message**: "Add label setup script for Gitea agent workflow"
### Step 2: Rewrite SKILL.md (2 hours)
**Files**: `.agents/skills/gitea/SKILL.md`
**Actions**:
1. Keep frontmatter and system prompt
2. Update Configuration section with 1Password integration
3. Keep correct existing sections (users, orgs, repos, issues, PRs, releases)
4. Remove incorrect project board endpoints (lines 222-263)
5. Add Milestones section (create, list, update, delete)
6. Add Agent Workflow section (state machine, all 8 helper functions)
7. Add MCP Integration section (gitea-mcp setup and usage)
8. Add Dependencies section (issue blocking API)
9. Update Error Handling section
**Commit message**: "Rewrite Gitea skill with milestone-based project management"
### Step 3: Create test script (1 hour)
**Files**: `.agents/skills/gitea/test-gitea-skill.sh`
**Actions**:
1. Write integration test runner
2. Implement all 10 test cases
3. Add setup/teardown (create/delete test repo)
4. Add JSON validation for all outputs
5. Add color-coded pass/fail output
**Commit message**: "Add integration test script for Gitea skill"
### Step 4: Verify 1Password integration (30 min)
**Actions** (no file changes):
1. Verify gitea-token item exists in TerraphimPlatform vault (or create it)
2. Test `op read op://TerraphimPlatform/git.terraphim.cloud-admin-token/credential`
3. Verify token has required scopes (repo, admin:org, write:user)
**Commit message**: None (verification only; document findings in test output)
### Step 5: Run tests and iterate (1 hour)
**Actions**:
1. Run setup-labels.sh against a test repository
2. Run test-gitea-skill.sh
3. Fix any failing tests
4. Verify cleanup succeeded
**Commit message**: "Fix issues found during integration testing" (if needed)
**Total estimated time**: ~5 hours
---
## 9. Risk Mitigation
| Risk | Likelihood | Impact | Mitigation |
|------|-----------|--------|------------|
| Gitea API changes in future version | Low | Medium | Pin to 1.22.6 in docs; version check in test script |
| gitea-mcp adds milestone support | Low | Low | Reduces need for curl helpers; update skill to prefer MCP |
| 1Password token not configured | Medium | High | Test script checks for token before running; clear error message |
| Label name collision with existing labels | Low | Low | setup-labels.sh checks for existing labels; skips if present |
| Test repo cleanup fails | Low | Medium | Test script has explicit cleanup step; documents manual cleanup |
| Rate limiting on bulk label creation | Low | Low | Sequential creation with small delay if needed |
### Rollback Plan
All changes are in `.agents/skills/gitea/` directory. Rollback = `git revert` the commits.
No infrastructure changes. No database migrations. No service restarts needed.
---
## 10. Dependencies
| Dependency | Type | Status |
|-----------|------|--------|
| Gitea 1.22.6 running at git.terraphim.cloud | Runtime | Available |
| GITEA_TOKEN in 1Password TerraphimPlatform vault | Secret | Needs verification |
| curl | Tool | Available on bigbox |
| jq | Tool | Available on bigbox |
| gitea-mcp (optional) | MCP Server | Not yet installed; documented for agent use |
---
## 11. Open Items (Updated After Live Verification)
1. **GITEA_TOKEN in 1Password**: RESOLVED. Token exists at
`op://TerraphimPlatform/git.terraphim.cloud-admin-token/credential`.
Authenticated user is `root` (admin). Update SKILL.md to use this path.
2. **gitea-mcp installation**: The skill documents gitea-mcp setup but does not install it.
Installation is a separate task (requires Go 1.24+ or pre-compiled binary).
3. **Issue dependencies API**: RESOLVED. Works with `IssueMeta` body format:
`{"owner": "...", "repo": "...", "index": N}`. Supports cross-repo dependencies.
Update design helper functions to use correct format.
4. **Scoped labels**: RESOLVED. Mutual exclusivity confirmed. Using `exclusive: true`
on label creation + scope prefix (e.g., `status/`) enforces one-label-per-scope.
5. **Default tracking repo**: RESOLVED. Default is `terraphim/agent-tasks` via
`GITEA_OWNER=terraphim` and `GITEA_REPO=agent-tasks`. User can override both
env vars to point at any repo. The `agent-tasks` repo will be created during
setup if it doesn't exist.
---
## 12. Approval Checklist
Before proceeding to Phase 3 (Implementation), confirm:
- [ ] Architecture (milestones as projects, labels as workflow) is acceptable
- [ ] File change list is complete and correct
- [ ] Shell helper function signatures are acceptable
- [ ] Label scheme (12 labels, 3 categories) is acceptable
- [ ] Test strategy (10 integration tests, no mocks) is acceptable
- [ ] Implementation sequence (5 steps, ~5 hours) is reasonable
---
## Appendix A: Gitea 1.22.6 Milestone API Reference
```
POST /repos/{owner}/{repo}/milestones - Create milestone
GET /repos/{owner}/{repo}/milestones - List milestones
GET /repos/{owner}/{repo}/milestones/{id} - Get milestone
PATCH /repos/{owner}/{repo}/milestones/{id} - Update milestone
DELETE /repos/{owner}/{repo}/milestones/{id} - Delete milestone
```
Response fields: `id`, `title`, `description`, `state` (open/closed),
`open_issues`, `closed_issues`, `due_on`, `created_at`, `updated_at`.
## Appendix B: Gitea 1.22.6 Label API Reference
```
POST /repos/{owner}/{repo}/labels - Create label
GET /repos/{owner}/{repo}/labels - List labels
PATCH /repos/{owner}/{repo}/labels/{id} - Update label
DELETE /repos/{owner}/{repo}/labels/{id} - Delete label
POST /repos/{owner}/{repo}/issues/{index}/labels - Add labels to issue
PUT /repos/{owner}/{repo}/issues/{index}/labels - Replace issue labels
DELETE /repos/{owner}/{repo}/issues/{index}/labels - Clear issue labels
DELETE /repos/{owner}/{repo}/issues/{index}/labels/{id} - Remove label from issue
```
## Appendix C: br Workflow Mapping Reference
| br Concept | Gitea Mapping |
|------------|--------------|
| Bead | Issue |
| Bead status | Label (workflow:*) |
| Bead priority | Label (priority:*) |
| Bead type | Label (type:*) |
| Project/Sprint | Milestone |
| Assignment | Issue assignee |
| Dependencies | Issue dependencies API |
| Progress | Milestone open/closed ratio |
| Comments | Issue comments |
| Close | Issue state = closed + workflow:done label |
+469
View File
@@ -0,0 +1,469 @@
# Research Document: Gitea Skill for AI Agent Project/Task Management
**Status**: Draft -- Awaiting Approval
**Author**: Claude (Phase 1 Research)
**Date**: 2026-02-18
**Reviewers**: Alex
---
## 1. Problem Statement
### Description
Enhance the existing Gitea skill (`.agents/skills/gitea/SKILL.md`) so that an AI agent can perform end-to-end project and task management on the Gitea instance at https://git.terraphim.cloud (Gitea 1.22.6):
1. **Authenticate** -- Log in via API token (stored in 1Password)
2. **Create a project** -- Set up a project board for organizing work
3. **Create tasks** -- File issues within a repository and associate them with the project
4. **Track progress** -- Update issue state, add comments, move between workflow stages
### Success Criteria
- [ ] Agent can authenticate to Gitea API using a token retrieved from 1Password
- [ ] Agent can create a "project" (or equivalent organizational unit) to group tasks
- [ ] Agent can create issues (tasks) with title, body, labels, assignees, milestones
- [ ] Agent can update issue state (open/closed), add comments, change labels
- [ ] Agent can track workflow progress (backlog -> in-progress -> done or equivalent)
- [ ] Skill document is self-contained and usable by any AI agent without external docs
- [ ] Operations are idempotent where possible (re-running does not create duplicates)
---
## 2. Existing System Analysis
### 2.1 Current Gitea Skill (`/home/alex/projects/terraphim/gitea-infrastructure/.agents/skills/gitea/SKILL.md`)
The existing skill covers:
- **Users**: Admin CLI creation, API listing/info
- **Organizations**: Create, list repos
- **Repositories**: Create, delete, list (user and org)
- **Issues**: Create, list, get, update, close/reopen, add comments, add/remove labels
- **Pull Requests**: List, get, merge
- **Projects**: Create (user/org), list, add issue to project
- **Labels**: Create
- **Releases**: Create
- **Helper functions**: Bash alias for common operations
- **Error handling**: HTTP status codes, jq parsing
**Gaps in the current skill:**
1. No authentication via 1Password (`op inject` or `op read`)
2. No project column/board management (create columns, move issues between columns)
3. No milestone management (create, update, list, close)
4. No workflow patterns (agent-oriented: ready/claim/implement/close)
5. No idempotency patterns (check-before-create)
6. No JSON output parsing patterns for machine consumption
7. No issue template patterns (standardized issue bodies)
8. No dependency management between issues
### 2.2 Infrastructure Context (`/home/alex/projects/terraphim/gitea-infrastructure/HANDOVER.md`)
- **Instance**: Gitea 1.22.6 at https://git.terraphim.cloud
- **Server**: bigbox (100.106.66.7) via Tailscale
- **1Password Vault**: `TerraphimPlatform` (already has gitea-postgres, gitea-s3)
- **Secrets pattern**: `op inject` with `op://TerraphimPlatform/...` references
- **Source auth**: `source ~/op_zesticai_non_prod.sh` sets `OP_SERVICE_ACCOUNT_TOKEN`
### 2.3 Reference Patterns from Terraphim Ecosystem
**br (beads_rust) pattern:**
- CLI issue tracking: `br ready`, `br create`, `br update`, `br close`, `br sync`
- Priorities P0-P4, types (bug, feature, task, epic, chore)
- Agent workflow: ready -> claim -> implement -> close -> sync
- `--json` flag for machine parsing
**bv (beads viewer) pattern:**
- Robot flags: `--robot-triage`, `--robot-next`, `--robot-plan`
- Dependency-aware scheduling, PageRank, critical path
- Graph-aware triage engine
**MCP Agent Mail pattern:**
- Multi-agent coordination via messaging
- Projects, identities, inbox/outbox
- File reservations to avoid conflicts
---
## 3. Critical Finding: Gitea Project Board API Status
### 3.1 Project Board API is NOT Available in Gitea 1.22.6
This is the single most important finding of this research.
**Evidence:**
- GitHub Issue [#14299](https://github.com/go-gitea/gitea/issues/14299) "[FEATURE] API for projects" -- opened Jan 2021, still **OPEN** as of Feb 2026, assigned to milestone **1.26.0**
- PR [#28111](https://github.com/go-gitea/gitea/pull/28111) adding project API endpoints -- still in **DRAFT** status, targeted for 1.26.0
- GitHub Issue [#31769](https://github.com/go-gitea/gitea/issues/31769) "API support for columns" -- opened Aug 2024, still **OPEN**, type/proposal
**Proposed but NOT yet merged endpoints from PR #28111:**
```
POST /user/projects
POST /orgs/{org}/projects
POST /repos/{owner}/{repo}/projects
GET /user/projects
GET /orgs/{org}/projects
GET /repos/{owner}/{repo}/projects
GET /projects/{id}
PATCH /projects/{id}
DELETE /projects/{id}
```
**Column management endpoints from Issue #31769 (proposed, NOT implemented):**
```
PATCH /projects/{project_id}/columns/move
PATCH /projects/{project_id}/columns/{column_id}/move
```
**VERIFIED 2026-02-18**: Tested against live instance at https://git.terraphim.cloud:
- `GET /api/v1/user/projects` returns **HTTP 404** ("404 page not found")
- `GET /api/v1/repos/terraphim/gitea-infrastructure/projects` returns **HTTP 404**
- The existing skill's "Projects" section (lines 222-263 of SKILL.md) documents endpoints that **do not work** on Gitea 1.22.6 and must be removed or replaced.
### 3.2 What IS Available in Gitea 1.22.6 API
The following endpoints ARE confirmed available and functional:
**Issues (full CRUD):**
```
POST /repos/{owner}/{repo}/issues -- Create issue
GET /repos/{owner}/{repo}/issues -- List issues
GET /repos/{owner}/{repo}/issues/{index} -- Get issue
PATCH /repos/{owner}/{repo}/issues/{index} -- Update issue (title, body, state, milestone, assignees)
POST /repos/{owner}/{repo}/issues/{index}/comments -- Add comment
POST /repos/{owner}/{repo}/issues/{index}/labels -- Add labels
DELETE /repos/{owner}/{repo}/issues/{index}/labels/{id} -- Remove label
```
**Labels (full CRUD):**
```
POST /repos/{owner}/{repo}/labels -- Create label
GET /repos/{owner}/{repo}/labels -- List labels
PATCH /repos/{owner}/{repo}/labels/{id} -- Update label
DELETE /repos/{owner}/{repo}/labels/{id} -- Delete label
```
**Milestones (full CRUD):**
```
POST /repos/{owner}/{repo}/milestones -- Create milestone
GET /repos/{owner}/{repo}/milestones -- List milestones
GET /repos/{owner}/{repo}/milestones/{id} -- Get milestone
PATCH /repos/{owner}/{repo}/milestones/{id} -- Update milestone
DELETE /repos/{owner}/{repo}/milestones/{id} -- Delete milestone
```
**API Token Management:**
```
POST /users/{username}/tokens -- Create token (requires BasicAuth, NOT token auth)
GET /users/{username}/tokens -- List tokens (requires BasicAuth)
DELETE /users/{username}/tokens/{id} -- Delete token (requires BasicAuth)
```
**Note on token creation**: The `/users/{username}/tokens` endpoint requires HTTP BasicAuth with username:password. You **cannot** create a new token using an existing token -- this is a Gitea security restriction.
### 3.3 Existing MCP Servers for Gitea
Two MCP servers exist that could complement or replace the curl-based skill:
**1. Official Gitea MCP Server** ([gitea.com/gitea/gitea-mcp](https://gitea.com/gitea/gitea-mcp))
- ~80+ tools covering repos, branches, issues, PRs, releases, wiki, actions, tags, labels
- **Does NOT support project boards or columns**
- **Does NOT support milestones** (except as a field when editing PRs)
- Supports stdio and SSE modes
- Config: `GITEA_HOST`, `GITEA_ACCESS_TOKEN`, `GITEA_INSECURE`
- Written in Go, MIT licensed
**2. forgejo-mcp** ([github.com/raohwork/forgejo-mcp](https://github.com/raohwork/forgejo-mcp))
- Supports issues, labels, milestones, comments, attachments, dependencies
- **Does NOT support project boards or columns**
- **Does support milestone CRUD** (create, edit, delete)
- Supports stdio and HTTP modes
- Config: `FORGEJOMCP_SERVER`, `FORGEJOMCP_TOKEN`
- Written in Go, MPL-2.0 licensed
**3. Tea CLI** ([gitea.com/gitea/tea](https://gitea.com/gitea/tea))
- Official command-line tool for Gitea
- Supports issues, milestones, labels, PRs, time tracking, notifications
- Milestone issue management: add/remove issues from milestones
- **Does NOT mention project board support**
---
## 4. Recommended Architecture: Milestones as Projects
### 4.1 Rationale
Since the Project Board API is not available in Gitea 1.22.6, we need an alternative. The best available option is to use **milestones** as the primary organizational unit (i.e., "project" equivalent), combined with **labels** for workflow state tracking.
| Concept | br/bv equivalent | Gitea Implementation |
|---------|-------------------|---------------------|
| Project | br project / bv graph | Milestone |
| Task | br bead / issue | Issue |
| Status | br state (ready/claimed/done) | Labels: `status/backlog`, `status/in-progress`, `status/done` |
| Priority | br P0-P4 | Labels: `priority/P0-critical`, `priority/P1-high`, `priority/P2-medium`, `priority/P3-low` |
| Type | br type (bug/feature/task) | Labels: `type/bug`, `type/feature`, `type/task`, `type/epic`, `type/chore` |
| Agent claim | br claim | Assignee field + `status/in-progress` label |
| Workflow column | Project board column | Scoped labels (`status/*`) |
### 4.2 Scoped Labels for Workflow State
Gitea supports **scoped labels** (format: `scope/name`). When a scoped label is applied, it automatically removes any other label with the same scope. This means:
- Applying `status/in-progress` automatically removes `status/backlog`
- Applying `priority/P0-critical` automatically removes `priority/P2-medium`
This provides kanban-like exclusivity without project board columns.
### 4.3 Agent Workflow
```
1. AUTHENTICATE
- Read token from 1Password: op read "op://TerraphimPlatform/gitea-api-token/credential"
- Export: GITEA_TOKEN=$(op read ...)
2. CREATE PROJECT (milestone)
- POST /repos/{owner}/{repo}/milestones
- Body: { "title": "Sprint 2026-W08", "description": "...", "due_on": "2026-02-28T00:00:00Z" }
3. SETUP LABELS (one-time per repo)
- Create scoped labels for status, priority, type
- Idempotent: check existing labels before creating
4. CREATE TASK (issue)
- POST /repos/{owner}/{repo}/issues
- Body: { "title": "...", "body": "...", "milestone": <milestone_id>, "labels": [<label_ids>], "assignees": [...] }
5. TRACK PROGRESS
- Change status: Replace labels (POST label, DELETE old label -- or use scoped labels)
- Add comment: POST /repos/{owner}/{repo}/issues/{index}/comments
- Close: PATCH /repos/{owner}/{repo}/issues/{index} with { "state": "closed" }
6. QUERY STATUS
- List by milestone: GET /repos/{owner}/{repo}/issues?milestone={name}&state=open
- List by label: GET /repos/{owner}/{repo}/issues?labels=status/in-progress
- Get milestone progress: GET /repos/{owner}/{repo}/milestones/{id}
(returns open_issues and closed_issues counts)
```
---
## 5. Authentication Strategy
### 5.1 1Password Integration
The existing infrastructure already uses 1Password (`TerraphimPlatform` vault) for secrets. The pattern should be:
```bash
# Store token in 1Password (one-time setup, done manually or via op CLI)
# Item name: gitea-api-token
# Field: credential (contains the token value)
# Agent retrieval at runtime:
export GITEA_TOKEN=$(op read "op://TerraphimPlatform/gitea-api-token/credential")
```
**Note**: Creating a Gitea API token programmatically requires BasicAuth (username + password), which is harder to automate securely. The recommended approach is:
1. Create the token manually via Gitea Web UI (Settings -> Applications -> Generate New Token)
2. Store the token in 1Password under `TerraphimPlatform/gitea-api-token`
3. Agent reads from 1Password at runtime using `op read`
### 5.2 Token Scopes Required
The agent needs the following scopes:
- `read:issue` + `write:issue` -- Create and update issues
- `read:repository` + `write:repository` -- Access repo metadata
- `read:user` -- Read user information for assignees
- `read:organization` -- Access org repos
- `write:misc` -- Needed for some label operations
Alternatively, use `all` scope for simplicity (less secure but simpler).
---
## 6. Constraints and Risks
### 6.1 Technical Constraints
| Constraint | Impact | Mitigation |
|------------|--------|------------|
| No Project Board API in 1.22.6 | Cannot use true kanban boards via API | Use milestones + scoped labels as alternative |
| Token creation requires BasicAuth | Cannot automate token creation with token auth | Manual token creation, store in 1Password |
| Gitea MCP server lacks milestone support | Cannot use MCP for full workflow | Use curl-based skill for now; MCP for repo/PR ops |
| Scoped labels require Gitea 1.20+ | Must verify instance supports scoped labels | VERIFIED: Gitea 1.22.6 supports scoped labels with mutual exclusivity |
| Issue dependency API body format differs from intuition | Must use IssueMeta format {owner, repo, index} | VERIFIED: Works with correct format, supports cross-repo deps |
### 6.2 Risks
| Risk | Likelihood | Impact | Mitigation |
|------|------------|--------|------------|
| Existing "Projects" endpoints in SKILL.md do not work | High | Skill provides wrong info | Verify against live instance; remove or caveat |
| Milestone-as-project is semantically confusing | Medium | Agent confusion | Clear naming conventions and docs |
| Label sprawl across repos | Medium | Maintenance burden | Standardized label set, setup automation |
| Token leaked in logs/output | Low | Security breach | Never echo token; use 1Password op read inline |
| Gitea upgrade to 1.26 changes API surface | Low | Skill needs update | Document version, plan for upgrade path |
### 6.3 Assumptions
| Assumption | Basis | Risk if Wrong |
|------------|-------|---------------|
| Gitea 1.22.6 supports scoped labels | Feature added in 1.20 | Fall back to manual label management |
| Milestone API is fully functional | Standard Gitea feature | Skill cannot create "projects" |
| 1Password `op read` available in agent env | Existing infra pattern | Agent cannot authenticate |
| Issues can be filtered by milestone name | API docs indicate this | Need milestone ID lookup step |
| Agent runs in environment with curl and jq | Standard tooling | Need alternative HTTP client |
---
## 7. Open Questions -- ANSWERED via Live Testing (2026-02-18)
### Q1: Do the existing project endpoints work on 1.22.6?
**ANSWER: NO.** Both `/api/v1/user/projects` and `/api/v1/repos/{owner}/{repo}/projects` return HTTP 404. Milestones-only approach confirmed.
### Q2: Is there an existing Gitea API token in 1Password?
**ANSWER: YES.** The admin token is at `op://TerraphimPlatform/git.terraphim.cloud-admin-token/credential`. Authenticated user is `root` (id=1, is_admin=true). Existing 1Password items:
- `git.terraphim.cloud-admin-token` -- admin API token (working)
- `gitea-postgres` -- database credentials
- `gitea-s3` -- S3 storage credentials
- `Gitea.Terraphim.io` -- legacy item (2 years old)
### Q3: Which repository should be the "default" for agent task tracking?
**TO DECIDE.** Available repos on instance:
- `terraphim/terraphim-ai`
- `terraphim/terraphim-skills`
- Orgs: `terraphim`, `zestic-ai`, `private`
### Q4: Do scoped labels work as expected on 1.22.6?
**ANSWER: YES.** Verified with live test:
- Created `status/backlog` (exclusive=true), `status/in-progress` (exclusive=true), `status/done` (exclusive=true)
- Applied `status/in-progress` via PUT (replace) -- only `status/in-progress` remained
- Then applied `status/backlog` via POST (add) -- `status/in-progress` was **automatically removed**, only `status/backlog` remained
- Scoped label mutual exclusivity is enforced by Gitea on both POST and PUT
### Q5: Do issue dependencies work?
**ANSWER: YES**, but the body format is `IssueMeta` (not `depends_on_id`):
```json
POST /repos/{owner}/{repo}/issues/{index}/dependencies
Body: {"owner": "root", "repo": "skill-test-temp", "index": 2}
```
- `GET .../dependencies` returns the list of issues that block this one
- `GET .../blocks` returns the list of issues this one blocks
- Cross-repo dependencies are supported (owner/repo fields)
### Q6: Do milestones work as project containers?
**ANSWER: YES.** Full CRUD verified:
- Create milestone with title, description, due_on -- returns id, state, open/closed counts
- Issues created with `"milestone": <id>` are linked to the milestone
- Progress tracking works: `open_issues` and `closed_issues` update automatically when issues are opened/closed
- Filter issues by milestone name: `?milestones=Sprint%202026-W08`
- Filter issues by label: `?labels=status/backlog`
### Q7: Does time tracking work?
**ANSWER: YES.** Stopwatch start/stop returns HTTP 201. Tracked times accessible via `GET .../times`.
### Q3: Which repository should be the "default" for agent task tracking?
**ANSWER: `terraphim/agent-tasks`** (user decision 2026-02-18). Configurable via `GITEA_OWNER` and `GITEA_REPO` env vars. Default repo created during setup if it doesn't exist. All open questions resolved.
---
## 8. Recommended Next Steps
### If Approved, Phase 2 (Design) Should:
1. **Verify live API behavior** -- Test project, milestone, and scoped label endpoints against https://git.terraphim.cloud
2. **Design the enhanced SKILL.md** with these sections:
- Authentication (1Password + op read)
- Project Management (milestones as projects)
- Task Management (issues with scoped labels)
- Workflow Operations (agent lifecycle: create -> claim -> update -> close)
- Label Setup (standardized scoped labels for status, priority, type)
- Query Patterns (list by milestone, by label, by state)
- Idempotency Patterns (check-before-create)
- JSON Output Parsing (jq patterns for machine consumption)
3. **Create a label initialization script** that sets up the standard label set in a repository
4. **Document the 1Password setup** for the Gitea API token
5. **Decide on MCP integration** -- whether to recommend gitea-mcp or forgejo-mcp alongside the curl skill
### Scope Recommendation
**Minimal Viable Skill (Phase 2 target):**
- 1Password authentication
- Milestone CRUD (as project proxy)
- Issue CRUD with labels and milestone assignment
- Scoped label workflow (status/backlog -> status/in-progress -> status/done)
- Comment-based progress tracking
- Query by milestone and label filters
**Future Enhancement (Phase 3+, when Gitea 1.26 ships):**
- True project board API integration
- Column management
- Issue-to-project linking
- MCP server integration
---
## 9. Appendix
### A. File Inventory
| File | Path | Relevance |
|------|------|-----------|
| Current skill | `/home/alex/projects/terraphim/gitea-infrastructure/.agents/skills/gitea/SKILL.md` | Primary file to enhance |
| Handover doc | `/home/alex/projects/terraphim/gitea-infrastructure/HANDOVER.md` | Infrastructure context |
| Docker compose template | `/home/alex/projects/terraphim/gitea-infrastructure/docker-compose.yml.template` | 1Password patterns |
| Repository setup | `/home/alex/projects/terraphim/gitea-infrastructure/REPOSITORY-SETUP.md` | Deployment patterns |
| Prior research | `/home/alex/projects/terraphim/gitea-infrastructure/.docs/RESEARCH-gitea-bigbox-deployment.md` | Infrastructure research |
### B. External References
- Gitea API docs: https://docs.gitea.com/api/1.22/
- Gitea Project API feature request: https://github.com/go-gitea/gitea/issues/14299
- Gitea Column API proposal: https://github.com/go-gitea/gitea/issues/31769
- Gitea Project API draft PR: https://github.com/go-gitea/gitea/pull/28111
- Official Gitea MCP server: https://gitea.com/gitea/gitea-mcp
- forgejo-mcp: https://github.com/raohwork/forgejo-mcp
- Tea CLI: https://gitea.com/gitea/tea
- Gitea scoped labels blog: https://blog.gitea.com/introducing-new-features-of-labels-and-projects/
### C. Gitea MCP Server Tool Inventory (for reference)
The official gitea-mcp provides ~80 tools:
- **User**: get_my_user_info, get_user_orgs, search_users
- **Repos**: create_repo, fork_repo, list_my_repos, search_repos
- **Branches**: create_branch, delete_branch, list_branches
- **Tags**: create_tag, delete_tag, get_tag, list_tags
- **Releases**: create_release, delete_release, get_release, get_latest_release, list_releases
- **Files**: get_file_content, get_dir_content, create_file, update_file, delete_file
- **Commits**: list_repo_commits
- **Issues**: get_issue_by_index, list_repo_issues, create_issue, create_issue_comment, edit_issue, edit_issue_comment, get_issue_comments_by_index
- **PRs**: get/list/create/merge pull requests, reviewer management, review CRUD
- **Org labels**: list/create/edit/delete org labels
- **Actions/CI**: workflow, run, job, secret, variable management (~25 tools)
- **Wiki**: list/get/create/update/delete wiki pages
**Not covered by gitea-mcp**: milestones, project boards, repo labels (only org labels), issue labels, issue assignees, issue deadlines
### D. forgejo-mcp Tool Inventory (for reference)
forgejo-mcp provides:
- Issues: create, edit, view, labels (add/remove/replace), comments, attachments, dependencies
- Milestones: create, edit, delete, progress reporting
- Labels: create, edit, delete
- Repos: search, list
- Releases: manage, attachments
- PRs: view
- Wiki: manage
- Actions: view tasks
**Key advantage over gitea-mcp**: Full milestone CRUD support, issue dependency management, issue label management.
+45
View File
@@ -0,0 +1,45 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
# Adapted from terraphim-ai pre-commit config for infrastructure project
default_language_version:
python: python3.12
repos:
# General code quality hooks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
name: Trim trailing whitespace
- id: end-of-file-fixer
name: Fix end of files
- id: check-yaml
name: Check YAML syntax
- id: check-json
name: Check JSON syntax
- id: check-case-conflict
name: Check for case conflicts
- id: check-merge-conflict
name: Check for merge conflicts
- id: detect-private-key
name: Detect private keys
- id: check-added-large-files
name: Check for large files
args: ['--maxkb=1000']
# Secret detection
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
name: Detect secrets
args: ['--baseline', '.secrets.baseline']
exclude: .*\.template$|.*\.sample$
description: "Detect secrets in staged code"
# Global exclusions
exclude: |
(?x)(
^\.cachebro/.*
)
+172
View File
@@ -0,0 +1,172 @@
{
"version": "1.5.0",
"plugins_used": [
{
"name": "ArtifactoryDetector"
},
{
"name": "AWSKeyDetector"
},
{
"name": "AzureStorageKeyDetector"
},
{
"name": "Base64HighEntropyString",
"limit": 4.5
},
{
"name": "BasicAuthDetector"
},
{
"name": "CloudantDetector"
},
{
"name": "DiscordBotTokenDetector"
},
{
"name": "GitHubTokenDetector"
},
{
"name": "GitLabTokenDetector"
},
{
"name": "HexHighEntropyString",
"limit": 3.0
},
{
"name": "IbmCloudIamDetector"
},
{
"name": "IbmCosHmacDetector"
},
{
"name": "IPPublicDetector"
},
{
"name": "JwtTokenDetector"
},
{
"name": "KeywordDetector",
"keyword_exclude": ""
},
{
"name": "MailchimpDetector"
},
{
"name": "NpmDetector"
},
{
"name": "OpenAIDetector"
},
{
"name": "PrivateKeyDetector"
},
{
"name": "PypiTokenDetector"
},
{
"name": "SendGridDetector"
},
{
"name": "SlackDetector"
},
{
"name": "SoftlayerDetector"
},
{
"name": "SquareOAuthDetector"
},
{
"name": "StripeDetector"
},
{
"name": "TelegramBotTokenDetector"
},
{
"name": "TwilioKeyDetector"
}
],
"filters_used": [
{
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
},
{
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
"min_level": 2
},
{
"path": "detect_secrets.filters.heuristic.is_indirect_reference"
},
{
"path": "detect_secrets.filters.heuristic.is_likely_id_string"
},
{
"path": "detect_secrets.filters.heuristic.is_lock_file"
},
{
"path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
},
{
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
},
{
"path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
},
{
"path": "detect_secrets.filters.heuristic.is_sequential_string"
},
{
"path": "detect_secrets.filters.heuristic.is_swagger_file"
},
{
"path": "detect_secrets.filters.heuristic.is_templated_secret"
},
{
"path": "detect_secrets.filters.regex.should_exclude_file",
"pattern": [
"\\.cachebro/.*",
".*\\.template$",
".*\\.sample$"
]
}
],
"results": {
".docs/IMPLEMENTATION-gitea-bigbox-deployment.md": [
{
"type": "Secret Keyword",
"filename": ".docs/IMPLEMENTATION-gitea-bigbox-deployment.md",
"hashed_secret": "ebb78e1b3d8c84440d663d08edd0d0db46d8b3c3",
"is_verified": false,
"line_number": 424
}
],
"ARTICLE-gitea-deployment.md": [
{
"type": "Secret Keyword",
"filename": "ARTICLE-gitea-deployment.md",
"hashed_secret": "850b05c66deaef000492c33b0e9b582d9baca87a",
"is_verified": false,
"line_number": 131
}
],
"HANDOVER.md": [
{
"type": "Secret Keyword",
"filename": "HANDOVER.md",
"hashed_secret": "f2c57870308dc87f432e5912d4de6f8e322721ba",
"is_verified": false,
"line_number": 165
}
],
"docker-compose_kitchen_sink.yml": [
{
"type": "Secret Keyword",
"filename": "docker-compose_kitchen_sink.yml",
"hashed_secret": "5d2aec19b41f147a20ab309517816cc5222e5e1c",
"is_verified": false,
"line_number": 124
}
]
},
"generated_at": "2026-02-18T10:47:29Z"
}