Skip to main content
Stop paying API rates to call your own assistant. claude -p turns a Claude Code subscription into a scriptable agent that already knows your skills.

Poor Man's Agent - Claude Code Headless, No API Key Required

Stop paying API rates to call your own assistant. claude -p turns a Claude Code subscription into a scriptable agent that already knows your skills.

TL;DR

You don’t need an API key, a LiteLLM proxy, or a custom agent framework to script Claude. If you already pay for a Claude Code subscription, claude -p "..." runs a one-shot, headless prompt from your terminal - same model, same tools, same skills you already wrote - and exits. Pipe it into bash, cron, a Git hook, or a CI job. That’s your agent.

The setup most people pick (and why it’s overkill)

The default architecture for “AI in my pipeline” usually looks like:

  • Open an Anthropic / OpenAI account
  • Plug an API key into a .env
  • Pull in LiteLLM or LangChain or some agentic framework
  • Reimplement tool use, retries, prompt templates, context loading
  • Pay per token, separately from any subscription you already have

For a hobby script or a personal automation, that’s all overhead. You’re stitching together a parallel agent stack and paying API rates while your subscription sits there unused.

The trick: claude -p

The Claude Code CLI ships a flag called -p (or --print) that runs a single prompt non-interactively and prints the answer to stdout. No REPL, no UI, no session to manage:

claude -p "summarize the last 10 commits on this branch in 5 bullets"

That’s it. The CLI:

  • Uses your existing Claude Code subscription (no API key, no separate billing)
  • Runs in the current working directory, so it can read your repo
  • Honors your CLAUDE.md, your .claudeignore, and every skill in .claude/skills/
  • Can use the same tools the interactive version uses (file reads, shell, etc.)
  • Exits cleanly with the result on stdout

That last point is the unlock. Anything that consumes stdout is now an agent host: pipes, scripts, cron, Make targets, Git hooks, GitHub Actions, you name it.

A real “agent” in nine lines of bash

Drop this in bin/release-notes.sh:

#!/usr/bin/env bash
set -euo pipefail

PREV_TAG=$(git describe --tags --abbrev=0)
RANGE="${PREV_TAG}..HEAD"

claude -p "
You are writing release notes for the range ${RANGE}.
Group commits by category (feat, fix, chore).
Output Markdown only. No preamble, no closing.
" > RELEASE_NOTES.md

echo "Wrote RELEASE_NOTES.md"

That is a real agent. It reads the repo, calls a model, writes a file, exits. No framework, no API key, no LiteLLM, no LangChain. Wire it into a make release target or a pre-tag Git hook and you’re done.

Reuse the skills you already wrote

The interactive Claude Code session you use every day already activates skills based on their description. Headless mode reuses the same .claude/skills/ folder. That means:

  • The end-of-session handoff skill you wrote? Trigger it from a daily cron: claude -p "wrap up today's session and write a handoff".
  • The review this diff skill? Run it from a pre-push hook: claude -p "review the staged diff for security and style".
  • The custom domain expert skill for your team’s quirks? Run it in CI on every PR: claude -p "review changed files using the X-Corp coding standard".

You wrote the skill once. The interactive UI gets it. The headless script gets it too. Nothing else to wire.

What you give up vs the API route

To be honest about it:

  • No streaming UI. claude -p returns the full answer when it’s done. Fine for batch, not great for “watch the model think live.”
  • Rate limits follow your subscription, not the per-key API quota. For automation that runs all day, you may need to think about pacing.
  • No multi-step “deep agent” loops out of the box. You get a single prompt and a single response per invocation. If you need persistent state across runs, you save it to disk yourself (handoff files, JSON, whatever).
  • No model routing per token. You get the model the CLI is configured with. If you need Haiku for triage and Opus for hard work, you switch with claude --model per invocation - still no API key, just a flag.

For 90% of “I wish I could automate this small thing” tasks, none of that matters.

When you actually need the API

The API route earns its complexity when:

  • You’re serving Claude to other users (multi-tenant product, embedded assistant).
  • You need streaming responses to a UI you control.
  • You need fine-grained model orchestration (parallel calls, fan-out / fan-in, custom retry).
  • Your script needs to run on a machine where you can’t or won’t log into Claude Code.

Everything else: claude -p, your skills, a shell loop. That’s the poor man’s agent. It’s also, most days, the smart man’s agent.