# Pre‑Send Check Mechanism in the i‑have‑adhd Skill: How It Strips Preambles and Closers

> Discover the pre-send check mechanism in the i-have-adhd skill. Learn how it removes preambles and closers from assistant replies using regex for cleaner communication.

- Repository: [Ayoub Ghriss/i-have-adhd](https://github.com/ayghri/i-have-adhd)
- Tags: internals
- Published: 2026-08-20

---

**The pre‑send check in `ayghri/i-have-adhd` intercepts outgoing assistant replies and applies a two‑stage regex sanitizer to remove everything before the first numbered step and strip common closing phrases.**

The `i-have-adhd` open‑source skill enforces ten ADHD‑friendly response rules, with rule 10 mandating **"No preamble. No recap. No closers."** Rather than relying on prompt engineering alone, the skill implements a deterministic **pre‑send check** that filters LLM output at the moment before delivery. This article explains how the mechanism works, where it is implemented, and why it guarantees clean, action‑first responses across all supported runtimes.

## Where the Pre‑Send Check Lives

The mechanism is implemented in two complementary locations to ensure consistent behavior whether the skill runs as a universal hook or as an OpenCode plugin:

| Component | Location | Purpose |
|-----------|----------|---------|
| **Always‑On Hook** | `hooks/always-on.mjs` | Universal intercept that sanitizes every outgoing message |
| **OpenCode Plugin Wrapper** | `.opencode/plugins/i-have-adhd.mjs` | Runtime‑specific wrapper applying the same logic |

Both files import and execute an identical sanitization function, ensuring that Claude, OpenAI, Gemini, or any other backend receives identically filtered output.

## How the Sanitizer Removes Preambles and Closers

The `stripPreambleAndClosers()` function performs two regex passes on the raw LLM output.

### Stage 1: Strip the Preamble

The first regex discards everything before the first numbered step (e.g., "1.", "2."):

```js
const withoutPreamble = raw.replace(/^.*?(?=\d+\.)/s, '');

```

- **`^.*?(?=\d+\.)`** — From the start of the string, match any characters lazily until a positive lookahead finds digits followed by a period.
- **`s` flag** — Allows the dot to match newlines, catching multi‑line preambles.

This eliminates phrases like *"Sure, here's what you need:"* or *"Here are the steps:"* that LLMs commonly prepend.

### Stage 2: Strip the Closer

The second regex removes recognized closing sentences:

```js
const withoutCloser = withoutPreamble.replace(
  /(?:\s*Hope this helps!|\s*Let me know if you need anything else\.)\s*$/i,
  ''
);

```

The pattern targets exact phrases defined in [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) under rule 10. The case‑insensitive flag (`i`) ensures matches regardless of capitalization.

### Complete Implementation

Here is the full sanitization helper as implemented in the codebase:

```js
// helpers.js (simplified excerpt)
export function stripPreambleAndClosers(text) {
  // Remove anything before the first numbered step
  const stepStart = text.replace(/^.*?(?=\d+\.)/s, '');

  // Remove common closing phrases
  return stepStart.replace(
    /(?:\s*Hope this helps!|\s*Let me know if you need anything else\.)\s*$/i,
    ''
  );
}

```

## Hook Integration Points

### Always‑On Hook (`hooks/always-on.mjs`)

The universal hook intercepts every response at the pre‑send stage:

```js
// hooks/always-on.mjs
import { stripPreambleAndClosers } from './helpers.js';

export async function onPreSend({ output }) {
  const cleaned = stripPreambleAndClosers(output);
  return { output: cleaned };
}

```

The `onPreSend` function is invoked automatically by the runtime before displaying text to the user, making the sanitization transparent to downstream consumers.

### OpenCode Plugin Wrapper (`.opencode/plugins/i-have-adhd.mjs`)

For OpenCode environments, the plugin's `run()` method applies identical processing:

```js
// .opencode/plugins/i-have-adhd.mjs
import { stripPreambleAndClosers } from '../helpers.js';

export async function run(context) {
  const raw = await generateAnswer(context);
  return stripPreambleAndClosers(raw);
}

```

This dual implementation guarantees that the **pre‑send check mechanism** operates consistently regardless of how the skill is deployed.

## Supporting Files and Extensions

| File | Description |
|------|-------------|
| [`skills/i-have-adhd/SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/skills/i-have-adhd/SKILL.md) | Defines rule 10 and the complete set of ADHD‑friendly response guidelines |
| [`extensions/i-have-adhd.ts`](https://github.com/ayghri/i-have-adhd/blob/main/extensions/i-have-adhd.ts) | TypeScript type definitions for developers extending the skill |
| [`hooks/always-on.sh`](https://github.com/ayghri/i-have-adhd/blob/main/hooks/always-on.sh) / `.ps1` / `.bat` | Shell wrappers for environments that execute scripts directly |

## Why Centralized Sanitization Matters

- **Runtime independence** — The same logic applies to Claude Code, OpenAI, Gemini, and local models without per‑provider configuration.
- **Prompt resilience** — Even if the system prompt is bypassed or the LLM hallucinates filler text, the output is guaranteed clean.
- **User experience** — ADHD‑friendly responses prioritize immediate actionable content, reducing cognitive load from unnecessary framing.

## Summary

- The **pre‑send check mechanism** in `ayghri/i-have-adhd` enforces rule 10 ("No preamble. No recap. No closers") by intercepting outgoing text.
- **Two regex passes** remove content before the first numbered step and strip recognized closing phrases.
- Implementation spans **`hooks/always-on.mjs`** for universal coverage and **`.opencode/plugins/i-have-adhd.mjs`** for OpenCode integration.
- The shared **`stripPreambleAndClosers()`** helper ensures identical behavior across all deployment targets.

## Frequently Asked Questions

### What triggers the pre‑send check to run?

The pre‑send check runs automatically on every assistant response. In hook mode, the runtime calls `onPreSend()` before displaying output. In OpenCode mode, the plugin's `run()` method explicitly invokes the sanitizer. No user action is required.

### Can I customize which phrases count as closers?

Currently, the closer phrases are hardcoded in the regex within [`helpers.js`](https://github.com/ayghri/i-have-adhd/blob/main/helpers.js) and documented in [`SKILL.md`](https://github.com/ayghri/i-have-adhd/blob/main/SKILL.md). To extend the list, modify the alternation group (` Hope this helps!|...`) in both the source code and the rule documentation, then rebuild the skill.

### Does the sanitizer handle non‑numbered responses?

No. The preamble removal specifically targets the first occurrence of `\d+\.` (digits followed by a period). If the LLM outputs unnumbered content, the preamble will persist. This aligns with the skill's design, which expects structured, step‑based answers.

### Is there performance overhead from the regex processing?

Negligible. The regexes execute in microseconds on typical response lengths. The check adds no I/O or network latency since it operates on strings already held in memory.