June 16, 2026 · build log

Self-running agents inside Claude Code.

Everyone's buying an “autonomous agent” framework that wraps a raw LLM API, reinvents tool-calling, and bills you a second time per token. Meanwhile the best agent runtime that exists is already on your machine and already paid for: Claude Code. You just need the right loop around it. Three pieces do it — a goal, a loop, and claude -p — and the whole thing runs on your subscription with no API key in sight.

Repo: github.com/alejandroclvi/claude-agent-loops · MIT · two working examples (Reddit + X), a headless loop driver, and the field notes.

The whole idea in three boxes

An agent is just three things wearing a trench coat: a goal (what done looks like), a loop (keep acting until done), and a runtime (something that can read state, decide, and act with tools). Most frameworks make you build all three. Claude Code already is the runtime. This repo supplies the other two and shows how to bolt them on cheaply.

Diagram: goal feeds a loop, each iteration runs claude -p, memory lives in files
The pattern. The goal describes done; the loop keeps re-invoking; claude -p does the work on your subscription; files carry the memory between passes.

The runtime you already pay for

claude -p “…” runs Claude Code non-interactively: it takes a prompt, does the work with its tools, prints the result, and exits. Two things make it the right engine for cheap autonomy. First, it bills to your Claude subscription / Claude Code login — there's no separate metered API key to manage, which is the entire cost advantage. Second, it inherits your whole toolbox: the built-in Read / Write / Bash / Grep, plus every MCP server you've already wired up. A tiny loop gets big capabilities for free.

Terminal: claude -p replies ok with no API key, then claude mcp list shows connected servers
One line proves the engine. No API key was set — claude -p reused my subscription login. Every connected MCP server becomes a tool the loop can call.

Worth clearing up the most common confusion: there is no API key to paste anywhere. If you can run claude interactively, you can run claude -p, and it's the same budget. (You can point it at the raw Anthropic API with ANTHROPIC_API_KEY for a headless server — but you don't have to, and the default path is what keeps this cheap.)

The goal: describe done, not the steps

The biggest mistake is scripting the steps. Don't. Describe the end state and let the agent plan backward from it. Compare:

A good goal is terminal (there's an observable done), bounded (it says what not to do), and stateful (it names the file that survives between iterations). That last one is the secret: state lives in files, not the model's context. Each fresh claude -p call is amnesiac — but the file remembers, so the loop is resumable, debuggable, and you can cat it anytime to see where the agent is.

The loop: three rungs, climb only as high as you need

A single turn rarely finishes a real job, so the loop re-invokes the agent to build on its own output. There's a ladder:

Terminal: loop.sh runs three iterations, growing leads.jsonl until the goal is met and it prints DONE
The headless loop in action. Each pass reads the file the last one wrote and extends it; iteration 3 sees the target met and prints DONE, so the loop exits. The agent decides done — the shell just watches for the word.

Four things keep that loop safe and cheap: a goal with an explicit DONE stop-condition; --allowedTools scoped to the minimum this job needs (your blast radius); a LOOP_MAX_ITERATIONS backstop so a confused agent can't run forever; and file-based memory so you can always see — and resume — the state.

Two examples that ship in the repo

The pattern is abstract until you watch it do real work. Both examples drive a logged-in social account through a saved browser session (no platform API key) and default to read-only — writing is opt-in and rate-limited.

The same shape generalizes far past social. A few I've run with this exact pattern, stripped to the idea:

The real unlock: a second brain under the loop

Here's the part that turns a clever trick into a system. A single loop's leads.jsonl remembers one job. But that same instinct — memory lives outside the model, in something you can read — scales into a second brain: a persistent, cross-session memory layer that every agent reads before it does anything. The loops run on top of it.

Why it matters so much: a cold agent re-derives your whole world on every run — what the project is, your conventions, what's already been tried, who you already contacted. That's slow, expensive, and exactly how agents repeat yesterday's mistakes. An agent sitting on a second brain wakes up already informed.

Diagram: goal+loop agents sitting on top of a persistent second-brain memory layer made of file memory, knowledge graph, notes, and tasks
The loops sit on top; the brain underneath persists across every session. A session-start hook injects it into every run — even a headless claude -p fired by cron wakes up knowing what it's working on.

The shape I run is a few layers, each reachable as a tool (an MCP server) so any agent can both read and write it:

The mechanic that makes it automatic is a session-start hook: at launch it injects the memory index and a short operating manual into every agent — including the headless claude -p runs a cron job fires at 3am. The agent never boots blank. It opens knowing who it is, what it's working on, and the rules it operates under.

And that's what supercharges the goal + loop pattern. Your goal can now lean on durable knowledge instead of re-explaining it every time. “Find leads we haven't already contacted” just works, because the brain remembers who you contacted. Each loop's little file stops being a throwaway and becomes one more entry in a memory that compounds — the loop gets smarter the longer it's run, without you touching the model.

Setup, honestly

Fifteen minutes, and most of it is one-time. The full walkthrough is in docs/02-setup.md; the short version:

# 1. the runtime (log in once — that's your "token")
npm i -g @anthropic-ai/claude-code
claude -p "Reply with exactly: ok" --allowedTools ""   # → ok

# 2. python runner for the examples
brew install uv

# 3. configure + capture a browser login (once)
cp .env.example .env
cd examples/reddit-outreach
uv run --with patchright python login_capture.py

# 4. wrap it in a goal-driven loop
cd ../agent-loop && ./loop.sh

Service auth is the part people expect to be painful and isn't: instead of registering an app and juggling OAuth, you capture your own logged-in browser session once (login_capture.py opens a real browser, you log in, it saves the session) and reuse it. That saved file is as sensitive as your password — every auth/ path is gitignored by default, and it lives outside the repo.

The field notes (why this, not that)

Every shortcut in the repo exists because the “obvious” path broke. These are the war stories, because they're the actually-reusable part:

The meta-lesson: probe real behavior, distrust silent success, keep a lower-level fallback, and verify. That mindset — not any one script — is what makes a small, cheap loop reliable.

Why I'm building it this way

This is the same bet I keep making: put the intelligence in the harness, not the model. I proved a 2 GB local model beats an 8B on hard research once the harness was smart enough. This is the other side of that coin — the harness here is a loop, a goal, a stop condition, and a second brain underneath, and the“model” is the best one going, already paid for. Either way the durable value lives in the structure around the model — the loops, the memory, the rules — where it compounds and persists, instead of being rented per call.

It's ~40 lines of bash plus two example toolboxes. Read it — there's no magic, and that's the point. Clone it, change the goal to a file you care about, point it at your own tools (including any MCP server you've added), and let it run.