<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shin Yamamoto</title>
    <description>The latest articles on DEV Community by Shin Yamamoto (@scenee).</description>
    <link>https://dev.to/scenee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F44246%2F8cfe7d93-9147-42b9-aed7-8b8dd949c90d.jpeg</url>
      <title>DEV Community: Shin Yamamoto</title>
      <link>https://dev.to/scenee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/scenee"/>
    <language>en</language>
    <item>
      <title>Keeping Claude Code sessions for your repository in one place</title>
      <dc:creator>Shin Yamamoto</dc:creator>
      <pubDate>Sun, 06 Sep 2026 04:17:55 +0000</pubDate>
      <link>https://dev.to/scenee/keeping-claude-code-sessions-for-your-repository-in-one-place-3pj8</link>
      <guid>https://dev.to/scenee/keeping-claude-code-sessions-for-your-repository-in-one-place-3pj8</guid>
      <description>&lt;p&gt;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 &lt;em&gt;whole&lt;/em&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CLAUDE_CODE_PROJECT_DIR_NAME&lt;/code&gt; fixes this by letting you name that folder yourself. In this post, I'll show how I wired it up with &lt;a href="https://direnv.net" rel="noopener noreferrer"&gt;direnv&lt;/a&gt; so it applies automatically per repository.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CLAUDE_CODE_PROJECT_DIR_NAME&lt;/code&gt; requires Claude Code v2.1.234 or later, released on 17 August 2026.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The problem: one &lt;code&gt;&amp;lt;project&amp;gt;&lt;/code&gt; name per working directory path
&lt;/h2&gt;

&lt;p&gt;By default, transcripts live at &lt;code&gt;&amp;lt;config dir&amp;gt;/projects/&amp;lt;project&amp;gt;/&amp;lt;session-id&amp;gt;.jsonl&lt;/code&gt;, where &lt;code&gt;&amp;lt;project&amp;gt;&lt;/code&gt; is the working directory path with every non-alphanumeric character replaced by &lt;code&gt;-&lt;/code&gt;. My &lt;code&gt;projects&lt;/code&gt; folder looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-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/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 &lt;code&gt;.claude/&lt;/code&gt;, one under &lt;code&gt;.agents/&lt;/code&gt;, 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.&lt;/p&gt;

&lt;p&gt;The same mechanism splits things across machines. Because the name is derived from the absolute path, a checkout at &lt;code&gt;/Users/scenee/src/blog&lt;/code&gt; on another Mac is a different project from &lt;code&gt;/Users/scenee/Workspace/blog&lt;/code&gt;, even though it is the same repository on the same branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming the &lt;code&gt;&amp;lt;project&amp;gt;&lt;/code&gt; folder yourself
&lt;/h2&gt;

&lt;p&gt;Setting &lt;code&gt;CLAUDE_CODE_PROJECT_DIR_NAME&lt;/code&gt; pins the folder name regardless of the working directory. Claude Code then writes both transcripts and &lt;a href="https://code.claude.com/docs/en/memory#auto-memory" rel="noopener noreferrer"&gt;auto memory&lt;/a&gt; under that name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;config dir&amp;gt;/projects/&amp;lt;name&amp;gt;/&amp;lt;session-id&amp;gt;.jsonl
&amp;lt;config dir&amp;gt;/projects/&amp;lt;name&amp;gt;/memory/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are three rules to keep in mind:&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt; must be set too.&lt;/strong&gt; Claude Code ignores &lt;code&gt;CLAUDE_CODE_PROJECT_DIR_NAME&lt;/code&gt; when &lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt; is unset. Even if you are happy with the default location, you still have to export it explicitly, pointing at that same &lt;code&gt;~/.claude&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The name must be 1–64 letters, digits, hyphens or underscores&lt;/strong&gt; (and not a Windows device name like &lt;code&gt;con&lt;/code&gt;). Anything else is ignored and you get the derived name back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It has to be in the shell environment that launches &lt;code&gt;claude&lt;/code&gt;.&lt;/strong&gt; Claude Code reads it once at startup, so an &lt;code&gt;env&lt;/code&gt; block in &lt;code&gt;settings.json&lt;/code&gt; does &lt;em&gt;not&lt;/em&gt; work. I tried that first, and it silently had no effect.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Automating it with direnv
&lt;/h2&gt;

&lt;p&gt;That last rule is the awkward one. Exporting the variable by hand before every &lt;code&gt;claude&lt;/code&gt; run is easy to forget, and putting it in &lt;code&gt;~/.zshrc&lt;/code&gt; defeats the purpose because the value should differ per repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://direnv.net" rel="noopener noreferrer"&gt;direnv&lt;/a&gt; does exactly this: it loads and unloads environment variables as you enter and leave a directory. After &lt;a href="https://direnv.net/docs/installation.html" rel="noopener noreferrer"&gt;installing it&lt;/a&gt; and &lt;a href="https://direnv.net/docs/hook.html" rel="noopener noreferrer"&gt;hooking it into your shell&lt;/a&gt;, add an &lt;code&gt;.envrc&lt;/code&gt; at the root of the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CONFIG_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/.claude
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CODE_PROJECT_DIR_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;scenee-blog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create the file with &lt;code&gt;direnv edit .&lt;/code&gt; rather than your editor of choice. It opens &lt;code&gt;.envrc&lt;/code&gt; and runs &lt;code&gt;direnv allow&lt;/code&gt; for you when you save, which saves you from the "direnv: error .envrc is blocked" message.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now every session started from this repository (or from any of its worktrees) lands in the same folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scenee-blog/
├── 1f9a0c3e-....jsonl
├── 7c42b8d1-....jsonl
└── memory/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Two things I keep forgetting
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start a new shell before running &lt;code&gt;claude&lt;/code&gt;.&lt;/strong&gt; direnv only exports into shells that enter the directory afterwards, and Claude Code reads the variable at startup. Confirm with &lt;code&gt;echo $CLAUDE_CODE_PROJECT_DIR_NAME&lt;/code&gt; before launching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run &lt;code&gt;direnv allow&lt;/code&gt; on each machine.&lt;/strong&gt; The &lt;code&gt;.envrc&lt;/code&gt; is committed to the repository, but direnv records its approval per path on the local machine, so a fresh checkout on another Mac needs &lt;code&gt;direnv allow&lt;/code&gt; before it takes effect.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A worktree you make yourself gets its own unapproved copy of &lt;code&gt;.envrc&lt;/code&gt;, so run &lt;code&gt;direnv allow&lt;/code&gt; there before you start &lt;code&gt;claude&lt;/code&gt; in it. &lt;strong&gt;A worktree Claude creates and moves into mid-session is unaffected&lt;/strong&gt;, since the session read the variable at startup.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The payoff
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;See &lt;a href="https://code.claude.com/docs/en/sessions#name-the-project-directory-yourself" rel="noopener noreferrer"&gt;Name the project directory yourself&lt;/a&gt; in the Claude Code documentation, and the &lt;a href="https://code.claude.com/docs/en/env-vars" rel="noopener noreferrer"&gt;environment variables reference&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>claude</category>
      <category>claudecode</category>
      <category>productivity</category>
      <category>direnv</category>
    </item>
  </channel>
</rss>
