(dirPath: string)
| 152 | // Used by Grep/Glob which take a directory `path` rather than a specific file. |
| 153 | // Checks both configDir and memoryBaseDir to handle custom memory dir paths. |
| 154 | export function isMemoryDirectory(dirPath: string): boolean { |
| 155 | // SECURITY: Normalize to prevent path traversal bypasses via .. segments. |
| 156 | // On Windows this produces backslashes; toComparable flips them back for |
| 157 | // string matching. MinGW /c/... paths are converted to native before |
| 158 | // reaching here (extraction-time in isShellCommandTargetingMemory), so |
| 159 | // normalize() never sees them. |
| 160 | const normalizedPath = normalize(dirPath) |
| 161 | const normalizedCmp = toComparable(normalizedPath) |
| 162 | // Agent memory directories can be under cwd (project scope), configDir, or memoryBaseDir |
| 163 | if ( |
| 164 | isAutoMemoryEnabled() && |
| 165 | (normalizedCmp.includes('/agent-memory/') || |
| 166 | normalizedCmp.includes('/agent-memory-local/')) |
| 167 | ) { |
| 168 | return true |
| 169 | } |
| 170 | // Team memory directories live under <autoMemPath>/team/ |
| 171 | if ( |
| 172 | feature('TEAMMEM') && |
| 173 | teamMemPaths!.isTeamMemoryEnabled() && |
| 174 | teamMemPaths!.isTeamMemPath(normalizedPath) |
| 175 | ) { |
| 176 | return true |
| 177 | } |
| 178 | // Check the auto-memory path override (CLAUDE_COWORK_MEMORY_PATH_OVERRIDE) |
| 179 | if (isAutoMemoryEnabled()) { |
| 180 | const autoMemPath = getAutoMemPath() |
| 181 | const autoMemDirCmp = toComparable(autoMemPath.replace(/[/\\]+$/, '')) |
| 182 | const autoMemPathCmp = toComparable(autoMemPath) |
| 183 | if ( |
| 184 | normalizedCmp === autoMemDirCmp || |
| 185 | normalizedCmp.startsWith(autoMemPathCmp) |
| 186 | ) { |
| 187 | return true |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | const configDirCmp = toComparable(getClaudeConfigHomeDir()) |
| 192 | const memoryBaseCmp = toComparable(getMemoryBaseDir()) |
| 193 | const underConfig = normalizedCmp.startsWith(configDirCmp) |
| 194 | const underMemoryBase = normalizedCmp.startsWith(memoryBaseCmp) |
| 195 | |
| 196 | if (!underConfig && !underMemoryBase) { |
| 197 | return false |
| 198 | } |
| 199 | if (normalizedCmp.includes('/session-memory/')) { |
| 200 | return true |
| 201 | } |
| 202 | if (underConfig && normalizedCmp.includes('/projects/')) { |
| 203 | return true |
| 204 | } |
| 205 | if (isAutoMemoryEnabled() && normalizedCmp.includes('/memory/')) { |
| 206 | return true |
| 207 | } |
| 208 | return false |
| 209 | } |
| 210 | |
| 211 | /** |
no test coverage detected