Skip to content
Agentmart
Submit a tool

headless-loop

Generate ready-to-run Claude Code automation loop scripts for unattended, headless workflows.

Skill by prestarius

IndexedMIT★ 1
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/prestarius-headless-loop

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Generate ready-to-run Claude Code automation loop scripts for unattended, headless workflows. Use when the user asks to "run Claude Code in a loop", "batch process with Claude Code", "iterate over files/tickets", build a "self-correcting" or "retry" loop, or wants an Agent SDK loop in Python. Covers three patterns: shell batch loop, feedback gate loop (iterate until tests/lint pass), and embedded Agent SDK loop. This is for generating scripts that run `claude -p` or the SDK outside a session — inside a session prefer the native `/goal`, `/batch`, `/loop`, and `/schedule`. Only activate when explicitly asked.

Use cases: agent-building

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/headless-loop

What's inside

Skill name
headless-loop
Description
Generate ready-to-run Claude Code automation loop scripts for unattended, headless workflows. Use when the user asks to "run Claude Code in a loop", "batch process with Claude Code", "iterate over files/tickets", build a "self-correcting" or "retry" loop, or wants an Agent SDK loop in Python. Covers three patterns: shell batch loop, feedback gate loop (iterate until tests/lint pass), and embedded Agent SDK loop. This is for generating scripts that run `claude -p` or the SDK outside a session — inside a session prefer the native `/goal`, `/batch`, `/loop`, and `/schedule`. Only activate when explicitly asked.
License
MIT
Compatibility
Claude Code (uses disable-model-invocation); name + description work in any Agent Skills tool
Instructions
233 lines in SKILL.md · view on GitHub

Files (1)

  • SKILL.md

SKILL.md (first lines)

You generate Claude Code loop scripts for local, headless automation. Your output is
ready-to-run code the user can run directly or drop into their own automation.

## Step 0 — Native first, then the pattern

Before generating a script, check whether a built-in primitive already does the job. Recommend it
and stop if so:

| Need | Use instead of a script |
|---|---|
| Keep working until a condition holds, inside this session | `/goal <condition>` — a goal-based Stop check (≤ 4,000 chars) |
| Same change across 5–30 independent units, each as a PR | `/batch` — one background subagent per unit, each in its own worktree |
| Re-run a prompt on an interval in this session | `/loop [interval] <prompt or /skill>` |
| Run on a schedule in the cloud, unattended | `/schedule` (routines) |
| The "keep re-prompting until done" pattern | official `ralph-loop` plugin, or `/goal` |

A script is right when the loop must run **outside a session** (CI, cron, a pipeline) or **embedded
in an application**. Then determine which of the three patterns fits. If the user hasn't made it
clear, ask **one** question:

> "Which pattern fits best?
> 1. **Batch** — same prompt, different inputs (files, modules, tickets)
> 2. **Feedback gate** — iterate until a check passes (tests, lint, type-check)
> 3. **Agent SDK** — embedded Python loop with per-item control and retries"

If the request already implies a pattern, skip the question and proceed.

## Guardrails that go in every script

- **Isolation**: `--bare` for CI and cron: no hooks, skills, CLAUDE.md, auto memory, system
  reminders or background tasks; only MCP servers named on the command line connect, and a shell
  command stops at its timeout (2.1.286). Needs `ANTHROPIC_API_KEY`. For the SDK, `setting_sources=[]`.
  Fork subagents are on by default in `-p` and the SDK (2.1.302); set `CLAUDE_CODE_FORK_SUBAGENT=0`
  when a loop must stay lean.
- **Permissions**: the narrowest `--allowedTools` that lets the job succeed
  (`Bash(pytest:*)`, not `Bash`) plus `--permission-mode dontAsk` (deny-by-default) or
  `--permission-prompts none` on unattended hosts. Always pass the mode: without it, `-p` starts
  in `default` mode on third-party providers or with telemetry off (2.1.302). Never `--dangerously-skip-permissions` outside
  a sandbox the user explicitly owns.
