[BUG] Project slug encoding replaces all non-alphanumeric characters with "-", causing guaranteed path collisions

Status Open
Reported on v2.1.153
Maintainer reply ✓ Yes — bcherny
Activity 6 comments · opened Jun 22, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

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

  1. Create two directories, e.g. E:\test_v1 and E:\test-v1
  2. Open Claude Code in each directory
  3. 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

  1. Navigate to the first directory and start Claude Code:

cd E:\tsa_demo
claude

  1. Type a message (e.g. "hello"), then exit Claude Code.
  1. Navigate to the second directory and start Claude Code with --continue:

cd E:\tsa-demo
claude -c

  1. Observe that claude -c resumes the conversation from step 3 — it

treats both directories as the same project.

  1. 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_

View original on GitHub ↗

6 Comments

github-actions[bot] · 2 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/40946
  2. https://github.com/anthropics/claude-code/issues/69245
  3. https://github.com/anthropics/claude-code/issues/30244

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

paytonwu90 · 1 month ago

Independently reproduced this on Windows with 2 CJK-character sibling directories (not just theoretical — traced it end-to-end):

  1. Created C:\...\project\履歷 and later C:\...\project\測試 (both 2 Chinese characters, same parent directory).
  2. Ran claude -p "..." in 測試.
  3. No new folder appeared under ~/.claude/projects/. Instead, a new session .jsonl was written directly into the existing slug folder for 履歷 (C--Users-...-project---).
  4. Confirmed via the session file's own cwd field — it correctly recorded C:\...\project\測試, but the file itself was physically stored alongside the unrelated 履歷 project's session history and its memory/ 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 -.

bcherny collaborator · 11 days ago

Confirmed — reproduced on 2.1.233 (Linux).

Steps: created /tmp/tsa_demo and /tmp/tsa-demo, started a session in the first, then ran claude -c from 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 --continue resumes 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

yurenpai · 9 days ago

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:

C--Users-34776-AppData-Local-Temp-claude-collision-test----

When running claude --resume from 测试乙, the default project-scoped
resume picker displayed sessions from both 测试乙 and 项目甲. I did not
enable the all-projects view; the footer still showed:

Ctrl+A to show all projects

I also ran claude --continue from 项目甲. It resumed the session marker
that had originally been created in 测试乙:

PROJECT-B-SESSION-20260821

After extracting the cwd fields from the stored session JSONL files, the
session 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.

yurenpai · 9 days ago

Additional memory-isolation evidence from Windows with Claude Code 2.1.238:

I started a fresh Claude session from Project B without using --resume or
--continue. Project B's own project memory directory was empty, and Claude
initially reported that ONLY_PROJECT_A_82371 was not found in the current
project'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----\memory

That directory contained both MEMORY.md and
only-project-a-82371.md. Claude read the latter and confirmed that it
contained 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" />

yurenpai · 9 days ago

Additional evidence from claude project purge --dry-run on 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-4cd1619559f6

The 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" />