Skip to content

Let a project opt out of the memory loop with a .claude/.no-memory-loop marker - #49

Closed
breferrari wants to merge 1 commit into
mcs-cli:mainfrom
breferrari:per-project-opt-out
Closed

breferrari wants to merge 1 commit into
mcs-cli:mainfrom
breferrari:per-project-opt-out

Conversation

@breferrari

Copy link
Copy Markdown

Adds a way to exclude a single project from a global install: create an empty .claude/.no-memory-loop file in the project's root, and the pack's hooks do nothing there.

Why

A global sync installs the hooks for every project, and there was no way to leave one out. I have a repo where the memory loop doesn't fit (its knowledge lives elsewhere), and the only workaround was patching the installed hooks after every mcs sync. That broke when the hooks moved to .mts, so this puts the exclusion in the pack itself.

What changes in a project with the marker

Hook Behaviour
memory-loop-activator.sh Prints nothing
kb-gate.mts (every registration, including the kb-usage.mts copy) No search barrier, no sub-agent briefing, no log, no state, no .usage.tsv rows
sync-memories.mts Writes no config, never calls qmd

The marker is found with the existing projectRoot() (the activator repeats the same shell ladder as the launchers), so it resolves exactly the root everything else uses. Only the file's existence matters.

What doesn't change

Projects without the marker behave exactly as before. Each hook only adds one existsSync check; the activator also runs git rev-parse to find the root. Existing tests are untouched and all pass.

The memory write and delete gate can't be bypassed through the marker. Since the marker switches that gate off too, kb-gate now denies any agent Write, Edit or Bash call that touches .no-memory-loop, in any project. Only the user can create or remove it (for example with ! touch .claude/.no-memory-loop).

Docs

  • README: a short "Opting a project out" section.
  • CLAUDE.md: the gate's logging exceptions now include "opted out", plus one sentence telling future hook entry points to make the same check.

Test plan

  • Four new tests, each confirmed to fail without the change: activator silent, gate inert (spawn, briefing, write, retrieval), indexer skipped, marker protected from agents. 58/58 pass on two runs; typecheck, lint, check:sync and mcs pack validate are clean.
  • Manually: touch .claude/.no-memory-loop in a project → no reminder, no .claude/.kb-gate*, no .claude/.kb-index.
  • Ask Claude to create or delete the marker → expect a denial.

Merge danger

Door: two-way. Nothing is migrated or deleted; a revert restores the old behaviour.
Blast radius: projects that carry the marker, and any agent tool call that names it.

Your call

I kept this to the hooks and left these for you to decide:

  • Template. The installed CLAUDE.md section still tells Claude to search the KB first. A one-line exemption would help, but it lands in every user's global CLAUDE.md, so I didn't add it.
  • MCP server. It still starts in an opted-out project. Having the launcher exit would show "failed to connect" every session, so the README suggests a permissions deny instead.
  • Old state. A project that opts out after being indexed keeps its .kb-index and .kb-gate files, and doctor still checks them. Nothing is deleted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant