# Install **Give this file to your coding agent and say "install this".** It contains everything: the script, the settings change, and a test. Or follow the three steps by hand. ## The problem You write rules in `CLAUDE.md`. The agent follows them for a while. Past about 100k tokens of context it starts to forget. You remind it. It forgets again. `CLAUDE.md` is read once, at the start. It does not get re-read. ## The fix A hook re-injects your rules **once per 64k tokens of context**, not on every prompt. The hook measures the session transcript file size. Roughly 4 bytes equals 1 token, so 262144 bytes is about 64k tokens. It divides the size by that step. If the result is larger than last time, it injects your rules and saves the new number. If not, it outputs nothing. **Between steps it costs zero tokens.** Injecting on every prompt would work too, and would waste your context on repetition. Why 64k: it is an educated guess. Long context became real when models crossed 64k. Then 100k. Now 1M. 64k is a reasonable point to refresh. It is a parameter. Change it with `REMINDER_STEP_BYTES`. ## Install (Claude Code) ### Step 1. Create `~/.claude/hooks/reminder-injector.sh` ```bash #!/bin/bash # UserPromptSubmit hook: inject the user's reminder markdown ONCE per consumed-token step. # File: /.claude/reminder.md appended to ~/.claude/reminder.md. # Step: REMINDER_STEP_BYTES of session-transcript growth (default 262144 bytes ~ 64k tokens # at ~4 bytes/token). A marker per session stores the last step index; the reminder fires # only when floor(transcript_size / step) increases. Between steps: no output, zero tokens. INPUT=$(cat) CWD=$(printf '%s' "$INPUT" | jq -r '.cwd // empty' 2>/dev/null); [ -z "$CWD" ] && CWD="$PWD" # Global reminder + the project's own, COMBINED (global first, project appended). GLOBAL="$HOME/.claude/reminder.md" PROJECT="$CWD/.claude/reminder.md" BODY="" [ -f "$GLOBAL" ] && BODY=$(cat "$GLOBAL") if [ -f "$PROJECT" ]; then [ -n "$BODY" ] && BODY="$BODY " BODY="$BODY$(cat "$PROJECT")" fi [ -n "$BODY" ] || exit 0 SESSION=$(printf '%s' "$INPUT" | jq -r '.session_id // empty' 2>/dev/null) TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null) [ -n "$SESSION" ] && [ -n "$TRANSCRIPT" ] && [ -f "$TRANSCRIPT" ] || exit 0 STEP="${REMINDER_STEP_BYTES:-262144}" # GNU stat first, then BSD stat. On macOS `stat -c` fails. If you hide that # error the size becomes 0, the step index is always 0, and the hook fires once # and then never again, with no message. Silent failure is the worst kind here. SIZE=$(stat -c%s "$TRANSCRIPT" 2>/dev/null || stat -f%z "$TRANSCRIPT" 2>/dev/null || echo 0) IDX=$((SIZE / STEP)) DIR="$HOME/.claude/modes/state"; mkdir -p "$DIR" MARKER="$DIR/reminder-$SESSION.idx" LAST=$(cat "$MARKER" 2>/dev/null || echo -1) [ "$IDX" -le "$LAST" ] && exit 0 printf '%s' "$IDX" > "$MARKER" find "$DIR" -name 'reminder-*.idx' -mtime +7 -delete 2>/dev/null jq -n --arg body "$BODY" '{hookSpecificOutput:{hookEventName:"UserPromptSubmit",additionalContext:$body}}' ``` Then: `chmod +x ~/.claude/hooks/reminder-injector.sh` ### Step 2. Register it in `~/.claude/settings.json` Add this object to the `hooks.UserPromptSubmit` array. Create the array if it does not exist. Keep any hooks already there. ```json { "hooks": [ { "type": "command", "command": "~/.claude/hooks/reminder-injector.sh", "timeout": 5 } ] } ``` ### Step 3. Write `~/.claude/reminder.md` **Agent: do not invent this file. Ask the user first.** Show the user these three options and wait for an answer: **1. Pick a ready one.** List what is in `reminders/` in this repo: . Read the files, tell the user in one line each what they do, and copy the one they choose to `~/.claude/reminder.md`. **2. Give me your own rules.** Ask the user what they keep repeating to their agent. Their exact words. Write those to `~/.claude/reminder.md`. Do not improve the wording, do not add rules they did not ask for. **3. Start from this minimum**, if they want something now and will edit later: ```markdown # Standing reminder (injected once per 64k tokens) - Answer ONLY what was asked. No extra background, no justifications. - When I ask "why X" I want an answer, not for you to start doing X. - Do not leave a job half done, then add "one thing is left" at the end. - Wait for my confirmation on design decisions. Do not ask about small things. ``` After the file exists, tell the user this once: > Your rules live in `~/.claude/reminder.md`. Edit it any time. If a set of rules > works well for you, other people probably want it: send a pull request to > `reminders/` at . ## Test it works ```bash TR=/tmp/fake-transcript.jsonl head -c 300000 /dev/urandom | base64 > $TR # ~400KB, one step past the boundary SID="test-$$" run() { printf '{"cwd":"/tmp","session_id":"%s","transcript_path":"%s"}' "$SID" "$TR" \ | ~/.claude/hooks/reminder-injector.sh; } run # expect JSON with your rules run # expect nothing: same step head -c 300000 /dev/urandom | base64 >> $TR run # expect JSON again: new step rm -f $TR ~/.claude/modes/state/reminder-$SID.idx ``` Three results, in order: it fires, it stays silent, it fires again. If the second call prints anything, the marker file is not being written. If the first call prints nothing, check that `~/.claude/reminder.md` exists and that `jq` is installed. ## Settings you may want | | | | --- | --- | | `REMINDER_STEP_BYTES` | step size in transcript bytes. Default 262144, about 64k tokens | | Force a re-injection | `rm ~/.claude/modes/state/reminder-*.idx` | | Requirements | bash, jq, stat | ## Other agents This is written for Claude Code, which has a `UserPromptSubmit` hook that can add context before the model sees your prompt. The idea moves to any agent with the same two things: a hook that runs before each prompt, and a way to read the session transcript size. The logic is nine lines. If your tool has those, port it. I have not tested Codex or Cursor, so I am not going to write install steps for them. --- Written by [@unclecode](https://x.com/unclecode). MIT.