claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

Claude Code does not respect the XDG Base Directory specification

Open jennifgcrl opened this issue 8 months ago • 36 comments

Environment

  • Claude CLI version: all
  • Operating System: linux
  • Terminal: all

Bug Description

Claude Code writes its cache data and configs to ~/.claude.json and ~/.claude instead of following the XDG Base Directory specification. It looks like you can kinda get claude code to put some file in CLAUDE_CONFIG_DIR but the default behavior without configuration should be to follow the XDG specification.

Steps to Reproduce

install & run claude code

Expected Behavior

follows xdg specification

Actual Behavior

creates ~/.claude.json and ~/.claude directory

Additional Context

Here's what Claude Code has to say on why Claude Code should follow the XDG spec:

User Environment Respect

Following XDG standards ensures Claude Code respects users' configured directory preferences rather than cluttering their home directory with dot-files. Users who have customized XDG_CONFIG_HOME, XDG_DATA_HOME, and XDG_CACHE_HOME expect all well-behaved applications to honor these settings.

System Administrator Compliance

In enterprise environments, system administrators often configure XDG directories to point to network storage, encrypted volumes, or specific partitions. Non-compliant applications break these carefully designed setups and create security or storage policy violations.

Container and Sandboxing Compatibility

Modern deployment patterns (containers, Flatpak, snap packages) rely heavily on XDG compliance for proper isolation and file system mapping. Non-compliant applications often fail or behave unpredictably in these environments.

Cross-Platform Consistency

While XDG originated on Linux, similar concepts exist across platforms (Windows Known Folders, macOS Application Support). Following XDG creates a foundation for consistent cross-platform behavior.

Backup and Migration Simplification

Users expect configuration, data, and cache to be cleanly separated. XDG compliance makes it trivial for users to backup only configuration and data while excluding cache, or to migrate settings between machines.

Given Claude Code's role as a developer tool that likely stores configuration, project data, and cache files, XDG compliance is essential for professional adoption and integration into existing development workflows.

jennifgcrl avatar May 31 '25 06:05 jennifgcrl

I confirm read/write by ~/.config/claude/CLAUDE.md now.

1.0.29 (Claude Code)

ncaq avatar Jun 19 '25 11:06 ncaq

Currently, I have configuration files placed only in the following directory:

~/.claude/CLAUDE.md
~/.claude/settings.json
・
・

I am using the following version of Claude Code:

% claude --version
1.0.31 (Claude Code)

When I check /permission, it appears that both the allow and deny settings are still active. Also, my CLAUDE.md file seems to be loading properly.

My question is as follows: Regarding the XDG path migration, do we users need to perform any migration work or configuration changes on our end?

umiyosh avatar Jun 21 '25 07:06 umiyosh

Looks like someone tried to fix this, but somehow the fix is partial and creates lots of issues because there wasn't a migration of existing data from one folder (~/.claude) to another (~/.config/claude).

See https://github.com/anthropics/claude-code/issues/2299#issuecomment-2993498737 for more details.

douglascamata avatar Jun 21 '25 10:06 douglascamata

Potentially there was an issue syncing well the change of configuration folder between Claude Code and the VSCode extension.

douglascamata avatar Jun 21 '25 10:06 douglascamata

I confirm claude read from ~/.claude when 2025-06-24. Please to be stable. Please use xdg dir always.

ncaq avatar Jun 24 '25 01:06 ncaq

@ncaq they were reading from ‘.config/claude’ on version 1.0.31, which was the last one I tested. Did they revert it and did a breaking change… again?!

douglascamata avatar Jun 24 '25 10:06 douglascamata

I'm using ln -s "$HOME/.config/claude/" "$HOME/.claude" for now to force the .config/ location.

JacobHayes avatar Jun 24 '25 15:06 JacobHayes

A fresh new install with claude code v1.0.34, and claude code creates the data under ~/.claude! What is happening? Shouldn't it create new directory under ~/.config/claude and ~/.local/share/claude for any new installation?

milanglacier avatar Jun 25 '25 03:06 milanglacier

@chrislloyd @wolffiex: hey folks, do you think we can this super messy situation in a consistent and stable way?

As @milanglacier reported, now on v1.0.34 my Claude Code puts files in ~/.claude, while I had already migrated everything to ~/.config/claude on v1.0.31.

