How the Pre-Send Check Works in the i‑have‑ADHD Extension

The pre-send check is a validation step that runs before every model response to determine whether ADHD-friendly rules must be injected into or removed from the conversation context.

The i‑have‑ADHD extension for Claude Code uses this mechanism to ensure the model follows ADHD-optimized communication rules only when explicitly enabled. The check prevents duplicate injections and guarantees clean removal when the mode is disabled, all without requiring manual context management by the user.

Where the Pre-Send Check Lives in the Codebase

The pre-send check spans two core files in the extensions/ directory:

Component File Path Purpose
rulesAreInContext extensions/context-compat.ts Examines session markers to determine if rules are currently active
syncContext extensions/i-have-adhd.ts Executes injection or removal based on the check's result

This architecture separates detection logic from action logic, making the pre-send check both testable and context-agnostic.

The Detection Logic: rulesAreInContext

The rulesAreInContext function in extensions/context-compat.ts performs the actual pre-send validation. It uses a helper function called latestMarkerIsActive to compare the order and types of custom markers in the conversation.

The function returns true only when the most recent active marker is i-have-adhd-rules — not i-have-adhd-disabled or any other state. This comparison accounts for marker timestamps and handles both OpenAI Message Protocol (OMP) and Pi context formats.

// Conceptual flow of rulesAreInContext
function rulesAreInContext(sessionMarkers: Marker[]): boolean {
  // Find latest occurrence of each marker type
  const rulesIndex = findLatestIndex(sessionMarkers, "i-have-adhd-rules");
  const disabledIndex = findLatestIndex(sessionMarkers, "i-have-adhd-disabled");
  
  // Rules are active only if they appear after any disable marker
  return latestMarkerIsActive(rulesIndex, disabledIndex);
}

The latestMarkerIsActive helper is unit-tested in scripts/check_context_compat.ts to ensure correct behavior across different context implementations.

The Action Logic: syncContext Pre-Send Handler

Before each turn, event handlers in extensions/i-have-adhd.ts call syncContext. This function uses the pre-send check result to maintain context integrity:

  • Mode enabled + rules missing: Inject the full rule set via hidden pi.sendMessage()
  • Mode disabled + rules present: Send i-have-adhd-disabled marker to cancel previous injection
  • No state change: Skip modification, avoiding unnecessary context bloat
// Simplified syncContext implementation pattern
async function syncContext(pi: PiAPI, enabled: boolean): Promise<void> {
  const rulesPresent = await rulesAreInContext(pi.getSessionMarkers());
  
  if (enabled && !rulesPresent) {
    // Pre-send injection: rules needed but not found
    await pi.sendMessage({
      role: "system",
      content: loadRulesFrom("skills/i-have-adhd/SKILL.md"),
      hidden: true
    });
  } else if (!enabled && rulesPresent) {
    // Pre-send cleanup: disable marker supersedes rules
    await pi.sendMessage({
      role: "system",
      content: "i-have-adhd-disabled",
      hidden: true
    });
  }
  // Else: state matches desired mode, no action needed
}

What the Pre-Send Check Guards Against

Failure Mode Pre-Send Defense
Duplicate rule injection syncContext only calls sendMessage when rulesAreInContext returns false, preventing multiple identical rule blocks from accumulating
Stale rules after disable The disabled marker takes precedence in latestMarkerIsActive comparison, ensuring rules stop applying immediately upon user request
Context pollution Hidden messages keep the rule management invisible to users while maintaining clear marker history for the check

Complete Pre-Send Flow Example

// 1️⃣ User enables ADHD mode
await pi.sendCommand("i-have-adhd");   // toggles enabled = true

// Pre-send check runs: rulesAreInContext() → false
// Action: Inject full rules from skills/i-have-adhd/SKILL.md

// 2️⃣ Model responds with ADHD-optimized formatting
// Pre-send check runs: rulesAreInContext() → true  
// Action: No injection needed, response proceeds normally

// 3️⃣ User disables with stop phrase
await pi.processInput("stop adhd mode");  // toggles enabled = false

// Pre-send check runs: rulesAreInContext() → true (rules still present)
// Action: Send i-have-adhd-disabled marker

// 4️⃣ Next model response follows default style
// Pre-send check runs: latest marker is disabled → rulesAreInContext() → false
// No rules applied, standard formatting restored

Rule Source and Customization

The actual rule content injected during the pre-send check resides in skills/i-have-adhd/SKILL.md. This markdown file contains the complete ADHD-friendly communication guidelines that the model follows when the pre-send check determines rules should be active. Modifying this file changes the behavior without altering the pre-send check logic itself.

Summary

  • The pre-send check is implemented through rulesAreInContext in extensions/context-compat.ts and executed via syncContext in extensions/i-have-adhd.ts
  • It validates marker state using latestMarkerIsActive to determine if ADHD rules are currently in effect
  • The check prevents duplicate injections by comparing desired state against actual context markers
  • Clean disable is achieved through marker precedence — i-have-adhd-disabled always wins over i-have-adhd-rules when newer
  • Rule content is sourced from skills/i-have-adhd/SKILL.md and injected as hidden system messages only when needed

Frequently Asked Questions

What triggers the pre-send check to run?

The pre-send check executes before every model turn through event handlers in extensions/i-have-adhd.ts. Any user message, command, or state change calls syncContext, which invokes rulesAreInContext to validate the current marker state.

Why use hidden messages instead of modifying the prompt directly?

Hidden messages preserve the conversation history structure while keeping rule management invisible to users. This approach maintains compatibility with different Claude Code context formats (OMP and Pi) without requiring platform-specific prompt injection methods.

How does the extension handle rapid enable/disable toggles?

Each toggle updates the timestamp of its respective marker. The latestMarkerIsActive helper always selects the most recent marker by time, so rapid state changes resolve correctly based on final toggle order regardless of intermediate states.

Can the pre-send check logic be tested independently?

Yes. The scripts/check_context_compat.ts file contains unit tests specifically for latestMarkerIsActive and rulesAreInContext. These tests verify correct marker comparison without requiring full Claude Code environment integration.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →