From 5854961c1f51300ff3db0c230704f2d31b7c7d83 Mon Sep 17 00:00:00 2001 From: Defame1297 Date: Sun, 5 Jul 2026 10:35:12 +0000 Subject: [PATCH] feat(gitea): add gitea-branches skill (branches + commits) Adds plugins/gitea/skills/gitea-branches/ per ADR 0011, covering list_branches/create_branch/delete_branch (migrated from the flat plugins/bin/skills/gitea/ dispatch) plus list_commits/get_commit (new read-only commit-history domain). Call signatures were re-verified live via ToolSearch against the deployed gitea-mcp server rather than copied from api-reference.md, per issue #6 comment #849's root-cause fix. Bumps the gitea plugin to 1.1.0 in both manifests for the new skill. --- plugins/gitea/.claude-plugin/plugin.json | 5 +- plugins/gitea/plugin.json | 5 +- plugins/gitea/skills/gitea-branches/README.md | 35 +++++++++ plugins/gitea/skills/gitea-branches/SKILL.md | 65 ++++++++++++++++ .../gitea-branches/references/branches.md | 78 +++++++++++++++++++ .../gitea-branches/references/commits.md | 67 ++++++++++++++++ .../gitea-branches/references/sources.md | 25 ++++++ 7 files changed, 276 insertions(+), 4 deletions(-) create mode 100644 plugins/gitea/skills/gitea-branches/README.md create mode 100644 plugins/gitea/skills/gitea-branches/SKILL.md create mode 100644 plugins/gitea/skills/gitea-branches/references/branches.md create mode 100644 plugins/gitea/skills/gitea-branches/references/commits.md create mode 100644 plugins/gitea/skills/gitea-branches/references/sources.md diff --git a/plugins/gitea/.claude-plugin/plugin.json b/plugins/gitea/.claude-plugin/plugin.json index 68b602c..ff240af 100644 --- a/plugins/gitea/.claude-plugin/plugin.json +++ b/plugins/gitea/.claude-plugin/plugin.json @@ -10,9 +10,10 @@ "issues", "prs", "milestones", - "releases" + "releases", + "branches" ], "license": "MIT", "name": "gitea", - "version": "1.0.0" + "version": "1.1.0" } diff --git a/plugins/gitea/plugin.json b/plugins/gitea/plugin.json index c86abc8..3c4a6aa 100644 --- a/plugins/gitea/plugin.json +++ b/plugins/gitea/plugin.json @@ -11,7 +11,8 @@ "issues", "prs", "milestones", - "releases" + "releases", + "branches" ], "license": "MIT", "mcpServers": ".mcp.json", @@ -19,5 +20,5 @@ "skills": [ "skills/" ], - "version": "1.0.0" + "version": "1.1.0" } diff --git a/plugins/gitea/skills/gitea-branches/README.md b/plugins/gitea/skills/gitea-branches/README.md new file mode 100644 index 0000000..c84e765 --- /dev/null +++ b/plugins/gitea/skills/gitea-branches/README.md @@ -0,0 +1,35 @@ +# gitea-branches + +Manage Gitea repository branches and inspect commit history via the Gitea MCP server. + +## What it does + +This skill handles branch lifecycle operations (list, create, delete) and read-only commit +history (list commits, get a single commit's full detail) against a Gitea repository. It resolves +`owner`/`repo` from the git remote, dispatches to the right MCP tool, and applies safety and +pagination conventions specific to Gitea's API (e.g. refusing to delete a protected branch without +explicit confirmation, and treating unexpected 404s as possible masked 403s). + +## Before you start + +Requires a Gitea MCP server configured with a token. `list_branches`, `list_commits`, and +`get_commit` work with `write:issue` alone; `create_branch` and `delete_branch` need +`write:repository`. Requires a git remote named `origin` pointing at the Gitea instance. + +## Usage + +``` +/gitea-branches +``` + +Describe your task: list/create/delete a branch, or list/inspect commits. See `SKILL.md`'s +dispatch table for the full set of recognized invocations. + +## Files + +| File | Purpose | +|------|---------| +| `SKILL.md` | Skill instructions for agents — dispatch table, gotchas | +| `references/branches.md` | Verified call signatures and mechanics for list/create/delete branch | +| `references/commits.md` | Verified call signatures and mechanics for list/get commit | +| `references/sources.md` | Research sources backing the branch/commit guidance | diff --git a/plugins/gitea/skills/gitea-branches/SKILL.md b/plugins/gitea/skills/gitea-branches/SKILL.md new file mode 100644 index 0000000..9c355f4 --- /dev/null +++ b/plugins/gitea/skills/gitea-branches/SKILL.md @@ -0,0 +1,65 @@ +--- +name: gitea-branches + +description: > + Use when managing Gitea repository branches — listing, creating, or deleting + branches — or inspecting commit history within a Gitea repo: listing commits + (optionally filtered by branch or file path) or getting full detail for a + single commit by SHA. Triggers on "list branches", "create a branch", + "delete a branch", "what commits are on this branch", "show commit ", + "what changed in that commit" — even if the user doesn't say "Gitea" + explicitly, as long as the repo's remote is a Gitea instance. Do not use for + local git branch/commit operations on your working copy (use git-branches or + git-history) or for PR-side branch references like cross-repo fork PR heads + (use gitea-prs). + +compatibility: Requires Gitea MCP server configured with a token; list_branches, list_commits, and get_commit work with write:issue alone, create_branch and delete_branch require write:repository. Requires git remote "origin" pointing to the Gitea instance. + +metadata: + category: integration + version: "0.1.0" + source_keys: + - gitea-mcp-repo + - gitea-mcp-slim-go + +allowed-tools: Bash mcp__gitea__list_branches mcp__gitea__create_branch mcp__gitea__delete_branch mcp__gitea__list_commits mcp__gitea__get_commit +--- + +## Gotchas + +- **Never delete a protected branch (`main`/`master` by name, or `protected: true` from `list_branches`) without explicit confirmation.** `delete_branch` is a direct API call, not a local `git push` — there is no client-side force-push guard protecting it. Name-matching `main`/`master` is a convenient default but not authoritative — a repo can protect a differently-named default branch. When in doubt, call `list_branches` first and check `protected` on the target; treat deletion of any protected branch as a hard refusal unless the user explicitly confirms in the conversation. +- **404 may actually mean 403.** Gitea hides permission errors as not-found to avoid leaking resource existence. If any of these five tools returns 404 unexpectedly, check token scope (see `references/branches.md` / `references/commits.md`) before concluding the branch or commit doesn't exist. +- **Pagination is manual.** `list_branches` and `list_commits` return one page at a time — no auto-pagination in the MCP layer. When you need a complete list, iterate `page: 1, 2, ...` until the returned count is less than `per_page`. +- **Owner/repo always come from the git remote, never from `get_me`.** Resolve them via `git remote get-url origin` (Step 1 below). `get_me`/`list_my_repos` are blocked under the token scopes this skill assumes. +- **`create_branch`'s source is `old_branch`, not "wherever gitea-mcp feels like."** Omitting `old_branch` forks from the repo's server-side default branch — not necessarily the branch you're currently working on locally. If you want to branch from your current checkout, pass `old_branch` explicitly. + +## Step 1 — Resolve owner and repo + +Before any tool call, extract `owner` and `repo` from the git remote: + +```bash +git remote get-url origin +``` + +If origin is not set or the URL is not a Gitea URL, stop and report: "No Gitea remote found — set origin to your Gitea instance URL." + +## Step 2 — Dispatch + +| Invocation | Action | +|---|---| +| `/gitea-branches` or `/gitea-branches list` | List branches | +| `/gitea-branches create [from ]` | Create branch | +| `/gitea-branches delete ` | Delete branch | +| `/gitea-branches commits [on ] [touching ]` | List commit history | +| `/gitea-branches commit ` | Get full detail for one commit | + +For branch operations (list/create/delete), read `references/branches.md`. +For commit operations (list/get), read `references/commits.md`. + +## Step 3 — Report + +For reads: display branches as name + protected flag; display commits as SHA (short), message summary, author, date. + +For writes (create/delete): confirm the action taken, the branch name, and (for create) the base it forked from. + +For errors: surface the HTTP code and message. If a 404 is unexpected, re-check token scope per the Gotchas above before reporting "not found" to the user. diff --git a/plugins/gitea/skills/gitea-branches/references/branches.md b/plugins/gitea/skills/gitea-branches/references/branches.md new file mode 100644 index 0000000..1c995b3 --- /dev/null +++ b/plugins/gitea/skills/gitea-branches/references/branches.md @@ -0,0 +1,78 @@ +--- +topic: branches +source_keys: + - gitea-mcp-repo + - gitea-mcp-slim-go +--- + +# Branch operations + +Call signatures below were verified live against the deployed `gitea-mcp` server via `ToolSearch` +at authoring time, not copied from research docs — this is deliberate: research docs are generated +from source code at a point in time and can drift from the server actually deployed. Re-verify +against the live schema if these tools appear to behave differently than documented here. + +## `list_branches` + +**Parameters:** +- `owner` (string, required) +- `repo` (string, required) +- `page` (number, optional, default: `1`) +- `per_page` (number, optional, default: `30`) + +**Call:** +``` +list_branches owner: repo: +``` + +**Response:** one object per branch: `name`, `protected` (bool), `commit_sha` (present when the +underlying commit data is available). + +Paginate if you need the full list (see Gotchas in SKILL.md) — iterate `page` until the returned +count is less than `per_page`. + +## `create_branch` + +**Parameters:** +- `owner` (string, required) +- `repo` (string, required) +- `branch` (string, required) — new branch name +- `old_branch` (string, optional) — source branch; if omitted, defaults to the repo's default + branch server-side (not necessarily your current local checkout) + +**Call:** +``` +create_branch owner: repo: branch: old_branch: +``` + +Default dispatch: if the user gives a base ("branch off of X", "from X"), pass it as `old_branch`. +If they don't specify a base and you're mid-task on a local branch, pass your current branch +(`git branch --show-current`) as `old_branch` so the new branch forks from where you're actually +working, rather than silently falling back to the repo default. If neither applies (e.g. a fresh +top-level request with no working branch context), omit `old_branch` and let it default server-side. + +A branch name collision returns `409 Conflict`. + +## `delete_branch` + +**Parameters:** +- `owner` (string, required) +- `repo` (string, required) +- `branch` (string, required) + +**Call:** +``` +delete_branch owner: repo: branch: +``` + +Before calling this, see the hard-refusal Gotcha in SKILL.md. If the target branch's name isn't +obviously a scratch/feature branch, call `list_branches` first and check `protected` on the +matching entry — name-matching `main`/`master` alone isn't authoritative, since a repo can protect +a differently-named default branch. Confirm explicitly with the user before deleting anything +protected, every time, regardless of how the request is phrased. + +## Token scope + +`list_branches` works with `write:issue` alone. `create_branch` and `delete_branch` need +`write:repository`. All three are verified working empirically under a token with both scopes +(`write:issue` + `write:repository`). diff --git a/plugins/gitea/skills/gitea-branches/references/commits.md b/plugins/gitea/skills/gitea-branches/references/commits.md new file mode 100644 index 0000000..b63d426 --- /dev/null +++ b/plugins/gitea/skills/gitea-branches/references/commits.md @@ -0,0 +1,67 @@ +--- +topic: commits +source_keys: + - gitea-mcp-repo + - gitea-mcp-slim-go +--- + +# Commit operations + +Read-only commit history, scoped to a repo (optionally to one branch or one path). Call signatures +below were verified live against the deployed `gitea-mcp` server via `ToolSearch` at authoring time, +not copied from research docs, for the same drift-avoidance reason noted in `references/branches.md`. + +This domain has no prior skill precedent — it's new coverage added alongside branches because commit +history is naturally scoped to a branch (a "what happened on this branch" question), not because it +shares any tool family with branch create/delete. + +## `list_commits` + +**Parameters:** +- `owner` (string, required) +- `repo` (string, required) +- `sha` (string, optional) — starting SHA or branch name; if omitted, gitea-mcp uses the repo's + default branch +- `path` (string, optional) — restrict results to commits that touched this file/path +- `page` (number, optional, default: `1`, minimum: `1`) +- `per_page` (number, optional, default: `30`, minimum: `1`) + +**Call:** +``` +list_commits owner: repo: sha: path: +``` + +Dispatch defaults: +- "commits on ``" → pass `` as `sha`. +- "commits touching ``" (no branch mentioned) → pass `path` alone, `sha` omitted (defaults to + the repo's default branch). +- Both given → pass both; the result is history for that path, walked from that branch/SHA. +- Neither given → omit both; this returns default-branch history, which is a reasonable default for + an open-ended "what's the recent history here" question. + +**Response:** one object per commit: `sha`, `html_url`, `created`, `message` (when available), +`author` (`{name, email, date}`, when available). + +Paginate per the manual-pagination Gotcha in SKILL.md if you need more than one page of history. + +## `get_commit` + +**Parameters:** +- `owner` (string, required) +- `repo` (string, required) +- `sha` (string, required) + +**Call:** +``` +get_commit owner: repo: sha: +``` + +**Response:** same shape as a `list_commits` entry, but always fully populated (`message` and +`author` are guaranteed present, not conditional). Use this when the user asks about one specific +commit by SHA rather than browsing history — `list_commits` entries may omit `message`/`author` in +edge cases, `get_commit` will not. + +## Token scope + +Both tools are read-only and work with `write:issue` alone (no `write:repository` needed), verified +empirically against the deployed server. diff --git a/plugins/gitea/skills/gitea-branches/references/sources.md b/plugins/gitea/skills/gitea-branches/references/sources.md new file mode 100644 index 0000000..fe08c52 --- /dev/null +++ b/plugins/gitea/skills/gitea-branches/references/sources.md @@ -0,0 +1,25 @@ +# Sources + +**Note on call signatures:** per `docs/adr/0011-gitea-skill-deep-modules.md`, the tool parameter +signatures in `references/branches.md` and `references/commits.md` were re-verified live via +`ToolSearch` against the deployed `gitea-mcp` server at authoring time — they are not copied +verbatim from `api-reference.md` below. This resolves issue #6 comment #849's root-cause finding +that a prior skill was authored from API docs that had drifted from the actual MCP tool schema. +The research docs cited here informed gotchas, response shapes, and workflow context, not the +parameter lists themselves. + +## gitea-mcp-repo + +- **URL:** https://gitea.com/gitea/gitea-mcp +- **Description:** Official gitea-mcp repository (v1.3.0); operation/*.go source files documenting all 55 MCP tools, their parameters, and CLI flags. Informed the dispatch table and pagination / 404-may-mean-403 gotchas in SKILL.md, and the list/create/delete branch and list/get commit mechanics (including 409 conflict and default-branch fallback behavior) in references/branches.md and references/commits.md. +- **Research doc:** plugins/gitea/docs/research/docs/gitea/sources.md +- **Contributing files:** SKILL.md, references/branches.md, references/commits.md +- **Status:** `extracted` + +## gitea-mcp-slim-go + +- **URL:** https://gitea.com/gitea/gitea-mcp/raw/branch/main/operation/repo/slim.go +- **Description:** Slim response shape structs from gitea-mcp source; defines exactly which fields the MCP server returns for branches (name, protected, commit_sha) and commits (sha, html_url, created, message, author), and informed get_commit's always-populated guarantee vs. list_commits' conditional fields. +- **Research doc:** plugins/gitea/docs/research/docs/gitea/sources.md +- **Contributing files:** references/branches.md, references/commits.md +- **Status:** `extracted`