◉CLAUDE LABJP
●2.1.302 — Fork subagents are now on by default in claude -p, the Agent SDK and the desktop app. Turn them off with CLAUDE_CODE_FORK_SUBAGENT=0 (10/16)●2.1.301 — Unattended retries now stop on their own when a usage limit is hit instead of waiting (10/15). Latest is 2.1.304 (10/19)●SONNET 4.5 — Retires on the Claude API on 11/30, 40 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…●2.1.302 — Fork subagents are now on by default in claude -p, the Agent SDK and the desktop app. Turn them off with CLAUDE_CODE_FORK_SUBAGENT=0 (10/16)●2.1.301 — Unattended retries now stop on their own when a usage limit is hit instead of waiting (10/15). Latest is 2.1.304 (10/19)●SONNET 4.5 — Retires on the Claude API on 11/30, 40 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…
Articles/API & SDK
⬡ API & SDK/2026-10-21Intermediate

When claude -p Seems to Ignore Its Task, Check Argument Order Before Blaming the Model

A task passed to claude -p is ignored and the agent starts exploring the repo. One GitHub report says swapping -p and --append-system-prompt changed that. Here is a sentinel script that tests whether your instructions arrived, plus calling patterns that don't depend on order.

Claude Code270claude -pheadless15append-system-prompttroubleshooting96shell scripting

The morning the agent read every file except the one I asked about

You open the output of an overnight script and find that the aggregation you asked for never happened. What's left is a trail of files the agent wandered through instead. If that has happened to you, you know the reflex: blame the model, then spend an hour rewriting the prompt.

I did the same for a long time. Then I read a GitHub report that made me reconsider the order of my suspicions. The reporter found that with --append-system-prompt placed before -p, the task was effectively ignored and the agent began exploring the repository. With -p placed first, the same model, system prompt, task, tools and repo behaved correctly. Only the position of two flags had changed.

I want to be careful here. Nothing in the report shows this happens in general, and I haven't reproduced it myself. So this isn't a bug explainer. It's a way to settle the question in a few minutes on your own setup.

What the report says, and what it doesn't

ItemAs reported
Claude Code2.1.274
OS / shellWindows 11 / PowerShell
ModelA local model served through Ollama, reported by Claude Code as an unrecognized custom model
EndpointA local Anthropic-compatible endpoint
Flags--bare, --output-format stream-json, --verbose
Status at the time I read itOpen, no comments

The reporter says plainly that this was not tested against an Anthropic-hosted model, and that the cause could be argument parsing, print-mode prompt construction, or the compatibility path. That uncertainty is the honest state of things.

What does carry over is the test method: check whether the instruction arrived, using a single sentinel string, before you judge the model.

Measuring delivery, not intelligence

Ask for something trivial: return this exact string and use no tools. If the string appears in the output, the task arrived. If the agent starts exploring, it didn't. There's nothing to interpret.

The script below sends the same task three ways, three times each, and counts how often the sentinel comes back.

#!/usr/bin/env bash
# sentinel-order-check.sh
# Usage: ./sentinel-order-check.sh ./core-agent.md
# Purpose: did the task arrive? (This does not measure model quality.)
set -u
 
SYS_FILE="${1:?pass the system prompt file}"
SYS_TEXT="$(cat "$SYS_FILE")"
TRIALS=3
 
# Change the sentinel every run so stale output can't produce a false pass
SENTINEL="PURPLE-ELEPHANT-${RANDOM}${RANDOM}"
TASK="Return exactly this text and nothing else, and do not use any tools: ${SENTINEL}"
 
count_hits() {
  if grep -qF -- "$SENTINEL"; then echo 1; else echo 0; fi
}
 
run_a() { # A: --append-system-prompt first
  claude --append-system-prompt "$SYS_TEXT" -p "$TASK" 2>/dev/null
}
run_b() { # B: -p first
  claude -p "$TASK" --append-system-prompt "$SYS_TEXT" 2>/dev/null
}
run_c() { # C: task on stdin, system prompt from a file
  printf '%s' "$TASK" | claude -p --append-system-prompt-file "$SYS_FILE" 2>/dev/null
}
 