It's like every other day we have a breaking change in the folder that Claude Code stores important history and configuration, without any automatic migration of one folder to the other... this is very bad for all the users. For the 2nd time, suddenly all our settings and customizations disappear and we need to figure out where they should be.

douglascamata avatar Jun 25 '25 08:06 douglascamata

Yeah I'm guessing they made the change and then reverted it. Anyway, Claude says:

I think my developers could implement a simple migration approach without breaking changes:

Proposed approach:

  1. Check XDG first: Have me look for config in $XDG_CONFIG_HOME/claude/ and $XDG_CACHE_HOME/claude/ and if they don't exist ~/.config/claude/ and ~/.cache/claude/
  2. Fallback to legacy: If XDG locations don't exist, check for ~/.claude.json and ~/.claude/
  3. Migrate on write: When I save config/cache, always write to XDG locations. If legacy files exist, copy them over once and clean up the originals.

This would:

  • ✅ Make new installations XDG-compliant by default
  • ✅ Seamlessly migrate existing users on their next config update
  • ✅ Avoid any breaking changes or complex deprecation timelines
  • ✅ Respect XDG_CONFIG_HOME and XDG_CACHE_HOME environment variables

The implementation logic would be straightforward:

  if xdg_files_exist():
      use_xdg()
  elif legacy_files_exist():
      migrate_to_xdg_and_use()
  else:
      create_xdg()

Would this approach work for you? Happy to help my developers think through any implementation details if needed.

jennifgcrl avatar Jun 25 '25 09:06 jennifgcrl

The only way I've been able to solve this consistently is by explicitly setting CLAUDE_CONFIG_DIR which seems to take precedence over everything else:

Setting CLAUDE_CONFIG_DIR=$HOME/.claude in my shell seems to return the old behavior. I ended up adding this as a fish alias:

alias claude="env CLAUDE_CONFIG_DIR=$HOME/.claude $HOME/.claude/local/claude"

joshuadavidthomas avatar Jun 25 '25 14:06 joshuadavidthomas

it's a bit of a nitpick, but it would be nice if instead of $XDG_CONFIG_HOME the creds would be stored in the keyring or at least a different directory ($XDG_RUNTIME_DIR?)

pushing an api key to a config repo could be a disaster

anuramat avatar Jun 25 '25 15:06 anuramat

Hi folks, I shipped (in 1.0.28) and unshipped (in 1.0.31) partial XDG support. I hear all the frustration here and I’m sorry for the thrash.

I incorrectly thought it would be a straightforward feature but didn’t anticipate migrating existing ~/.claude config directories. I unshipped when we started getting reports of re-auths. This was understandably inconvenient for folks who ran the affected versions. I made the unship call because a.) there was minimal data loss (as existing ~/.claude directories remained), and b.) the implementation didn’t properly adhere to the XDG spec (by putting session data into the config dir) and would probably have required another migration. We're also going to invest in some better tests to catch future upgrades breaking things like this.

Needless to say, XDG support is on our radar but we want to do it right. In the meantime, I suggest using the workarounds from @JacobHayes or @joshuadavidthomas if you want to maintain the behavior from 1.0.29-31.

chrislloyd avatar Jun 25 '25 17:06 chrislloyd

I've ended up getting my system in a complete mess trying to keep up with these changes. I can work around most of it but one big issue I had was claude code reinitialising my ~/.claude.json.

You only realise how vital this file is when it's already too late. None of the documentation mentions this file even though it's the place where mcp servers are configured at the project and user level.

TC72 avatar Jun 26 '25 09:06 TC72

Can someone clarify the distinction between ~/.claude.json and ~/.claude/? e.g. why isn't the former in the latter folder? What is the intuition for what goes where? Maybe @chrislloyd you could clarify this?

The docs are not helpful (did not find any mention of .claude.json in the docs at all).

This is all very confusing - e.g. the CLAUDE_CONFIG_DIR env variable mentioned above is not menitoned in the docs: https://docs.anthropic.com/en/docs/claude-code/settings#environment-variables

gshpychka avatar Jun 30 '25 18:06 gshpychka

Can someone clarify the distinction between ~/.claude.json and ~/.claude/? e.g. why isn't the former in the latter folder? What is the intuition for what goes where? Maybe @chrislloyd you could clarify this?

The docs are not helpful (did not find any mention of .claude.json in the docs at all).

This is all very confusing - e.g. the CLAUDE_CONFIG_DIR env variable mentioned above is not menitoned in the docs: docs.anthropic.com/en/docs/claude-code/settings#environment-variables

