diff --git a/plugins/bin/.claude-plugin/plugin.json b/plugins/bin/.claude-plugin/plugin.json index 52e862a..490b0ca 100644 --- a/plugins/bin/.claude-plugin/plugin.json +++ b/plugins/bin/.claude-plugin/plugin.json @@ -8,5 +8,5 @@ "keywords": [], "license": "MIT", "name": "bin", - "version": "1.0.5" + "version": "1.1.0" } diff --git a/plugins/bin/plugin.json b/plugins/bin/plugin.json index dd3aedd..b0be24c 100644 --- a/plugins/bin/plugin.json +++ b/plugins/bin/plugin.json @@ -11,5 +11,5 @@ "skills": [ "skills/" ], - "version": "1.0.5" + "version": "1.1.0" } diff --git a/plugins/bin/skills/gitea/README.md b/plugins/bin/skills/gitea/README.md deleted file mode 100644 index 3a15047..0000000 --- a/plugins/bin/skills/gitea/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# gitea - -Dispatch skill for managing a Gitea repo — issues, PRs, milestones, labels, and branches — from within Claude Code. - -## Files - -| File | Purpose | -|---|---| -| `SKILL.md` | Skill definition — dispatch table, gotchas, execution steps | -| `references/token-access.md` | Token scope inventory — what works vs. what needs additional scopes | - -## Usage - -``` -/gitea # status: open issues + open PRs -/gitea issue # create issue from conversation context -/gitea issue # get issue details -/gitea issue close # close issue -/gitea issue comment # add comment from conversation context -/gitea label Kind/Bug # apply labels by name (resolves IDs automatically) -/gitea milestone # list milestones -/gitea milestone create # create milestone -/gitea pr # create PR from current branch → main -/gitea pr <N> # get PR status and diff summary -/gitea pr merge <N> # squash-merge PR, delete branch -/gitea branch # list branches -/gitea branch create <name> # create branch from current branch -``` - -## Requirements - -- Gitea MCP server configured in `~/.claude.json` with `write:issue` and `write:repository` token scopes -- `git remote origin` pointing to the Gitea instance (used to derive owner/repo at runtime) - -## Scope (v1) - -In scope: issues, milestones, labels, PRs, branches, status. -Out of scope: releases, CI/Actions, wiki, file operations, notifications, packages, time tracking. diff --git a/plugins/bin/skills/gitea/SKILL.md b/plugins/bin/skills/gitea/SKILL.md deleted file mode 100644 index a6203aa..0000000 --- a/plugins/bin/skills/gitea/SKILL.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -name: gitea -description: > - Use when the user wants to interact with Gitea — create or update issues, - open or merge pull requests, manage labels and milestones, list branches, - or check repo status. Always use this skill to interact with the GiteaMCP, never use GiteaMCP directly. - Triggers on: "create an issue", "open a PR", "what's - open", "label this issue", "create a milestone", "merge the PR", "list - branches", "close this issue" — even when the user doesn't say "Gitea" - explicitly. Owner and repo are derived automatically from the git remote; - no config required. Do not use for releases, CI/Actions, wiki, file - operations, notifications, or package management — those are out of scope. -compatibility: Requires Gitea MCP server configured in ~/.claude.json with write:issue and write:repository token scopes. Requires git remote "origin" pointing to the Gitea instance. -allowed-tools: Bash mcp__gitea__list_issues mcp__gitea__issue_read mcp__gitea__issue_write mcp__gitea__label_read mcp__gitea__label_write mcp__gitea__milestone_read mcp__gitea__milestone_write mcp__gitea__list_pull_requests mcp__gitea__pull_request_read mcp__gitea__pull_request_write mcp__gitea__list_branches mcp__gitea__create_branch -metadata: - category: integration ---- - -## Gotchas - -- **Label writes take IDs, reads return names.** `issue_write` (add_labels, replace_labels) requires `labels: [3, 7]` (numeric IDs). Issue and PR responses return `labels: ["bug", "enhancement"]` (name strings). These are never interchangeable. Always call `label_read method: "list_repo_labels"` first and resolve names → IDs before any label write. -- **Issues and PRs share a number space.** `#5` might be an issue or a PR — there is only one counter per repo. `list_issues` returns issues only — it has no `type` parameter. Use `list_pull_requests` separately for PRs. Check `is_pull` on a single-item `issue_read` response to determine whether a number refers to an issue or PR. -- **Milestone write takes ID, not title.** `issue_write` takes `milestone: <numeric id>`. The title is not accepted. In `issue_read` responses the milestone is `{id, title}`, but in `pull_request_read` responses it's a bare title string — you cannot recover the ID from a PR response. Call `milestone_read method: "list"` and match by title if you need the ID from a PR context. -- **`get_me` is unavailable** with the current token (`write:issue, write:repository` only — `read:user` is missing). Owner and repo must always be derived from the git remote, never from `get_me` or `list_my_repos`. -- **Merging a PR does not itself close linked issues — but a commit message landing on the default branch can.** Gitea has no GitHub-style "merge triggers close" event. It does, however, parse closing keywords (`Fixes #N`, `Closes #N`) in commit messages pushed to the default branch. A regular (non-squash) merge preserves each original commit message, so if any of those commits says `Fixes #N`, the issue auto-closes at merge time — confirmed empirically (PR #64 auto-closed #63 this way, before any explicit `issue_write` call was made). This skill's own `pr merge` dispatch defaults to `merge_style: "squash"` (Step 3), which rewrites history into one commit — whether the keyword survives depends on what message that squash commit ends up with, so squash-merged PRs are the case most likely to still need an explicit close. Always call `issue_read method: "get"` to check current state before manually closing after a merge — closing an already-closed issue is a harmless no-op, but don't assume a manual close is always needed. -- **Pagination is manual.** List tools return one page at a time — no auto-pagination. When building complete datasets (e.g. all labels for name→ID mapping), iterate `page: 1, 2, ...` until result count < `per_page`. -- **`pull_request_read method: "get"` returns `review_scomments`, not `review_comments`.** This is a source-level typo in gitea-mcp v1.3.0. Do not access `review_comments` — it will always be undefined. Use `review_scomments`. -- **Cross-repo fork PRs require `head` as `"fork-owner:branch-name"`.** A bare branch name causes Gitea to search the base repo and return 422. The `pr create` dispatch assumes same-repo PRs (bare branch name). For fork-based PRs, pass `head` explicitly in the `owner:branch` format. -- **`draft: true` on PR create prepends `WIP:` to the title.** There is no first-class draft field — Gitea implements draft PRs via title prefix. To un-draft, call `pull_request_write method: "update"` and pass the title without the `WIP:` prefix. This differs from GitHub's draft PR model. -- **HTTP 404 may mean 403.** Gitea hides permission errors as not-found to avoid leaking resource existence. If a tool call returns 404 unexpectedly, check `references/token-access.md` before assuming the resource does not exist. - -## 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 - -Route on the first argument: - -| Invocation | Action | -|---|---| -| `/gitea` (no args) | **Status** — list open issues + open PRs | -| `/gitea issue` | Create issue from conversation context | -| `/gitea issue <N>` | Get issue details | -| `/gitea issue close <N>` | Close issue | -| `/gitea issue comment <N>` | Add comment from conversation context | -| `/gitea label <N> <names...>` | Apply named labels to issue/PR | -| `/gitea milestone` | List milestones | -| `/gitea milestone create <title>` | Create milestone | -| `/gitea pr` | Create PR from current branch → main | -| `/gitea pr <N>` | Get PR status and diff summary | -| `/gitea pr merge <N>` | Merge PR (squash, delete branch) | -| `/gitea branch` | List branches | -| `/gitea branch create <name>` | Create branch from current branch | - -## Step 3 — Execute - -### Status (default) - -Call `list_issues state: "open"` and `list_pull_requests state: "open"` in parallel. `list_issues` does not accept a `type` parameter — it returns issues only. `list_pull_requests` returns PRs. Report as two sections. - -### issue (create) - -Extract title and body from conversation context. Use the most recent task, bug description, grill output, or explicit statement. If no body text is available from context, fall back to empty string. Fire immediately — no confirmation step. - -**Label inference (do this before the create call):** -1. Call `label_read method: "list_repo_labels"` to get all available labels with their IDs. -2. From conversation context, infer which labels apply: - - Issue type → `Kind/*`: bug reports → `Kind/Bug`; new capabilities → `Kind/Feature`; improvements → `Kind/Enhancement`; docs → `Kind/Documentation`; security → `Kind/Security` - - Urgency signals → `Priority/*`: "blocking", "critical", "urgent" → `Priority/Critical`; "soon", "high priority" → `Priority/High`; default → `Priority/Medium` - - Explicit blocking → `Status/Blocked` -3. Resolve inferred label names to IDs from the label list. **Labels require numeric IDs — never pass name strings to `issue_write`.** If no labels can be confidently inferred, omit the `labels` parameter entirely rather than guessing. - -Set `ref` to the current branch name (`git branch --show-current`) if a branch is already checked out for this work. - -Call `issue_write method: "create" title: <extracted> body: <extracted or ""> labels: [<inferred IDs or omit>] ref: <current-branch-if-applicable>`. - -### issue <N> - -Call `issue_read method: "get" issue_number: <N>`. If the response includes `is_pull: true`, the number refers to a PR — report it as such and offer `pr <N>` for a full PR summary. - -### issue close <N> - -Call `issue_write method: "update" issue_number: <N> state: "closed"`. There is no `method: "close"` — using a non-existent method will error. - -### issue comment <N> - -Extract the comment body from conversation context (same sourcing as issue create). Call `issue_write method: "add_comment" issue_number: <N> body: <extracted>`. - -### label <N> <names...> - -1. Call `label_read method: "list_repo_labels"` — paginate until complete if > 30 labels. -2. Match each provided name (case-insensitive) against the label list → collect IDs. -3. Call `issue_write method: "add_labels" issue_number: <N> labels: [<matched IDs>]`. -4. Report applied labels and warn on any names that did not match, listing available labels. - -Do not fail the operation because of unmatched names — apply what matches. - -### milestone - -Call `milestone_read method: "list"`. Report each milestone as: id, title, state (open/closed), open issue count, closed issue count. - -### pr (create) - -1. `git branch --show-current` → head branch. -2. Title: extract from conversation context; fall back to the last commit message (`git log -1 --pretty=%s`). -3. Body: extract from conversation; fall back to empty. -4. Call `pull_request_write method: "create" head: <branch> base: "main" title: <derived in step 2> body: <derived in step 3>`. - -Note: this dispatch assumes a same-repo PR (bare branch name for `head`). For cross-repo fork PRs, `head` must be `"fork-owner:branch-name"` — see Gotchas. - -### pr <N> - -Call `pull_request_read method: "get"` and `pull_request_read method: "get_status"` in parallel (both take `pull_number: <N>`). Report: title, state, draft/merged flag, head → base, labels, CI status from get_status. Note: `milestone` in PR responses is a bare title string, not an object — you cannot extract a milestone ID from it. - -### pr merge <N> - -First call `pull_request_read method: "get_status" pull_number: <N>`. If CI status is failing, report it and warn the user — but do not block the merge unless they say to stop. - -Then call `pull_request_write method: "merge" pull_number: <N> merge_style: "squash" delete_branch: true`. To use a different merge style, the user must specify it explicitly. - -Squashing rewrites history into one commit — whether a linked issue's closing keyword survives depends on what message that squash commit ends up with. After merging, call `issue_read method: "get"` on any issue referenced by the PR to check whether it auto-closed before deciding whether to close it explicitly (see the auto-close gotcha above). - -### milestone create <title> - -Call `milestone_write method: "create" title: <title>`. Report the created milestone ID — it will be needed for assigning issues. - -### branch - -Call `list_branches`. Report each branch as: name, protected (bool). - -### branch create <name> - -Get the current local branch: `git branch --show-current`. Call `create_branch branch: <name> old_branch: <current-branch>`. This forks the new branch from where you are, not from the repo's default branch. If the user specifies a different base explicitly, use that instead. - -## Step 4 — Report - -For reads: display results as a compact table or numbered list — include number, title, labels, and milestone for issues/PRs. - -For writes: confirm what was created/updated with the Gitea issue/PR number and URL if returned. - -For errors: surface the HTTP code and message. 404 from some endpoints may actually mean insufficient token scope (Gitea hides 403 as 404 to avoid leaking resource existence). - -If label resolution fails partially, always report which names were applied and which were skipped. - -If token scope issues are suspected, read `references/token-access.md` for the full scope inventory. diff --git a/plugins/gitea/.claude-plugin/plugin.json b/plugins/gitea/.claude-plugin/plugin.json index a805fdf..15a1214 100644 --- a/plugins/gitea/.claude-plugin/plugin.json +++ b/plugins/gitea/.claude-plugin/plugin.json @@ -15,5 +15,5 @@ ], "license": "MIT", "name": "gitea", - "version": "1.3.1" + "version": "1.3.2" } diff --git a/plugins/gitea/plugin.json b/plugins/gitea/plugin.json index 89fed4c..9601cec 100644 --- a/plugins/gitea/plugin.json +++ b/plugins/gitea/plugin.json @@ -20,5 +20,5 @@ "skills": [ "skills/" ], - "version": "1.3.1" + "version": "1.3.2" } diff --git a/plugins/bin/skills/gitea/references/token-access.md b/plugins/gitea/references/token-access.md similarity index 100% rename from plugins/bin/skills/gitea/references/token-access.md rename to plugins/gitea/references/token-access.md diff --git a/plugins/gitea/skills/gitea-issues/README.md b/plugins/gitea/skills/gitea-issues/README.md index 41bb05d..7d83306 100644 --- a/plugins/gitea/skills/gitea-issues/README.md +++ b/plugins/gitea/skills/gitea-issues/README.md @@ -11,7 +11,7 @@ The create flow closes out four enrichments deferred from issue #6 comment #848: and milestone assignment (both by composing `gitea-labels-milestones`), an assignee workaround for the blocked `get_me` scope, and the "Depends on #N" dependency-linking convention. It supersedes the `issue`/`issue <N>`/`issue close <N>`/`issue comment <N>` dispatch in the old flat -`plugins/bin/skills/gitea/SKILL.md`, which remains in place untouched as a fallback per +`plugins/bin/skills/gitea/SKILL.md`, removed per `docs/adr/0011-gitea-skill-deep-modules.md`. ## Before you start