[BUG] Auto-memory writes prompt every time since 2.1.280 when CLAUDE_CONFIG_DIR's projects/ is a symlink to ~/.claude/projects (allow rules, hooks and auto mode cannot approve)

Status Open
Reported on v2.1.283
Maintainer reply None cached
Activity 0 comments · opened Sep 29, 2026

Environment

  • Claude Code 2.1.283 native install on macOS (Darwin 25.6), launched from the VS Code extension, permissions.defaultMode: auto. The 2.1.284 binary carries the same logic.
  • Several account profiles: CLAUDE_CONFIG_DIR=~/.claude-profiles/<profile>, where projects, settings.json, skills, plugins, commands and CLAUDE.md inside each profile are symlinks to ~/.claude/<same name>, so sessions and auto-memory are shared across profiles.

Symptom

Since 2.1.280, every Edit/Write to the session's own auto-memory directory <CLAUDE_CONFIG_DIR>/projects/<slug>/memory/*.md shows

This will modify /Users/<me>/.claude/projects/<slug>/memory/<file>.md (outside working directory) via a symlink

with only Yes / No. There is no "always allow", and in auto mode the classifier never approves it, so every memory note costs a manual click. 2.1.278 never prompted (transcripts show 2.1.278 through 2026-09-28 and the prompts start with 2.1.280 / 2.1.283).

What does not help

  • permissions.allow with Edit(~/.claude/projects/*/memory/**) and Edit(~/.claude-profiles/*/projects/*/memory/**) still prompts.
  • permissions.additionalDirectories does not apply because the sensitive-file check runs first.
  • A PreToolUse hook (matcher Edit|Write) returning permissionDecision: "allow" fires (the transcript records hook_success with allow) but the prompt is still shown.

Root cause as read from the 2.1.283 bundle

  1. Since 2.1.280 the write check builds the spellings [requested path, symlink landing] (changelog: "Fixed writes through a symlinked path being judged by their in-tree spelling").
  2. The auto-memory carve-out ("auto memory files are allowed for writing") is evaluated for every spelling and all of them must allow. It compares with startsWith(<CLAUDE_CONFIG_DIR>/projects/<slug>/memory/), so the landing spelling ~/.claude/projects/... fails and the combined result is passthrough.
  3. The sensitive-file check then flags the .claude path segment of the landing and returns ask. Because the requested spelling alone is safe while the landing is not, the result is marked not classifier-approvable, so auto mode has to ask a person.
  4. permissions.allow rules are evaluated only after that check, so they never apply.

Expected

Writes to the session's own auto-memory directory should be auto-allowed whether or not <CLAUDE_CONFIG_DIR>/projects is a symlink. For example, compare the carve-out against the realpath of the auto-memory directory as well, or treat the resolved auto-memory directory as non-sensitive as #79206 proposes.

Steps to reproduce

mkdir -p ~/.claude-profiles/p1
ln -s ~/.claude/projects      ~/.claude-profiles/p1/projects
ln -s ~/.claude/settings.json ~/.claude-profiles/p1/settings.json
export CLAUDE_CONFIG_DIR=~/.claude-profiles/p1
cd <any project> && claude          # auto mode
# ask Claude to save a memory note -> the prompt above appears on every write

Control experiment: the same layout but with the real directory outside any .claude segment (for example ~/.claude-shared/projects, with ~/.claude/projects symlinked to it) plus allow rules covering both spellings makes the writes auto-approved (tool_use to tool_result 0.07 s, versus 12 to 41 s while waiting for the prompt).

Related

  • #97585 auto mode prompts per write through a user-created symlink since 2.1.280
  • #79206 auto-memory under ~/.claude gated as a sensitive file, "always allow" does not persist
  • The 2.1.283 changelog fixed the "started in a subdirectory of a git repository" variant of the auto-memory sensitive-file block; the symlinked CLAUDE_CONFIG_DIR variant remains.

View original on GitHub ↗