slowlp
← Blog
Method 2026.06.27 · 9 min read

Why I Dropped Codex and Wired Claude CLI Into Hermes

Getting daily AI news via cron without spending a single credit

Method

I wanted to receive daily AI news automatically — not as blog material, just the kind of product announcements and service updates worth keeping in the wiki and dropping into Discord.

The first attempt used Hermes, the Discord bot running on my home server. Hermes was already authenticated with OpenAI Codex via OAuth, so I didn’t need a separate API key. The leftover Codex tokens would cover a daily cron, I figured. The setup: a server cron pulls RSS feeds every morning, saves them to raw/, Codex summarizes in Korean, and Discord gets the digest. It worked.

Then it stopped working.

One Morning the Digest Was Gone

I checked the server. 429 — rate limit hit.

That’s when I started looking into whether I could replace Codex with Claude CLI. The first analysis I got back was wrong.

Looking only at the Hermes config, the conclusion was: “This runs on Claude’s OAuth subscription, same pool as Claude Code — switching to CLI won’t help.” Sounded reasonable. But I knew it wasn’t right.

“No, it’s using Codex OAuth.”

That one correction turned the whole analysis upside down. Opening the server’s auth file confirmed it: OpenAI Codex OAuth. Which meant the 429 was a Codex (ChatGPT subscription) limit — completely separate from the Claude subscription pool. Running the digest with claude -p would step entirely out from under that limit. The opposite of “same pool, won’t help.”

Lesson here: don’t guess what a bot is authenticating with. Open auth.json and check.

”Wait, Does -p Mode Bill Credits?”

The next concern: if claude -p (headless mode) runs on credit-based billing, then using it alongside a subscription just means paying twice. That would make the whole thing pointless.

I didn’t trust memory on this one, so I looked it up. The answer:

  • -p doesn’t change the billing mode. It uses the same auth as the interactive claude session. If you’re logged in with subscription OAuth, -p runs on subscription limits — no credits consumed.
  • The trap is the ANTHROPIC_API_KEY environment variable. If that’s set, it takes priority over OAuth and switches you to credit-based billing. Keeping it unset in the cron environment is the whole trick.
  • claude --bare -p (bare mode) bypasses OAuth entirely and only accepts an API key. Use it only if you actually want credit billing.

In short: leave ANTHROPIC_API_KEY unset, and claude -p quietly runs on your subscription.

For Cron, setup-token Is the Right Tool

The most reliable approach for non-interactive cron turned out to be claude setup-token.

This issues a long-lived OAuth token (sk-ant-oat01-...) tied to your subscription account — not credits. Valid for roughly a year. Set it once as CLAUDE_CODE_OAUTH_TOKEN and you’re done.

# One-time issuance on Mac (needs browser for OAuth)
claude setup-token
# → outputs sk-ant-oat01-...

# Store in server .env (runs on subscription, no credits)
CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-... \
  claude -p "Summarize today's news" --allowedTools "Read,Bash"

Token issuance requires a browser, so I generated it on the Mac once and copied it to the server. Only needs to be redone when the token expires or is revoked.

Host or Container?

One decision left: where to install claude on the server.

A. Install directly on the host. Simple, but claude runs with hong user permissions — full access to /home/hong. That means trading_mvp, hansaiam, other project secrets. Too much exposure for a bot.

B. Install inside the Hermes container. Hermes already runs in a sandboxed container by design. Claude inside it only sees /workspace (the second wiki) and Hermes state directories. No docker.sock, no inbound ports, no other app secrets mounted.

The isolation case for B is straightforward — claude gets the same sandbox as Hermes. So I went with B.

B also handles rebuilds cleanly:

  • Installation is baked into the Dockerfile — it survives image rebuilds permanently
  • The token lives in .env, which is mounted — it persists across rebuilds. It doesn’t go into the image because it’s a secret

So there’s a one-time setup cost and then nothing. Add the native installer to the Dockerfile (claude.ai/install.sh stable, no Node required), put the token in .env, wire the digest call to docker exec hermes-discord claude -p .... After that, rebuilds are automatic.

The Final Shape

[Codex cron] 429 rate limit

[host cron] → fetch-ai-news.py → claude -p (subscription OAuth) → digest → git push

ANTHROPIC_API_KEY unset + CLAUDE_CODE_OAUTH_TOKEN (setup-token) → subscription only

Container isolation (B): claude only sees the second wiki

The news fetch itself doesn’t require Hermes at all — just a host cron and claude. [[헤르메스-claude-code-분담-운용|Wherever hermes chat used to be called]], claude -p slots in.

It’s been running daily since. Codex is fully out of the automation path. The Discord chat side still technically uses Codex’s free tokens, but there’s almost no chat happening. When something comes up, I file it as a blog idea rather than typing it into Discord.

From the project
Hermes LIVE
Thoughts dropped into Discord automatically accumulate in the second brain.
View →
COMMENTS