Claude Code does not respect the XDG Base Directory specification
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.
I confirm read/write by ~/.config/claude/CLAUDE.md now.
1.0.29 (Claude Code)
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?
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.
Potentially there was an issue syncing well the change of configuration folder between Claude Code and the VSCode extension.
I confirm claude read from ~/.claude when 2025-06-24.
Please to be stable.
Please use xdg dir always.
@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?!
I'm using ln -s "$HOME/.config/claude/" "$HOME/.claude" for now to force the .config/ location.
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?
@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.
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:
- 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/
- Fallback to legacy: If XDG locations don't exist, check for ~/.claude.json and ~/.claude/
- 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.
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/.claudein 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"
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
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.
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.
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
Can someone clarify the distinction between
~/.claude.jsonand~/.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.jsonin the docs at all).This is all very confusing - e.g. the
CLAUDE_CONFIG_DIRenv variable mentioned above is not menitoned in the docs: docs.anthropic.com/en/docs/claude-code/settings#environment-variables
@bogini could you clarify, please?
Hi, I'd like to highlight this issue which is directly related to the topic here: https://github.com/anthropics/claude-code/issues/4739
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.
@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?
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 ~
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.
+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
vibed release notes
I think they added and then removed support because it was breaking things, see above in this thread
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.
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?
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.