Making a quick Nix home-manager flake to manage Claude Code config
# 30 Apr 2025 by SeanClaude Code has a bug where it can’t see symlinked files, which
unfortunately means if you’re trying to manage things like user commands
or memory, it never
sees that setup. It’s also kind of a pain in the ass that the ~/.claude.json
file where you’d define MCP servers needs
to be writable by Claude…
So, I wrote a nix flake for home-manager to help manage these issues.
This is not a great flake tbh, because it does almost no deterministic configuration, and instead just abuses activation scripts to copy all the config files into place, rather than putting them in the Nix store and symlinking them in like Nix usually does.
The options are:
package
, defaults to your system’spkgs.claude-code
. You can pass any custom package in, ornull
if you want or need to manage the install externallymemory.text
ormemory.source
, which will write content to~/.claude/CLAUDE.md
commandsDir
andcommands
, which take either a path, or list of paths, of commands to put into~/.claude/commands/
. You can use both together, but any filenames that recur betweencommandsDir
and explicitcommands
will get the explicitcommands
filepreClean
, if set totrue
, will remove~/.claude/CLAUDE.md
or anything in~/.claude/commands/
if they’re present before the activation script starts moving files in. This ensures we avoid duplicates, and if you remove a file between runs, it will get removed.mcpServers
, accepts an attrset, which will be transformed to JSON, and then merged into~/.claude.json
’smcpServers
key, while leaving the file otherwise availabel for Claude to manage itself
Here’s an example setup:
# Inside your home-manager config...
imports = [
inputs.claude-code.nixosModules.default
];
# This requires home-manager as a NixOS module
programs.claude-code = {
enable = true;
package = my-custom-package;
preClean = true;
commandsDir = ./claude-commands;
commands = [
./extra-claude-command.md
];
memory.text = ''
# Coding style
- Use the best Ruby style possible, following all Rubocop settings from the project's config
- Always practice TDD, using the red/green/refactor pattern
- DO NOT COMMENT CODE
'';
mcpServers = {
github = {
command = "docker";
args = [
"run"
"-i"
"--rm"
"-e"
"GITHUB_PERSONAL_ACCESS_TOKEN"
"ghcr.io/github/github-mcp-server"
];
};
};
};
Future
I’m sure Anthropic will fix their shit and this flake can get a lot leaner and use actual nix patterns for file
management. But, when that happens, the external API of this module is pretty much good to go. The only thing I’d need
to deprecated is preClean
, which defaults to false
anyways. Plus, it’s not like I’m shipping this package to tons of
people and don’t control my own deprecation cycle :sweat_smile:
.