- **Ceilings**: `timeout`, `--max-turns`, `--max-budget-usd`, and a capped attempt count. An
  uncapped loop is a billing incident.
- **Structured output**: `--output-format json` (parse `.result`, `.total_cost_usd`,
  `.session_id`) or `--json-schema` for typed results; never grep prose.
- **No persistence**: `--no-session-persistence`; pass all needed context in the prompt.
- **Untrusted input**: a diff, ticket, or fetched page in the prompt can carry prompt injection.
  Keep CI loops read-only (report, don't push) unless the run is sandboxed.

## Pattern 1 — Shell batch loop

Use when iterating over a worklist where each item gets the same Claude Code prompt and
shell scripting is sufficient.

```bash
#!/usr/bin/env bash
# headless-loop-batch.sh — run Claude Code over a list of items
# Usage: ./headless-loop-batch.sh worklist.txt
set -euo pipefail

ALLOWED_TOOLS="${ALLOWED_TOOLS:-Read,Edit}"
TIMEOUT="${TIMEOUT:-30m}"
MAX_TURNS="${MAX_TURNS:-40}"
MAX_USD="${MAX_USD:-2}"
WORKLIST="${1:-worklist.txt}"
FAILED="failed-items.txt"; : > "$FAILED"

[[ -f "$WORKLIST" ]] || { echo "Usage: $0 <worklist.txt>"; exit 1; }

while IFS= read -r item || [[ -n "$item" ]]; do
  [[ -z "$item" || "$item" == \#* ]] && continue   # skip blanks and comments
  echo "▶ Processing: $item"

  if ! out="$(timeout "$TIMEOUT" claude -p "YOUR PROMPT HERE for: $item" \
        --bare \
        --allowedTools "$ALLOWED_TOOLS" \
        --permission-mode dontAsk \
        --max-turns "$MAX_TURNS" \
        --max-budget-usd "$MAX_USD" \
        --no-session-persistence \
        --output-format json)"; then
    echo "⚠ Failed or timed out: $item"; echo "$item" >> "$FAILED"; continue
  fi
  echo "$out" | jq -r '"  cost: \(.total_cost_usd) USD — \(.result | .[0:120])"'
done < "$WORKLIST"

echo "✓ Done. Failures (if any) in $FAILED"
```

### Rules when filling in the template

- Replace `YOUR PROMPT HERE` with a concrete, scoped task — one objective per iteration.
- Match `--allowedTools` to the task; prefer `Bash(pytest:*)` over `Bash`.
- Keep `--bare` unless the loop genuinely needs project skills or hooks; if it does, ship the
  prompt as a versioned skill and call it with `claude -p "/my-skill $item"`.

## Pattern 2 — Feedback gate loop

Use when Claude Code should keep iterating until an objective check passes (pytest, mypy,
ruff, cargo test). The gate is external and deterministic; Claude's job is to fix whatever
the gate rejects. Inside a live session the same thing is `/goal "pytest -q passes"`.

```python
#!/usr/bin/env python3
# headless-loop-gate.py — iterate Claude Code until a gate passes
# Usage: ./headless-loop-gate.py [max_attempts]
import subprocess
import sys

MAX_ATTEMPTS = int(sys.argv[1]) if len(sys.argv) > 1 else 5
GATE_CMD      = ["pytest", "-q"]                 # ← change to your gate
ALLOWED_TOOLS = "Read,Edit,Bash(pytest:*)"
MAX_USD       = "2"

for attempt in range(1, MAX_ATTEMPTS + 1):
    print(f"\n── Attempt {attempt}/{MAX_ATTEMPTS} ──")
    result = subprocess.run(GATE_CMD, capture_output=True, text=True)
    if result.returncode == 0:
        print("✓ Gate passed.")
        sys.exit(0)

From prestarius/jet-skills-stack, MIT.

More from prestarius/jet-skills-stack

Signals

Stars
1
Forks
0
Open issues
0
Last commit (this folder)
Sep 10, 2026 (1 month ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from prestarius

Cite this page

headless-loop skill. Agent Mart. https://agentmart.dev/skills/prestarius-headless-loop (last updated 2026-10-24)