[Feature Request] First-class deferred context injection via Stop hook (`continueWith` field)

Resolved 💬 2 comments Opened Feb 8, 2026 by WarrenZhu050413 Closed Mar 9, 2026

Problem / Use Case

There's no supported way to chain multi-step workflows where context is automatically injected after Claude's response completes. This is needed for patterns like:

  • Auto code review: User types ECHO<CHECK> → Claude responds → code reviewer automatically runs
  • Multi-phase workflows: Complete task → inject "now run tests" → Claude continues
  • Skill chaining: One skill's output triggers another skill's input

Current Workaround

The only way to achieve this today is a Stop hook blocking hack:

  1. UserPromptSubmit hook parses ECHO<content> from the user's prompt, stores it in a session-scoped temp file
  2. Stop hook reads the stored content and returns {"decision": "block", "reason": "<stored content>"}
  3. Claude is forced to continue with the injected content as context

This works, but has real problems:

  • Shows as an error in the UI (#12667)—block was designed for error handling, not workflow continuation
  • Race conditions with parallel sessions (#15047, #15885)—state files must be keyed by session_id, not project path
  • No infinite loop protection—need manual guards (stop_hook_active checks)
  • Fragile state management—temp files, cleanup logic, atomic writes via mv
  • Overloaded semanticsdecision: "block" + reason conflates "error, stop" with "continue with this context"

How It's Built Today (3 hooks)

# 1. echo-deferred.sh (UserPromptSubmit) — captures ECHO<content>
PROMPT=$(echo "$INPUT" | jq -r '.prompt')
if [[ "$PROMPT" =~ ECHO\<([^>]+)\> ]]; then
  echo "${BASH_REMATCH[1]}" > "/tmp/claude_echo_state_${SESSION_ID}"
fi

# 2. echo-stop.sh (Stop) — injects stored content by blocking
if [[ -f "$STATE_FILE" ]]; then
  STORED=$(<"$STATE_FILE"); rm -f "$STATE_FILE"
  jq -n --arg reason "$STORED" '{"decision":"block","reason":$reason}'
fi

# 3. checkend-deferred.sh (UserPromptSubmit) — alternative: inject on NEXT prompt

The key insight: Stop hook's block decision is being repurposed as a context injection mechanism, which is powerful but semantically wrong.

Proposed Solution

Add a continueWith field to the Stop hook output schema, specifically designed for workflow continuation (not error handling):

interface StopHookOutput {
  decision: "approve" | "block";
  reason?: string;
  
  // NEW: Workflow continuation
  continueWith?: string;    // Inject this as Claude's next context
  showAsError?: boolean;    // Default false — no red error banner
}

Behavior

When continueWith is present:

  1. Claude's response completes normally
  2. Instead of stopping, Claude receives continueWith as follow-up context
  3. No error banner shown (unlike current block + reason)
  4. A subtle indicator (e.g., "Hook continuation…") replaces the error UX
  5. One-shot by default—continueWith fires once, then Claude stops normally

Example: Auto Code Review

#!/bin/bash
# stop-hook.sh
STATE_FILE="/tmp/claude_echo_state_$(echo "$INPUT" | jq -r '.session_id')"
if [[ -f "$STATE_FILE" ]]; then
  STORED=$(<"$STATE_FILE"); rm -f "$STATE_FILE"
  jq -n --arg ctx "$STORED" '{"decision":"approve","continueWith":$ctx}'
fi

Now decision: "approve" means "response was fine" and continueWith means "but also do this next." Clean semantics.

Stretch Goal: Built-in ECHO<content> Primitive

If continueWith lands, Claude Code could natively support an ECHO<content> syntax in user prompts—no custom hooks needed:

Fix the login bug ECHO<CHECK>

Claude fixes the bug, then automatically runs whatever CHECK maps to. This would make deferred context injection a zero-config feature.

Why Not clearContext?

Issue #16659 proposes clearContext: true for the Ralph Wiggum loop pattern. That solves a different problem (context bloat across iterations). This proposal is orthogonal:

  • clearContext = "forget everything, start fresh with this prompt"
  • continueWith = "keep context, inject this as a follow-up"

Both could coexist. You could even combine them: {"clearContext": true, "continueWith": "Start phase 2"}.

Session Isolation

A lesson from building this: state must be keyed by session_id, not project path. Multiple Claude Code sessions in the same directory will steal each other's state if keyed by project. The session_id field in hook input was the fix. If continueWith is built-in, this is handled automatically.

Related Issues

  • #12667 — Stop hook shows "error" for intentional blocking (direct consequence of this hack)
  • #15047 — Cross-session stop hook interference (race condition this pattern hits)
  • #15885 — Multiple state files needed for session isolation
  • #16659 — clearContext field proposal (orthogonal, complementary)
  • #16932 — Slash command chaining (similar goal, different mechanism)
  • #10808 — Autonomous messages after SessionStart (related: proactive context injection)

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