[BUG] Project slug encoding replaces all non-alphanumeric characters with "-", causing guaranteed path collisions
Preflight Checklist
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
- [x] I have searched existing issues and this hasn't been reported yet
What's Wrong?
Claude Code replaces all non-alphanumeric characters (including _ - .
and all non-ASCII characters) with a single - when generating the project
slug, causing different directory names to resolve to the same slug.
The function OVK / oU8 applies this regex:
``js``
path.replace(/[^a-zA-Z0-9]/g, "-")
If a character is in a-z A-Z 0-9 → keep it. Otherwise → replace with -.
### Collision case 1: ASCII separators
````
E:\MatLab_HomeWork → E--MatLab-HomeWork
E:\MatLab-HomeWork → E--MatLab-HomeWork ← same slug
E:\MatLab.HomeWork → E--MatLab-HomeWork ← same slug
_ - . are all outside [a-zA-Z0-9], so they all become - and are
indistinguishable from each other.
### Collision case 2: non-ASCII characters
````
D:\桌面\资料\matlab综合 → D--------matlab--
D:\其他\目录\matlab内容 → D--------matlab-- ← same slug
Each Chinese character becomes exactly one -, retaining no identity.
Two paths with the same number of non-ASCII characters in the same
positions will always collide.
## Steps to reproduce
- Create two directories, e.g.
E:\test_v1andE:\test-v1 - Open Claude Code in each directory
- Observe they share the same project slug, causing session history and
memory to leak across directories
## Expected behavior
_, -, and . should produce distinct slugs. Non-ASCII characters
should be encoded in a way that preserves distinguishable information.
## Environment
- OS: Windows 11
- Claude Code version: 2.1.153
## Additional context
Same root cause as issue #40946.
What Should Happen?
Different directory paths should produce different project slugs. Specifically:
_,-, and.in path names should remain distinct in the slug rather
than all collapsing to the same character
- Non-ASCII characters should be encoded in a lossless way (e.g., URL-style
percent encoding or base36 encoding of codepoints), so that two paths
containing different non-ASCII characters do not accidentally collide
Error Messages/Logs
Steps to Reproduce
1.Open a terminal and create two directories with names differing only
by _ vs -:
mkdir E:\tsa_demo
mkdir E:\tsa-demo
- Navigate to the first directory and start Claude Code:
cd E:\tsa_demo
claude
- Type a message (e.g. "hello"), then exit Claude Code.
- Navigate to the second directory and start Claude Code with
--continue:
cd E:\tsa-demo
claude -c
- Observe that
claude -cresumes the conversation from step 3 — it
treats both directories as the same project.
- Optionally, verify the slug collision by checking the project storage:
ls ~/.claude/projects/
# Both directories map to the single slug: E--tsa-demo
Claude Model
Other
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
Claude Code version: 2.1.153
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
_No response_
6 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Independently reproduced this on Windows with 2 CJK-character sibling directories (not just theoretical — traced it end-to-end):
C:\...\project\履歷and laterC:\...\project\測試(both 2 Chinese characters, same parent directory).claude -p "..."in測試.~/.claude/projects/. Instead, a new session.jsonlwas written directly into the existing slug folder for履歷(C--Users-...-project---).cwdfield — it correctly recordedC:\...\project\測試, but the file itself was physically stored alongside the unrelated履歷project's session history and itsmemory/folder.This confirms the collision isn't just a slug-lookup ambiguity — it means two unrelated live projects silently share session history and auto-memory the moment their directory names happen to produce the same non-alphanumeric-character count at the same path depth. No rename or unusual action required, just picking a name in a non-ASCII language.
This disproportionately affects users working in CJK (and likely other non-Latin-script) languages, since ASCII names are preserved character-for-character but non-ASCII names are lossily collapsed to
-.Confirmed — reproduced on 2.1.233 (Linux).
Steps: created
/tmp/tsa_demoand/tmp/tsa-demo, started a session in the first, then ranclaude -cfrom the second. It resumed the first directory's conversation, and~/.claude/projects/shows a single shared folder (-tmp-tsa-demo) for both paths. The same collapse applies to.and non-ASCII characters, so distinct paths can collide as described.This is a real bug: directories that differ only by
_vs-vs.(or by non-ASCII characters in the same positions) share session history and project state. A recent release fixed the related collision for very long (>200 character) paths, but short-path collisions like this one remain. We're looking at encoding path characters losslessly and/or verifying the recorded working directory before--continueresumes a session.I couldn't confirm the regression claim — this encoding has behaved this way for a long time. If you saw distinct folders for
_vs-in a specific older version, please share that version number.🤖 Generated with Claude Code
Follow-up with newer-version evidence:
I retested this issue on Windows with Claude Code 2.1.235 using a clean,
isolated
CLAUDE_CONFIG_DIR.I created two distinct project directories:
C:\Users\34776\AppData\Local\Temp\claude-collision-test\项目甲C:\Users\34776\AppData\Local\Temp\claude-collision-test\测试乙Both projects mapped to the same slug directory:
When running
claude --resumefrom测试乙, the default project-scopedresume picker displayed sessions from both
测试乙and项目甲. I did notenable the all-projects view; the footer still showed:
I also ran
claude --continuefrom项目甲. It resumed the session markerthat had originally been created in
测试乙:After extracting the
cwdfields from the stored session JSONL files, thesession file for this resumed session contained entries for both:
C:\Users\34776\AppData\Local\Temp\claude-collision-test\测试乙C:\Users\34776\AppData\Local\Temp\claude-collision-test\项目甲This provides additional evidence that the collision can affect session
continuation and may cause cross-project session contamination, not only
cross-project visibility in the resume picker.
Additional memory-isolation evidence from Windows with Claude Code 2.1.238:
I started a fresh Claude session from Project B without using
--resumeor--continue. Project B's own project memory directory was empty, and Claudeinitially reported that
ONLY_PROJECT_A_82371was not found in the currentproject's Memory.
I then explicitly asked Claude to inspect the current project's accessible
project-level Memory and granted a one-time read-only permission for the
temporary test directory. Claude resolved the Memory directory to the shared
slug path:
...\claude-collision-config\projects\C--Users-34776-AppData-Local-Temp-claude-collision-test----\memoryThat directory contained both
MEMORY.mdandonly-project-a-82371.md. Claude read the latter and confirmed that itcontained the Project A-only marker
ONLY_PROJECT_A_82371.This does not demonstrate automatic Memory injection into a normal fresh
session. However, it demonstrates that, because of the slug collision, a
session started from Project B can resolve and read Project A's project-state
Memory storage when explicitly inspecting the shared project directory.
The read permission was granted only once; no persistent permission was
created.
<img width="1755" height="864" alt="Image" src="https://github.com/user-attachments/assets/d5376d12-7815-436c-9ab2-6ff4c15bf1b3" />
Additional evidence from
claude project purge --dry-runon Windows:I ran a dry-run purge for both distinct project paths:
C:\Users\34776\AppData\Local\Temp\claude-collision-test\项目甲C:\Users\34776\AppData\Local\Temp\claude-collision-test\测试乙Both purge plans targeted the same project storage directory:
...\projects\C--Users-34776-AppData-Local-Temp-claude-collision-test----The plan describes this directory as containing project transcripts (
.jsonl)and
memory/.Both purge plans also targeted the same file-history directory:
...\file-history\5d2270fc-6d3a-4606-99eb-4cd1619559f6The dry-run did not delete anything. However, this indicates that purging
either project could affect shared transcripts, project Memory, and file-edit
history belonging to the other project.
The project entries in the config and the prompt-history filters remained
separate by real path, so the collision appears to affect project storage
directories rather than every project-scoped setting.
<img width="1826" height="615" alt="Image" src="https://github.com/user-attachments/assets/8df1f165-807c-4f90-ac42-44bc097bbd59" />