[BUG] Security-guidance plugin Stop hook always skips ("LLM review disabled or no API credentials") for subscription/OAuth users — ANTHROPIC_AUTH_TOKEN not reaching hook environment
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
claude --version 2.1.209 (Claude Code)
Summary
The bundled security-guidance plugin never runs its LLM-based reviews (Stop hook, commit review, push sweep) when authenticated via a Claude subscription (OAuth) instead of an ANTHROPIC_API_KEY. The plugin's own docstring states that ANTHROPIC_AUTH_TOKEN is a valid alternative to an API key and that "Claude Code passes this automatically for OAuth-authenticated users", but in practice HAS_API_CREDENTIALS evaluates to false and every LLM review is skipped.
Debug log
extensibility: loaded 1042 chars from /Users/<me>/.claude/claude-security-guidance.md
Stop hook: LLM review disabled or no API credentials
The guidance file loads correctly (1042 chars). The skip happens at the credentials gate.
Relevant code
In the plugin hook script, all LLM review paths gate on:
pythonif not ENABLE_CODE_SECURITY_REVIEW or not HAS_API_CREDENTIALS:
debug_log("... LLM review disabled or no API credentials")
... sys.exit(0)
ENABLE_CODE_SECURITY_REVIEW defaults to enabled, so the trip is HAS_API_CREDENTIALS == False. HAS_API_CREDENTIALS is derived in llm.py from ANTHROPIC_API_KEY OR ANTHROPIC_AUTH_TOKEN. Neither is present in the hook subprocess environment for an OAuth-authenticated (subscription) session.
Plugin docstring (for reference):
- ANTHROPIC_API_KEY: Required for LLM-based reviews
- ANTHROPIC_AUTH_TOKEN: Alternative to API key — OAuth access token sent as Bearer auth.
Claude Code passes this automatically for OAuth-authenticated users.
Steps to reproduce
Authenticate Claude Code with a Claude subscription (OAuth login), with no ANTHROPIC_API_KEY set.
Enable the security-guidance plugin and place a ~/.claude/claude-security-guidance.md.
Make a code edit and let the session stop (trigger the Stop hook), or run git commit.
Check the plugin debug log.
Expected
The Stop hook / commit review runs the LLM review using the OAuth token (ANTHROPIC_AUTH_TOKEN) that Claude Code is documented to pass automatically.
Actual
HAS_API_CREDENTIALS is false and every LLM review is skipped with "LLM review disabled or no API credentials". Setting ANTHROPIC_API_KEY manually is the only workaround, which incurs separate metered API billing on top of the subscription.
Environment (please fill in)
Claude Code version: claude --version → __________
OS / version: __________
Auth method: Claude subscription (OAuth), no ANTHROPIC_API_KEY
echo $ANTHROPIC_AUTH_TOKEN inside a hook context: (empty / set?) __________
Additional notes
This looks like the OAuth access token is not being exported into the hook subprocess environment, so the plugin cannot pick it up as ANTHROPIC_AUTH_TOKEN. If token export to hooks was added in a specific version, subscription users on older versions would see this. Confirmation of the intended behavior (should hooks receive ANTHROPIC_AUTH_TOKEN automatically?) would help.
What Should Happen?
The Stop hook / commit review runs the LLM review using the OAuth token (ANTHROPIC_AUTH_TOKEN) that Claude Code is documented to pass automatically.
Error Messages/Logs
extensibility: loaded 1042 chars from /Users/<me>/.claude/claude-security-guidance.md
Stop hook: LLM review disabled or no API credentials
Steps to Reproduce
Authenticate Claude Code with a Claude subscription (OAuth login), with no ANTHROPIC_API_KEY set.
Enable the security-guidance plugin and place a ~/.claude/claude-security-guidance.md.
Make a code edit and let the session stop (trigger the Stop hook), or run git commit.
Check the plugin debug log.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.209
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
This looks like the OAuth access token is not being exported into the hook subprocess environment, so the plugin cannot pick it up as ANTHROPIC_AUTH_TOKEN. If token export to hooks was added in a specific version, subscription users on older versions would see this. Confirmation of the intended behavior (should hooks receive ANTHROPIC_AUTH_TOKEN automatically?) would help.