openai / openai/codex

GitHub Connector can create/merge branches and PRs but cannot list or delete branches, leaving normal repository cleanup impossible

Open
#41,863 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

codex-web enhancement
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Summary

The GitHub App Connector available to ChatGPT/Codex currently supports enough write operations to create a large amount of repository state — branches, commits, pull requests, comments, merges, file writes/deletes — but does not expose the basic branch/ref lifecycle operations needed to clean that state up afterward.

This creates a very awkward capability asymmetry:

  • the connector can create branches;
  • it can commit to branches;
  • it can open PRs;
  • it can merge PRs;
  • it can inspect repository metadata and see that the authenticated user has admin, maintain, and push permissions;
  • but it cannot list branches/refs through a first-class tool;
  • it cannot delete merged branches;
  • it cannot update the repository setting that automatically deletes merged PR head branches;
  • and it exposes no generic GitHub REST request escape hatch for operations that are safe, ordinary, and already authorized by the connected GitHub App.

In practice, this means an agent can perform a complete feature-development workflow repeatedly and then gets stuck at the very last mundane maintenance step: deleting the obsolete branches it created.

Concrete example

I have a public repository with a long series of agent-created PR branches. The connected GitHub identity has full repository administration permissions. The repository metadata returned through the connector confirms:

permissions:
  admin: true
  maintain: true
  push: true
  triage: true
  pull: true

The same metadata also exposes:

default_branch: main
delete_branch_on_merge: false

The desired task was completely ordinary:

Keep main and branches attached to open PRs; delete branches whose work is already merged into main.

This is exactly the kind of repository housekeeping an agent should be able to do safely and deterministically.

However, the connector's available GitHub actions included operations equivalent to:

list repositories
get repository metadata
read file
list files
create issue
create branch
write file
delete file
commit files
create pull request
get pull request
comment
merge pull request

There was no branch listing action, branch/ref deletion action, repository-settings update action, or generic authenticated GitHub API action.

So the connector can literally do this:

create branch
  -> write code
  -> commit
  -> open PR
  -> merge PR

but cannot perform:

delete merged branch

That is a broken lifecycle boundary.

Why this matters beyond cosmetic branch clutter

This is not just a complaint about a messy branch dropdown.

A capable coding agent is expected to work repeatedly across the same repository. If every successful PR leaves a head branch behind, the repository accumulates dozens or hundreds of stale refs. This degrades both human and agent workflows:

  1. Branch selection becomes noisy.
    Humans and agents have to distinguish current work from old merged work.

  2. Branch-name collisions become more likely.
    An agent attempting to use a descriptive branch name may find an obsolete branch still occupying it.

  3. Repository state becomes harder to reason about.
    A stale branch can look like unfinished work even though its PR was already squash-merged.

  4. Automation becomes incomplete.
    The user can tell the agent to implement, test, open a PR, and merge, but then has to manually clean up the branch in the GitHub UI.

  5. Long-running agent workflows become progressively worse.
    This is particularly painful for users who deliberately use one repository as an agent development workspace and create many small PRs.

  6. The connector creates technical debt that it is incapable of removing.
    This is the key issue. The same integration responsible for creating the refs should be capable of deleting them after an explicitly authorized merge/cleanup operation.

The permission situation makes this more confusing

The connector already returns repository permission metadata indicating that the connected user has administrative/push rights.

That creates a misleading experience: the agent can see that the user is fully authorized, can perform highly consequential mutations such as merging a PR or deleting repository files, yet is inexplicably unable to delete a stale Git ref.

Deleting a merged branch is generally lower risk than several actions already exposed by the connector.

For example, the connector can currently:

  • delete a tracked source file;
  • overwrite source code;
  • commit arbitrary changes;
  • merge a pull request into the default branch.

Yet it cannot delete refs/heads/fix/already-merged-thing.

From a capability/safety standpoint, that ordering is difficult to justify.

Missing operations

At minimum, the GitHub connector should expose first-class actions for:

1. List branches

Equivalent to GitHub's repository branches API or refs API.

Useful fields should include at least:

name
sha
protected

If possible, include whether the branch is associated with an open PR.

2. Delete branch/ref

A narrowly-scoped action equivalent to deleting:

refs/heads/<branch>

The action should reject attempts to delete the repository default branch and should surface branch-protection errors cleanly.

3. Update delete_branch_on_merge

The connector can already retrieve this repository setting. It should be able to update it when the authenticated installation has the required administration permission.

This would solve the recurring problem at the source for users who want GitHub to clean up PR head branches automatically.

4. Optional generic GitHub REST action

Even if first-class tools are preferred, there should be some controlled escape hatch for supported GitHub API operations that have not yet received dedicated connector wrappers.

For example:

method: DELETE
path: /repos/{owner}/{repo}/git/refs/heads/{branch}

The connector could still enforce installation permissions and an allowlist of API families.

Without such an escape hatch, every missing endpoint becomes a hard stop for the agent regardless of how mundane the task is.

Suggested safe branch-cleanup contract

A purpose-built action could be safer than a raw REST endpoint.

Something like:

delete_branch(
    repo,
    branch,
    expected_sha=None,
)

