Thanks for the clarifcations.
Cursor version
Version: 3.6.21
VS Code Extension API: 1.105.1
Commit: e7a7e93f4d75f8272503ecf33cedbaae10114a10
Date: 2026-05-28T21:45:36.072Z
Layout: editor
Build Type: Stable
Release Track: Default
Electron: 39.8.1
Chromium: 142.0.7444.265
Node.js: 22.22.1
V8: 14.2.231.22-electron.0
xterm.js: 6.1.0-beta.220
OS: Linux x64 6.17.0-29-generic
I Software Update before I begin development so I’m certain it was an earlier version when this post was created.
I am only rarely in privacy mode and was not at the time I submitted this post.
Some recent Cursor update caused Cursor to start opening in Agent mode and the hook was running continuously. So I had the agent try to fix the runaway hook. It was supposed to be a hook that on Stop checked to see if any project files were updated and then confirm the project plan.md and readme.md were accurate.
Here is the hook after the agent tried to fix the continual firing:
#!/bin/bash
# Stop hook: check whether README.md and Project Plan.md were updated
# when extension source files were modified during the session.
#
# Uses git status to detect which files changed. If any file under
# iherb-extension/ was modified but README.md or Project Plan.md
# was not, sends the agent back with a followup message.
cd "$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0
changed_files=$(git status --porcelain 2>/dev/null)
if [ -z "$changed_files" ]; then
exit 0
fi
extension_changed=$(echo "$changed_files" | grep -c "iherb-extension/")
readme_changed=$(echo "$changed_files" | grep -c "README.md")
plan_changed=$(echo "$changed_files" | grep -c "Project Plan.md")
if [ "$extension_changed" -eq 0 ]; then
exit 0
fi
# Skip if we already reviewed this exact set of changes this session.
# The signature covers only extension files so adding README.md or
# Project Plan.md naturally produces a new signature and re-enables the hook.
signature=$(echo "$changed_files" | grep "iherb-extension/" | md5sum | cut -d' ' -f1)
state_file="/tmp/.cursor-hook-iherb-$signature"
if [ -f "$state_file" ]; then
exit 0
fi
touch "$state_file"
missing=""
if [ "$readme_changed" -eq 0 ]; then
missing="README.md"
fi
if [ "$plan_changed" -eq 0 ]; then
if [ -n "$missing" ]; then
missing="$missing and Project Plan.md"
else
missing="Project Plan.md"
fi
fi
if [ -z "$missing" ]; then
exit 0
fi
cat <<EOF
{
"followup_message": "Extension source files were modified but $missing was not updated. Review whether $missing needs changes to stay accurate, and update if so."
}
EOF
exit 0
For now, I have removed the hook.
My Rules are all User Rules in Cursor settiings. I don’t have any in files. Here they are:
Anytime curl for an install is considered, first discuss the need for the install, the downsides of curl installs (manual uninstall) and possible alternatives.
Do not use em dash in visible content.
Any SSH key should be named for its purpose, not the algorithm (e.g. deploy_mklimp, not id_ed25519).
Prefer asking a few targeted questions when requirements are ambiguous, instead of listing many possible approaches. For design and architecture, present a small set of options with tradeoffs. For explanations, be brief and on point. If the user’s request is already specific, implement or answer without extra clarification.
Whenver possible, there should only be one source of truth. Some examples include putting server settings in a script instead of documenting them; application version should be in one variable/object and the rest of the application should then reference that variable/object.
Never switch to or suggest Plan mode. Always stay in Agent mode.
Prefer single entry and exit point per code unit (funciton, etc). Guard clauses and continue are acceptable only in functions under ~10 lines.
Prefer direct names like start, scanProducts, setPriceTier, renderBadge
Make sure README.md is accurate after any significant code update
Every application will have a project plan.md. This document should guide all work that is done on the project.
Keep implementations simple and avoid unnecessary abstraction.
- Prefer the smallest working design.
- Avoid introducing a class unless at least one is true:
- Shared mutable state must persist across operations.
- Multiple instances are required.
- Explicit lifecycle management is required.
- Do not introduce new adapter/registry/helper abstractions until the immediate phase requires them.
- If a domain model exists in Project plan.md, implement against it directly before creating parallel temporary models.
- If a layer is introduced early, include a one-line comment explaining the immediate requirement it satisfies.
- Keep control flow shallow:
- Max 2 nesting levels per function.
- Prefer guard clauses and early returns.
- Keep functions small and single-purpose (target ~20 lines, soft limit).
- If two designs are valid, choose the one with fewer abstractions.
- Refactor for clarity before adding new patterns or layers.
Comment the code
OOP preferred
At this point, I am sure some of these things are in settings and some were redundant with the hook. I am learning 
I took a break from Cursor development for a bit so I cannot say if things are better or worse. I will be active again this week.