While using the gitea-mcp tools from a claude.ai web session (brain review + ADR-editing task, 2026-06-01), three friction points surfaced that limit how much an agent can complete end-to-end without dropping to a terminal. None are blockers, but each forces a workaround.
1. No direct-to-main write path
file_write_branch always writes to a feature branch (creating it from base if absent). The project convention (per project_create ADR and the project-wide TBD policy) is commit directly to main, every commit deployable. For single-file doc edits — a DECISIONS.md append, a CLAUDE.md tweak — being forced onto a branch + PR + merge is friction with no compensating safety gain, and it contradicts the trunk-based norm the rest of the platform follows.
Proposal: allow branch: "main" (or the repo default) as a valid target in file_write_branch — i.e. don't force a non-default branch. Keep the branch behaviour as the opt-in path for anything that genuinely warrants review.
2. No PR create/merge tools exposed to the claude.ai surface
Because writes land on a branch (see #1), the natural completion is "open a PR, merge it". pr_create / pr_merge exist in the broader gitea tool family but were not in the toolset exposed to this claude.ai session — only file_write_branch, file_delete, tag_create, release_create, repo_tree, plus the issue tools and read tools. So a branch write becomes a dead end from the web surface: I can create the branch but not land it.
Proposal: either (a) expose pr_create + pr_merge to the claude.ai connector surface so the branch→PR→merge loop can complete, or (b) implement #1 so single edits never need a branch. Doing both is ideal: direct-to-main for trivial edits, PR loop for substantial ones.
3. repo_search does not accept an owner-only listing
repo_search requires a q string; there's no clean "list all repos for owner mathias" call. I had to probe with guessed substrings (brain, ingest, hyperguild, gitea-mcp) to enumerate the repo set, which is lossy — a repo with no guessed-substring match would be invisible.
Proposal: allow repo_search with empty/absent q to return all repos for the owner (paginated), or add a thin repo_list to the exposed surface.
Acceptance criteria
An agent on the claude.ai surface can land a single-file edit to main in one tool call (no orphaned branch), or can complete branch → PR → merge without a terminal
Repo enumeration for an owner is possible without guessing search terms
Provenance
Surfaced during a brain-review session over the claude.ai gitea connector, 2026-06-01.
## Context
While using the gitea-mcp tools from a claude.ai web session (brain review + ADR-editing task, 2026-06-01), three friction points surfaced that limit how much an agent can complete end-to-end without dropping to a terminal. None are blockers, but each forces a workaround.
## 1. No direct-to-main write path
`file_write_branch` always writes to a feature branch (creating it from base if absent). The project convention (per `project_create` ADR and the project-wide TBD policy) is **commit directly to `main`, every commit deployable**. For single-file doc edits — a DECISIONS.md append, a CLAUDE.md tweak — being forced onto a branch + PR + merge is friction with no compensating safety gain, and it contradicts the trunk-based norm the rest of the platform follows.
**Proposal:** allow `branch: "main"` (or the repo default) as a valid target in `file_write_branch` — i.e. don't force a non-default branch. Keep the branch behaviour as the opt-in path for anything that genuinely warrants review.
## 2. No PR create/merge tools exposed to the claude.ai surface
Because writes land on a branch (see #1), the natural completion is "open a PR, merge it". `pr_create` / `pr_merge` exist in the broader gitea tool family but were **not in the toolset exposed to this claude.ai session** — only `file_write_branch`, `file_delete`, `tag_create`, `release_create`, `repo_tree`, plus the issue tools and read tools. So a branch write becomes a dead end from the web surface: I can create the branch but not land it.
**Proposal:** either (a) expose `pr_create` + `pr_merge` to the claude.ai connector surface so the branch→PR→merge loop can complete, or (b) implement #1 so single edits never need a branch. Doing both is ideal: direct-to-main for trivial edits, PR loop for substantial ones.
## 3. `repo_search` does not accept an owner-only listing
`repo_search` requires a `q` string; there's no clean "list all repos for owner `mathias`" call. I had to probe with guessed substrings (`brain`, `ingest`, `hyperguild`, `gitea-mcp`) to enumerate the repo set, which is lossy — a repo with no guessed-substring match would be invisible.
**Proposal:** allow `repo_search` with empty/absent `q` to return all repos for the owner (paginated), or add a thin `repo_list` to the exposed surface.
## Acceptance criteria
- [ ] An agent on the claude.ai surface can land a single-file edit to `main` in one tool call (no orphaned branch), **or** can complete branch → PR → merge without a terminal
- [ ] Repo enumeration for an owner is possible without guessing search terms
## Provenance
Surfaced during a brain-review session over the claude.ai gitea connector, 2026-06-01.
Item #1 (direct-to-main write) is the priority — fresh repro 2026-06-02
Confirming item #1 from another claude.ai session today. While committing an S5 spike handoff doc to infra (docs/superpowers/handoffs/2026-06-02-video-adapter-placement.md), I called file_write_branch with branch: "main" and it succeeded — landing the commit directly on main at a2e58db.
But that worked only because main is accepted as an arbitrary branch-name string, not because there is a deliberate direct-to-main path. The tool's contract is still "create/update a file on a feature branch (created from base if absent)." Passing main happens to no-op the branch creation since it already exists — it's an accident of the implementation, not a designed behaviour. The risk: nothing guarantees this keeps working if the tool ever starts enforcing non-default branch targets (which its own description implies it should), and there's no validation/intent signalling that direct-to-main is the sanctioned TBD path.
Why this is the highest-value item in this ticket
This is the behaviour the whole GitOps workflow leans on: the platform-wide convention (and gitea-mcp's own #27) is commit directly to main, one logical change per commit, every commit deployable. Forcing single-file edits (handoff docs, DECISIONS.md appends, CLAUDE.md tweaks) onto branch→PR→merge contradicts that and — per item #2 — currently dead-ends, since pr_create/pr_merge aren't on the claude.ai surface. So item #1 is what makes TBD from claude.ai actually function; items #2 (PR loop) and #3 (owner repo listing) are real but secondary.
Suggestion
Split item #1 out as its own focused P0 ticket ("feat: direct-to-main write path for TBD") with a deliberate acceptance criterion:
file_write_branch (or a clearer-named sibling) treats the repo default branch as a first-class, sanctioned target — not an incidental branch string
direct-to-main is the documented TBD path; feature-branch remains the opt-in for changes that genuinely warrant review
behaviour is stable even if branch-target validation is later tightened
Leave #2 and #3 in this ticket. Happy to file the split-out ticket if you'd prefer it tracked separately.
Repro provenance: S5 video-summary service placement spike, claude.ai session 2026-06-02.
## Item #1 (direct-to-main write) is the priority — fresh repro 2026-06-02
Confirming item #1 from another claude.ai session today. While committing an S5 spike handoff doc to `infra` (`docs/superpowers/handoffs/2026-06-02-video-adapter-placement.md`), I called `file_write_branch` with `branch: "main"` and it succeeded — landing the commit directly on `main` at `a2e58db`.
But that worked only because `main` is accepted as an arbitrary branch-name string, not because there is a deliberate direct-to-main path. The tool's contract is still "create/update a file on a feature branch (created from base if absent)." Passing `main` happens to no-op the branch creation since it already exists — it's an accident of the implementation, not a designed behaviour. The risk: nothing guarantees this keeps working if the tool ever starts enforcing non-default branch targets (which its own description implies it should), and there's no validation/intent signalling that direct-to-main is the sanctioned TBD path.
### Why this is the highest-value item in this ticket
This is the behaviour the whole GitOps workflow leans on: the platform-wide convention (and gitea-mcp's own #27) is **commit directly to `main`, one logical change per commit, every commit deployable**. Forcing single-file edits (handoff docs, DECISIONS.md appends, CLAUDE.md tweaks) onto branch→PR→merge contradicts that and — per item #2 — currently dead-ends, since `pr_create`/`pr_merge` aren't on the claude.ai surface. So item #1 is what makes TBD from claude.ai actually function; items #2 (PR loop) and #3 (owner repo listing) are real but secondary.
### Suggestion
Split item #1 out as its own focused P0 ticket ("feat: direct-to-main write path for TBD") with a deliberate acceptance criterion:
- `file_write_branch` (or a clearer-named sibling) treats the repo default branch as a first-class, sanctioned target — not an incidental branch string
- direct-to-main is the documented TBD path; feature-branch remains the opt-in for changes that genuinely warrant review
- behaviour is stable even if branch-target validation is later tightened
Leave #2 and #3 in this ticket. Happy to file the split-out ticket if you'd prefer it tracked separately.
_Repro provenance: S5 video-summary service placement spike, claude.ai session 2026-06-02._
Resolved as of v0.4.2 — all three friction points are closed:
Direct-to-main write — file_write_branch already commits directly to any existing branch: BranchExists→true skips branch creation and upserts (proven by TestFileWriteBranchSkipsCreateWhenBranchExists). So branch:"main" is a one-call direct-to-main write. The descriptor said "feature branch", understating it — updated to state both the direct-to-main (trunk) path and the create-from-base (PR) path.
PR create/merge — pr_create and pr_merge exist and are exposed. (And per #38/#45, pr_merge now uses canonical repo/number.)
Owner repo listing — repo_list exists (owner-scoped, paginated); code_search also fans out across an owner's repos via ListRepos. No more guessing search substrings.
Only change needed this round was the descriptor clarity fix; the capabilities were already present. Closing.
Resolved as of v0.4.2 — all three friction points are closed:
1. **Direct-to-main write** — `file_write_branch` already commits directly to any existing branch: `BranchExists`→true skips branch creation and upserts (proven by `TestFileWriteBranchSkipsCreateWhenBranchExists`). So `branch:"main"` is a one-call direct-to-main write. The descriptor said "feature branch", understating it — updated to state both the direct-to-main (trunk) path and the create-from-base (PR) path.
2. **PR create/merge** — `pr_create` and `pr_merge` exist and are exposed. (And per #38/#45, `pr_merge` now uses canonical `repo`/`number`.)
3. **Owner repo listing** — `repo_list` exists (owner-scoped, paginated); `code_search` also fans out across an owner's repos via `ListRepos`. No more guessing search substrings.
Only change needed this round was the descriptor clarity fix; the capabilities were already present. Closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Context
While using the gitea-mcp tools from a claude.ai web session (brain review + ADR-editing task, 2026-06-01), three friction points surfaced that limit how much an agent can complete end-to-end without dropping to a terminal. None are blockers, but each forces a workaround.
1. No direct-to-main write path
file_write_branchalways writes to a feature branch (creating it from base if absent). The project convention (perproject_createADR and the project-wide TBD policy) is commit directly tomain, every commit deployable. For single-file doc edits — a DECISIONS.md append, a CLAUDE.md tweak — being forced onto a branch + PR + merge is friction with no compensating safety gain, and it contradicts the trunk-based norm the rest of the platform follows.Proposal: allow
branch: "main"(or the repo default) as a valid target infile_write_branch— i.e. don't force a non-default branch. Keep the branch behaviour as the opt-in path for anything that genuinely warrants review.2. No PR create/merge tools exposed to the claude.ai surface
Because writes land on a branch (see #1), the natural completion is "open a PR, merge it".
pr_create/pr_mergeexist in the broader gitea tool family but were not in the toolset exposed to this claude.ai session — onlyfile_write_branch,file_delete,tag_create,release_create,repo_tree, plus the issue tools and read tools. So a branch write becomes a dead end from the web surface: I can create the branch but not land it.Proposal: either (a) expose
pr_create+pr_mergeto the claude.ai connector surface so the branch→PR→merge loop can complete, or (b) implement #1 so single edits never need a branch. Doing both is ideal: direct-to-main for trivial edits, PR loop for substantial ones.3.
repo_searchdoes not accept an owner-only listingrepo_searchrequires aqstring; there's no clean "list all repos for ownermathias" call. I had to probe with guessed substrings (brain,ingest,hyperguild,gitea-mcp) to enumerate the repo set, which is lossy — a repo with no guessed-substring match would be invisible.Proposal: allow
repo_searchwith empty/absentqto return all repos for the owner (paginated), or add a thinrepo_listto the exposed surface.Acceptance criteria
mainin one tool call (no orphaned branch), or can complete branch → PR → merge without a terminalProvenance
Surfaced during a brain-review session over the claude.ai gitea connector, 2026-06-01.
Item #1 (direct-to-main write) is the priority — fresh repro 2026-06-02
Confirming item #1 from another claude.ai session today. While committing an S5 spike handoff doc to
infra(docs/superpowers/handoffs/2026-06-02-video-adapter-placement.md), I calledfile_write_branchwithbranch: "main"and it succeeded — landing the commit directly onmainata2e58db.But that worked only because
mainis accepted as an arbitrary branch-name string, not because there is a deliberate direct-to-main path. The tool's contract is still "create/update a file on a feature branch (created from base if absent)." Passingmainhappens to no-op the branch creation since it already exists — it's an accident of the implementation, not a designed behaviour. The risk: nothing guarantees this keeps working if the tool ever starts enforcing non-default branch targets (which its own description implies it should), and there's no validation/intent signalling that direct-to-main is the sanctioned TBD path.Why this is the highest-value item in this ticket
This is the behaviour the whole GitOps workflow leans on: the platform-wide convention (and gitea-mcp's own #27) is commit directly to
main, one logical change per commit, every commit deployable. Forcing single-file edits (handoff docs, DECISIONS.md appends, CLAUDE.md tweaks) onto branch→PR→merge contradicts that and — per item #2 — currently dead-ends, sincepr_create/pr_mergearen't on the claude.ai surface. So item #1 is what makes TBD from claude.ai actually function; items #2 (PR loop) and #3 (owner repo listing) are real but secondary.Suggestion
Split item #1 out as its own focused P0 ticket ("feat: direct-to-main write path for TBD") with a deliberate acceptance criterion:
file_write_branch(or a clearer-named sibling) treats the repo default branch as a first-class, sanctioned target — not an incidental branch stringLeave #2 and #3 in this ticket. Happy to file the split-out ticket if you'd prefer it tracked separately.
Repro provenance: S5 video-summary service placement spike, claude.ai session 2026-06-02.
Resolved as of v0.4.2 — all three friction points are closed:
file_write_branchalready commits directly to any existing branch:BranchExists→true skips branch creation and upserts (proven byTestFileWriteBranchSkipsCreateWhenBranchExists). Sobranch:"main"is a one-call direct-to-main write. The descriptor said "feature branch", understating it — updated to state both the direct-to-main (trunk) path and the create-from-base (PR) path.pr_createandpr_mergeexist and are exposed. (And per #38/#45,pr_mergenow uses canonicalrepo/number.)repo_listexists (owner-scoped, paginated);code_searchalso fans out across an owner's repos viaListRepos. No more guessing search substrings.Only change needed this round was the descriptor clarity fix; the capabilities were already present. Closing.