I keep my Claude Code sessions in Dropbox so that I can pick up a conversation on another Mac. That works, but it comes with an annoyance: Claude Code names each project folder after the whole working directory path, so the moment a path differs even slightly — a different machine layout, or a git worktree — a brand new folder appears and the session history splits again.
CLAUDE_CODE_PROJECT_DIR_NAME fixes this by letting you name that folder yourself. In this post, I'll show how I wired it up with direnv so it applies automatically per repository.
Note
CLAUDE_CODE_PROJECT_DIR_NAMErequires Claude Code v2.1.234 or later, released on 17 August 2026.
The problem: one <project> name per working directory path
By default, transcripts live at <config dir>/projects/<project>/<session-id>.jsonl, where <project> is the working directory path with every non-alphanumeric character replaced by -. My projects folder looked like this:
-Users-scenee-Workspace-FloatingPanel/
-Users-scenee-Workspace-blog/
-Users-scenee-Workspace-blog--claude-worktrees-fix/
-Users-scenee-Workspace-blog--agents-worktrees-cover/
-private-tmp-blog-worktrees-hotfix/
Only the first entry is a different project. The other four are all this one blog repository: the checkout itself, plus three git worktrees — one under .claude/, one under .agents/, and one I made outside the repository altogether. Every worktree is a different working directory, so every worktree gets its own project folder, and the list grows each time I branch off.
The same mechanism splits things across machines. Because the name is derived from the absolute path, a checkout at /Users/scenee/src/blog on another Mac is a different project from /Users/scenee/Workspace/blog, even though it is the same repository on the same branch.
Naming the <project> folder yourself
Setting CLAUDE_CODE_PROJECT_DIR_NAME pins the folder name regardless of the working directory. Claude Code then writes both transcripts and auto memory under that name:
<config dir>/projects/<name>/<session-id>.jsonl
<config dir>/projects/<name>/memory/
There are three rules to keep in mind:1
-
CLAUDE_CONFIG_DIRmust be set too. Claude Code ignoresCLAUDE_CODE_PROJECT_DIR_NAMEwhenCLAUDE_CONFIG_DIRis unset. Even if you are happy with the default location, you still have to export it explicitly, pointing at that same~/.claude. -
The name must be 1–64 letters, digits, hyphens or underscores (and not a Windows device name like
con). Anything else is ignored and you get the derived name back. -
It has to be in the shell environment that launches
claude. Claude Code reads it once at startup, so anenvblock insettings.jsondoes not work. I tried that first, and it silently had no effect.
Automating it with direnv
That last rule is the awkward one. Exporting the variable by hand before every claude run is easy to forget, and putting it in ~/.zshrc defeats the purpose because the value should differ per repository.
direnv does exactly this: it loads and unloads environment variables as you enter and leave a directory. After installing it and hooking it into your shell, add an .envrc at the root of the repository:
export CLAUDE_CONFIG_DIR=~/.claude
export CLAUDE_CODE_PROJECT_DIR_NAME=scenee-blog
Warning
Create the file with
direnv edit .rather than your editor of choice. It opens.envrcand runsdirenv allowfor you when you save, which saves you from the "direnv: error .envrc is blocked" message.
Now every session started from this repository (or from any of its worktrees) lands in the same folder:
scenee-blog/
├── 1f9a0c3e-....jsonl
├── 7c42b8d1-....jsonl
└── memory/
Two things I keep forgetting
-
Start a new shell before running
claude. direnv only exports into shells that enter the directory afterwards, and Claude Code reads the variable at startup. Confirm withecho $CLAUDE_CODE_PROJECT_DIR_NAMEbefore launching. -
Run
direnv allowon each machine. The.envrcis committed to the repository, but direnv records its approval per path on the local machine, so a fresh checkout on another Mac needsdirenv allowbefore it takes effect.
Note
A worktree you make yourself gets its own unapproved copy of
.envrc, so rundirenv allowthere before you startclaudein it. A worktree Claude creates and moves into mid-session is unaffected, since the session read the variable at startup.
The payoff
Sessions from the same project now live under a single, stable folder no matter which Mac I'm on or which worktree I'm in. Sharing them across machines through Dropbox works. Best of all, pointing Claude at an older conversation is easy again, now that they are all in one place instead of scattered across a dozen path-shaped directories.
-
See Name the project directory yourself in the Claude Code documentation, and the environment variables reference. ↩
Top comments (0)