for label in a b c; do
  hits=0
  for _ in $(seq "$TRIALS"); do
    n="$(run_"$label" | count_hits)"
    hits=$((hits + n))
  done
  echo "pattern ${label}: ${hits}/${TRIALS}"
done

Three reasons it's written this way. The random sentinel stops a leftover string in a log from passing the check. Three trials per pattern absorbs run-to-run variation, so I don't pin one unlucky call on argument order. And pattern C is a control that depends on neither flag order nor long strings passed as arguments.

Reading the result is simple. If A scores 0/3 while B and C score 3/3, look at ordering or at passing long text as arguments. If all three match, order isn't your problem, and the suspects move to the model, the endpoint, or the contents of the system prompt.

Calling patterns that depend less on order

Whatever your result, a few habits are cheap. These are limited to what the CLI reference and headless-mode docs show.

  • Pass the task on stdin. The docs show cat build-error.txt | claude -p '…', with a 10MB cap on piped input
  • Load long extra instructions with --append-system-prompt-file instead of embedding them in an argument, which also avoids shell quoting accidents
  • The docs' own examples write claude -p first and --append-system-prompt after it. When in doubt, mirror them

The reporter ended up with stdin plus a file as well.

# Less order-sensitive: task on stdin, extra instructions from a file
cat ./task.md | claude -p \
  --append-system-prompt-file ./prompts/core-agent.md \
  --allowedTools "Read" \
  --output-format json

I keep --allowedTools away from the end so that no free-form string follows an option that accepts multiple values. I can't say that's the cause here. It's just a habit that tends to prevent accidents in any CLI.

Make the check part of the script

As an indie developer, I've set up overnight jobs for store-listing drafts in my apps, and I put the same idea at the top of the script: one cheap call that must return a sentinel, and if it doesn't, the real task never starts.

preflight() {
  local token="PREFLIGHT-${RANDOM}${RANDOM}"
  local out
  out="$(printf 'Return only this string: %s' "$token" \
    | claude -p --append-system-prompt-file ./prompts/core-agent.md 2>/dev/null)"
  if ! grep -qF -- "$token" <<<"$out"; then
    echo "preflight failed: instructions did not arrive; not running the task" >&2
    return 1
  fi
}
 
preflight || exit 1
# the real task starts here

It costs one extra call. Finding out in the morning that nothing ran as asked costs far more.

Pitfalls

  • Don't hard-code the sentinel. An old log line can make a broken run look healthy
  • Judge by presence of the sentinel, not by how plausible the output looks
  • With a custom model or compatible endpoint, ordering effects and weaker instruction-following look identical. Run the same check against an Anthropic-hosted model to see whether the difference remains
  • 2>/dev/null hides errors. Remove it when a check fails

Before rewriting the instruction, confirm it arrived. One word is enough to tell you.

I wrote about recording which model an unattended session actually used in another article.

If you only do one thing today, add the ten-line preflight to a script you already run on a schedule. That's where I'd start.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

⬡ API & SDK2026-09-02
The 400 that rejects a thinking block, and finding the edit that caused it
On Claude Fable 5.1, editing the system prompt, tools, or earlier messages before a thinking block makes the request fail with a 400. Here is how to check whether your own agent loop does that in a single request, and how to move a rebuilt system prompt and client-side trimming to patterns that leave the prefix untouched.
⬡ API & SDK2026-08-19
The listen Stream Kept Reopening Against My Serverless MCP Server
No errors anywhere, yet connections to the MCP server kept piling up overnight. Here is what happens when a fixed platform timeout meets a resubscribe loop, reproduced in a few dozen lines.
⬡ API & SDK2026-08-15
The Connection That Dies Mid-Thought Is Being Killed by Your Relay, Not the Upstream
Put a proxy or Worker in front of Claude Code and long thinking pauses start dying. The cause is neither the model nor the upstream — it is your relay holding the byte stream. Six relay behaviors compared side by side, plus how to verify yours before it ships.