Auto-mode classifier silently blocks GitHub comment edits (GraphQL + REST) while allowing comment creation, with no override — Codex CLI has no equivalent restriction
Environment: Claude Code 2.1.207, macOS, non-interactive/auto-mode session, gh CLI authenticated with repo scope.
What happened: In an auto-mode session, I attempted to edit an existing GitHub issue comment (correcting a data error in a bot-generated timing log) via two independent, structurally different calls:
gh api graphql -f query='mutation { updateIssueComment(...) }'gh api -X PATCH repos/{owner}/{repo}/issues/comments/{id} -f body=@file
Both were denied identically: "Permission for this action was denied by the Claude Code auto mode classifier. Reason: Blocked by classifier." A third attempt — a local-only node -e script that only read a file and wrote to disk (no GitHub call at all) — was also denied, suggesting the classifier evaluates something like inferred intent/context rather than the literal command being executed.
Meanwhile, in the same session: creating a new comment (gh issue comment ... --body), editing issue labels/title (gh issue edit), and all read operations were permitted without issue. Only edits to already-posted comments were blocked.
Cross-tool comparison: After Claude Code refused all three attempts, I ran the exact same gh api -X PATCH command through OpenAI's Codex CLI in the same repo/environment, and it executed without any permission block or classifier objection. So the same user, the same command, the same repo, and the same credentials succeeded on a competing agentic coding tool and failed on Claude Code. That's a direct product gap, not just a documentation gap — right now Claude Code is more restrictive than a competitor for a legitimate, user-directed maintenance action, with no way to opt in.
Why this is a problem:
- The block isn't a Bash permission-rule issue — the relevant commands were already allow-listed in
.claude/settings.json, so there's no way for a user to grant this capability short of running the command themselves (or switching tools). - There's no visible documentation of what the auto-mode classifier does or doesn't allow, so this is only discoverable by trial and error.
- The behavior is inconsistent: comment creation is allowed, comment edit is not, with no stated rationale.
- It's a hard blocker with no in-session override, and it's now a concrete reason a user is considering moving work to a competing tool that doesn't have this restriction.
Ask: Either document this guardrail and its scope, or provide a settings-level way to opt in to comment-edit operations the way Bash command allow-rules already work for everything else.
4 Comments
Corroboration on one point, and a correction on another, from a session on a newer build.
Environment: Claude Code 2.1.235, Claude desktop app (Code tab), macOS 26.5.1 / Darwin 25.5.0, auto-mode session,
ghauthenticated withrepo+projectscopes, target repo private and owned by the same user.Corroboration: a local-only script was denied too
You noted that a
node -escript touching no GitHub API was also blocked, and inferred the classifier evaluates inferred intent rather than the literal command. Same thing here with a different interpreter. Apython3 - file <<'PY' … PYheredoc that did nothing but string-replace checkbox markers (- [ ]→- [x]) in a scratchpad file was denied.It is cleanly isolated. The denied call bundled a
gh issue view … > fileredirect with that heredoc. The identical redirect, run alone moments later, was allowed. So the heredoc half was the trigger, on a file in a temp scratchpad directory, with no network call in the script at all. That is a second interpreter and a second session reaching your conclusion independently.Correction: on 2.1.235 a settings rule did clear the block
This is the part worth your attention, because it contradicts this issue's central claim and the same claim in #84477 and #88537.
What was denied, three times, with the same bare "Reason: Blocked by classifier":
| Command | Result |
|---|---|
|
gh issue view N --jq .body > f+python3 - f <<'PY' … PY| Blocked ||
gh issue edit N --body-file f+gh issue view N … \| grep -c| Blocked ||
gh issue edit N --repo OWNER/REPO --body-file f(bare, single command) | Blocked ||
gh issue view N --jq .body > f && wc -l f| Allowed |Reads were never blocked at any point.
Then I added four rules to the project's
.claude/settings.json:All four verbs then succeeded on the first attempt — body edit, comment, close, and a Projects v2
item-editStatus flip. No restart, same session, no other change.So the "hard blocker with no in-session override" is at least not universal. On 2.1.235 a targeted
Bash(gh <verb>:*)rule cleared it for these verbs, which may already satisfy the second half of your ask. Worth re-testing on your end, since you were on 2.1.207 and a generic allow-list evidently did not help you.Where our observations diverge
You saw
gh issue edit(labels/title) permitted while comment edits were blocked. I sawgh issue edit --body-fileblocked, and after the rule,gh issue commentcreation succeeded. So the split is not cleanly "create allowed, edit blocked". It may be finer-grained than the verb, sensitive to the flag or payload, or it may have shifted across the 28 builds between us.Limits of this evidence
Only
gh issue editis confirmed denied pre-rule. The other three verbs went into the allow-list in the same commit and were never exercised in the denied state, so I cannot say they would have been blocked. I am also not claiming the rule works forgh pr merge, which is the verb most of the other reports centre on and which I did not touch.One agreement in full: the denial surfaces no reasoning, so the scope is discoverable only by trial and error. Even where a settings-level opt-in does work, nothing tells you that it will, or which rule to write.
Retracting the main claim in my comment above. I said a
Bash(gh <verb>:*)allow rule cleared the block on 2.1.235. That is not supported, and I should not have published it on a single trial. The corroboration half of that comment still stands; the correction half does not.What I did to check
Removed the rules mid-session and re-ran the same verbs against a scratch issue in the same private repo, same session, same build.
| Verb | Allow rule present? | Result |
|---|---|---|
|
gh issue edit(denied 3× earlier) | removed | Succeeded ||
gh issue comment| removed | Succeeded ||
gh project item-edit| removed | Succeeded ||
gh issue close| removed | Succeeded ||
gh issue create| never had one | Succeeded |Everything passes with no rules at all, including the exact command denied three times an hour earlier.
What that means
Two explanations fit, and I cannot separate them from inside one session:
settings.jsonis not re-read mid-session, so neither adding nor removing the rules ever took effect.Both destroy the causal claim. What I actually observed was a block, then a settings edit, then no block — and I read a fix into a sequence. Correlation, one trial, no control. My apologies for putting that in your thread as a correction to your report.
The part that still stands
The local-script corroboration is unaffected: a
python3 … <<'PY'heredoc doing nothing but string replacement in a temp file was denied, cleanly isolated because theghread bundled with it ran fine alone. That independently reproduces yournode -edenial and your inference that the classifier weighs inferred intent over the literal command.Also unaffected, and consistent with your report:
gh issue createwas permitted throughout whilegh issue editwas denied — your create-versus-edit split, though for us the denial fell on the issue body rather than a comment.A hypothesis I can't test alone
The denials stopped immediately after the user explicitly approved the action in-session through a question prompt. If in-session user approval is what moves the classifier, rather than settings, that would explain this sequence, and it would also fit the reports of the classifier allowing what it previously denied (#91694, #91754). Stated as a hypothesis only — I have one session and no way to isolate it.
Net effect on your issue
Your central complaint comes out stronger, not weaker. The behaviour is opaque enough that an attentive observer ran a plausible fix, saw it "work", and published the wrong conclusion to a public tracker. If the denial surfaced any reasoning, or if there were a documented way to check whether a rule applies, that error would not have been possible. Worth weighing against #72589's ask to expose the denial reason.
Follow-up to my retraction. I ran the cold-session test, and it kills my replacement hypothesis too. Posting because the negative result is more useful than either thing I claimed before it.
Method:
claude -p --permission-mode auto, one fresh process per trial — no conversation history, no prior approval in context, and.claude/settings.jsoncarrying noghallow rules at all (the four I had added are reverted).| # | Shape | Result |
|---|---|---|
| 1 |
gh issue edit --title| Succeeded || 2 |
gh issue edit --body-file— the exact shape denied 3× | Succeeded || 3–5 | same, repeated | Succeeded ×3 |
Trial 1 is a bad probe, kept only for honesty:
--titleis the variant your report says was permitted, so it proves nothing. Trials 2–5 use--body-fileand match the denied command byte for byte apart from the issue number.Ten successes now, across two session types, and zero reproductions of the original denial. Five cold as above, five in the originating session after removing the rules.
Both hypotheses are dead
What is left
The three denials happened — same session, same minute,
gh issue edit --body-filerefused with the bare "Blocked by classifier" — and are not reproducible under any condition I can construct. No configuration change, no approval state, no session shape brings them back.That leaves transient classifier unavailability failing closed as the only explanation still standing. I'm labelling it inference, having now been wrong twice on this issue with more confidence than I had earned. But it fits #86341 (intermittently unavailable) and #86755 (degraded, blocking inconsistently within a session) far better than anything configuration-shaped.
If that is what happened, it changes the shape of your ask. A documented opt-in would not have helped, because there was nothing to opt into — the correct response to that denial was to retry it, and nothing in the message hints at that. The user-visible difference between "this action is disallowed" and "the classifier is briefly unavailable, retry" is currently zero, and every wrong theory in this thread, including both of mine, came out of that gap.
Last data point, and it retracts the one piece of my first comment I said still stood.
I probed the
python3heredoc denial cold as well —claude -p --permission-mode auto, fresh process per trial, no rules, no prior approval:| Probe | Shape | Trials | Result |
|---|---|---|---|
| A | bare
python3 - f <<'PY' … PY| 3 | Succeeded ×3 || B |
gh issue view … > f+ the same heredoc (the original compound) | 3 | Succeeded ×3 |Verified by side effect, not just exit code.
So the heredoc corroboration of your
node -eobservation is withdrawn too. I claimed it was "cleanly isolated" because theghread bundled with it passed on its own moments later. That inference silently assumed the classifier is deterministic. It isn't, so two calls at different times establish nothing about which half caused the denial. Every conclusion I posted in this thread came from that same mistake.What the whole session actually looks like
ghreads, tests, greps beforehand — all fine.python3heredoc, thengh issue editthree times.ghreads never blocked at any point, including inside the window.22 attempts, 4 denials, all four inside one window, 0 reproductions since. That is not a rule about which commands are disallowed. It reads as a bounded episode where everything routed to the classifier failed closed, while read-only commands — presumably never routed to it — were untouched.
Why this may be worth separating from your report
Your issue describes a stable asymmetry: comment creation allowed, comment edits denied, reproducibly enough to test against Codex CLI and compare. If yours reproduces on demand, it is a different animal from mine and my comments are noise in your thread — say so and I will stop adding to it.
But if yours also came from a single window and was never retried afterwards, the two are the same phenomenon, and the framing in both our reports is wrong: there is nothing to opt into, no rule to document, no scope to publish. The correct response to that denial was to run the command again.
That is the actionable gap, and it is the one thing every wrong theory in this thread has in common. A denial that means "disallowed" and a denial that means "the classifier is briefly unavailable, retry" are byte-identical to the user. Three of us — you, me twice — built explanations on that ambiguity. #72589's ask to surface the denial reason would have prevented all of it.