with safeguards:

  • reject the default branch;
  • reject protected branches unless the API explicitly permits it;
  • optionally require the caller to provide the current SHA as a compare-and-delete guard;
  • return not_found distinctly from permission failures;
  • never infer branch names from user text when an exact branch identifier is available;
  • preserve normal ChatGPT confirmation policy for destructive operations where appropriate.

For bulk cleanup, an even better operation would be:

list_branches(repo)

combined with individual explicit deletions, so the model can reason about which refs are safe to remove instead of using a dangerous blanket cleanup endpoint.

Recommended agent workflow

The desired end-to-end workflow should be possible entirely through the connector:

1. Read repository metadata.
2. List open PRs and their head branches.
3. List repository branches.
4. Determine which non-default branches are fully merged into the default branch.
5. Exclude all branches backing open PRs.
6. Present/confirm the deletion set if confirmation is required.
7. Delete those exact refs.
8. Optionally enable delete_branch_on_merge for future PRs.

This is straightforward, auditable, and much safer than telling the user to paste a shell loop that runs git push origin --delete outside ChatGPT.

Current workaround is worse than a connector-native operation

Because the connector cannot delete refs, the fallback is to tell the user to run local shell commands such as:

git fetch origin --prune

gh pr list ...

git for-each-ref ...

git push origin --delete "$branch"

This is inferior in several ways:

  • the user has to leave the product;
  • local GitHub CLI authentication may not match the connector's GitHub App installation;
  • the shell environment may not even have a clone of the repository;
  • the agent loses structured API error handling;
  • cleanup becomes harder to audit;
  • a badly written shell loop is more dangerous than a typed connector action with branch-protection guards.

In other words, withholding branch deletion from the connector does not eliminate the need for deletion; it merely pushes users toward a less controlled mechanism.

Related capability consistency problem

The GitHub connector should ideally be reviewed as a complete repository workflow, not as a loose collection of individually useful endpoints.

For each state-creating operation, ask whether the corresponding normal lifecycle/cleanup operation exists.

Examples:

create branch        -> delete branch
create PR            -> close PR / change PR state
add comment          -> edit/delete comment where permitted
create issue         -> close issue
add labels           -> remove labels
create deployment    -> manage deployment lifecycle

Not every reversible action must necessarily be exposed, but branch lifecycle is fundamental enough that omitting deletion creates recurring operational debt.

Repository settings should also be writable when permissions permit

This specific repository currently reports:

delete_branch_on_merge = false

The connector can read that fact but cannot fix it.

If the connected GitHub App installation and user have repository administration access, exposing a narrowly-scoped repository-settings update would let an agent solve the issue permanently:

delete_branch_on_merge = true

There should of course be an explicit user authorization boundary for changing repository settings. But once the user explicitly asks for it, the connector should not be structurally incapable of doing the operation.

Expected behavior

When a user with adequate repository permissions says something like:

Clean up the old branches. Keep main and anything attached to an open PR. Delete merged branches.

ChatGPT/Codex should be able to:

  1. inspect branches;
  2. inspect open PR heads;
  3. determine the exact safe deletion set;
  4. delete the merged refs after whatever confirmation policy applies;
  5. optionally offer to enable automatic branch deletion after future merges.

It should not end with:

I can create and merge all of these PRs, but the connector has no branch deletion tool, so please run this shell script yourself.

That is exactly the kind of last-mile tool gap connectors are supposed to remove.

Actual behavior

The connected GitHub tool can create a branch but exposes no corresponding deletion operation and no generic refs endpoint.

The agent therefore cannot complete a normal repository cleanup even when:

  • the user explicitly requests deletion;
  • the repository is owned/administered by the connected user;
  • the repository is public;
  • the connector reports admin and push permissions;
  • the branches are already merged;
  • the desired exclusions (main, protected branches, open-PR branches) are unambiguous.

Additional request: capability discovery should make this obvious

It would also be useful if connector capability discovery exposed a machine-readable distinction between:

repository content writes
pull-request writes
ref writes
repository administration

rather than forcing the agent to discover halfway through a workflow that a basic Git operation has no tool implementation.

If a connector advertises itself as capable of GitHub repository work, users reasonably expect branch lifecycle operations to be included.

Why I am filing this as a product/connector issue rather than a GitHub API issue

GitHub already supports all of these operations. This is not an API limitation.

The missing functionality is in the ChatGPT/Codex GitHub connector tool surface. The authenticated integration can perform other repository mutations, and the target account has sufficient permissions. The connector simply does not expose the required operations.

Bottom line

The GitHub connector currently has an amusing but genuinely painful property:

It can create the branch graveyard, but it cannot clean the cemetery.

For coding agents that continuously open and merge PRs, branch deletion is not an exotic administrative feature. It is part of the ordinary happy-path PR lifecycle.

Please add branch/ref listing and deletion, and ideally a narrowly-scoped way to enable automatic deletion of merged PR branches. The connector would become substantially more complete without requiring any new conceptual permission model — these are standard GitHub operations whose authorization can continue to come from the existing GitHub App installation and explicit user intent.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the GitHub App Connector capability and action definitions, then trace how repository metadata, branches, pull requests, and authenticated REST operations are exposed. Compare the available operations with GitHub’s branch/ref and repository-settings endpoints. Done means the requested branch lifecycle and cleanup workflow is supported with the stated safety checks and corresponding coverage.

Written by the indexing model from the issue text.

Assessment

Tech stack
github
Domain
api, devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.