Always-On Without Taking Over the Session

The Claude Code and Codex integrations for i-have-adhd solve a narrow but important problem: how to make a session-wide response policy available without turning installation into an unwanted behavior change or an optional hook into a startup dependency. This chapter follows the always-on path from a session event to injected rules, then compares the Node, shell, and PowerShell implementations. The useful judgment is not whether the hook runs in the happy case, but whether it stays explicit, predictable, and harmless when its inputs are missing.

Opt-in is the first transition

An always-on feature begins before the rules enter the assistant’s context. The user must create a flag file in the assistant’s configuration directory. Without that file, the hook produces no output and exits successfully. This makes the default state simple: the plugin may be installed and discoverable, but the special response mode is not active merely because the installation exists.

The hook is registered for a set of session-start conditions: startup, resume, clear, and compact. These events represent moments when a host may construct or reconstruct the context the model receives. A hook that only runs on the first startup could disappear after a context reset. A hook that runs on every ordinary request would be a different design, with different prompt and latency costs. The repository chooses the host’s session lifecycle rather than trying to intercept every response.

Each event protects against a different loss of continuity. Startup is the first opportunity to apply the user’s always-on choice. Resume covers a session that is being reopened rather than created from nothing. Clear can replace the conversation context while leaving the plugin installed. Compact can summarize or discard earlier messages, including an earlier injection of the response rules. Registering the same hook for all four events does not mean that the hook owns every turn; it means the policy gets another chance to enter context at the boundaries where the host may rebuild it. The flag remains the guard at every boundary, so a user who removes the opt-in does not keep receiving new injections merely because the session was resumed or compacted.

The event choice also defines what this adapter does not try to solve. It does not watch each response for drift, inspect whether the model followed every rule, or store a rich per-turn state record. It emits the rules at the host’s session boundary and relies on the injected policy—including its instruction to stop when the user asks—for the conversation-level behavior. That keeps the hook small, but it means the host’s context lifecycle matters. If a runtime compacts without emitting the matched event, this adapter has no evidence that the rules were lost and no documented path to reinsert them at that moment.

The launcher also has to find the plugin.