@bogini could you clarify, please?

gshpychka avatar Jul 23 '25 11:07 gshpychka

Hi, I'd like to highlight this issue which is directly related to the topic here: https://github.com/anthropics/claude-code/issues/4739

bijela-gora avatar Aug 01 '25 15:08 bijela-gora

Real-World Impact: 3.8MB Configuration File Demonstrates Urgent Need for XDG Compliance

I can provide concrete evidence of why XDG compliance is critical for Claude Code usability:

Current Disaster: Single Monolithic File

  • File: ~/.claude.json
  • Size: 3.8MB, 3,658 lines
  • Claude Code Version: 1.0.110
  • Platform: macOS

What's Inside This Monster File

  • 699 chat messages from 20+ different projects
  • Complete conversation histories for every directory ever used with Claude Code
  • Session metrics (costs, tokens, API calls) for every interaction
  • Project state data for each directory
  • Actual configuration: ~50 lines buried at the very end

Performance Impact

  • 3.8MB parsed on every startup - noticeable delay
  • Growing linearly with usage - will only get worse
  • Approaching 8MB corruption threshold confirmed in #2810

This Proves XDG Compliance is Essential

Your XDG specification request is not just about "clean directories" - it's about preventing Claude Code from becoming unusable for active developers.

Required XDG Structure

# Configuration (XDG_CONFIG_HOME)
~/.config/claude/config.json          # MCP servers, global settings only

# Data (XDG_DATA_HOME)
~/.local/share/claude/projects/       # Project-specific data
~/project/.claude/history/            # Chat histories per project

# Cache (XDG_CACHE_HOME)
~/.cache/claude/                      # Temporary files, sessions

Immediate Risk

At 3.8MB, I'm approaching the corruption threshold that affects multiple users. Every active Claude Code user will 
eventually hit this problem.

XDG compliance isn't just about standards - it's about basic usability for anyone who uses Claude Code regularly.

binarybcc avatar Sep 10 '25 16:09 binarybcc

@chrislloyd Any updates on the timeline for XDG compliance?

You have gone too far Claude. You have ignored XDG, you have inconsistent documentation, you have taken our jobs. All that I could forgive. But Claude... no man page?

sebastiancarlos avatar Oct 05 '25 17:10 sebastiancarlos

can we at least put the auth file in a directory, even if it's not XDG compliant? mounting to containers is a giant pain as a result of claude.json sitting in ~

parkan avatar Oct 07 '25 15:10 parkan

This is so annoying, and the ~/.claude.json causes config issues for me regularly with the ~/.claude/settings.json file, especially when I have claude even create a new agent, the agent works for that session, creates in ~/.claude/agents/ dir, and then on next Claude Code restart it no longer finds the agent. The entire CC config setup is broken right now IMO.

rsnodgrass avatar Oct 16 '25 15:10 rsnodgrass

+1 for making Claude XDG compliant. It's now a great CLI so it makes sense to start following good CLI hygiene.

PS: Weirdly, this changelog says there is support since version 1.0 but it is not working for me... https://github.com/anthropics/claude-code/blob/b4b858a11500393159bcdd64752be0e4f64864d5/CHANGELOG.md?plain=1#L509

kulesh avatar Oct 17 '25 20:10 kulesh

vibed release notes

lucaspar avatar Oct 17 '25 22:10 lucaspar

I think they added and then removed support because it was breaking things, see above in this thread

jennifgcrl avatar Oct 17 '25 22:10 jennifgcrl

While I agree some things would be simpler by using XDG_CONFIG_HOME, I'm not sure I've seen a single user-facing problem in this thread that can't be solved in 2 minutes or less by throwing more symlinks at it. If you feel blocked on this, grab some symlinks and shoveling.

brandon-fryslie avatar Oct 23 '25 01:10 brandon-fryslie

HOME, I'm not sure I've seen a single user-facing problem in this thread that can't be solved in 2 minutes or less by throwing more symlinks at it.

This is a STANDARD, though a non-obliged standard. If no product team care about the standard and shit on users like "you can use a symlink or whatever method xxx to DIY”… Guess why we need a STANDARD?

milanglacier avatar Oct 23 '25 03:10 milanglacier

Dupe of #2350? I know this one is older, but #2350 also has a proposal of how to organize it with the XDG spec in mind.

tingerrr avatar Nov 05 '25 09:11 tingerrr