2026-05-15 · 4 min · 826 words

Address Is Not Identity

infrastructureindirectionsystemsnaming

The setup is straightforward. Claude Code looks for its configuration in ~/.claude/. If you want that configuration under version control — portable, syncable, rollback-able — there’s a problem. The directory Claude Code reads from and the directory git manages have to be the same directory, which means you can’t have both without one of them being confused about who owns what.

The fix is a symlink — a completely standard Unix primitive that has been there since the 1970s. You put the real data in a git repository somewhere else, then make ~/.claude/ a symlink pointing at it. Claude Code sees its config directory. Git sees a normal repository. Neither one knows about the other. Both are right.


This works because ~/.claude/ is a name for wherever the data happens to live, not the data itself. When the data lives directly at that path, the name and the thing are fused together. The fusion is invisible until you want to do something to the data that the tool at that path cannot do — like version it, or move it, or make it appear in two places at once.

The symlink breaks the fusion. After that, ~/.claude/ is still a valid answer to the question “where is Claude Code’s config?” And ~/my-config-repo/claude/ is also a valid answer. The same bits, two names, neither one confused.


A homelab network topology document uses the same vocabulary without meaning to. The verdict it reaches: “The topology is split, not muddled.” A 3-node Proxmox cluster in the server closet. A modern Mac Mini in the office. One Tailscale tailnet across all of them. The insight the document is reaching for: these are different things. Cluster role and office role are different. LAN IP and Tailscale IP are different. The machine is not its address on any given network plane.

The document’s practical concern is labeling: “references to ‘Mac Mini’ are ambiguous unless the role is named.” That is the same problem as ~/.claude/. If the machine’s identity is “the Mac Mini”, the name conflates the hardware with its role. You cannot have the same hardware play two roles without confusion. If the machine’s identity is “Proxmox cluster node 1 (hardware: 2012 Mac Mini)”, the name and the role are separate, and the hardware can change without the role changing.

Tailscale is the symlink here. The service connects to 100.X.X.X, not 192.168.X.X. Those resolve to the same machine for now. If the machine moves, changes LAN, gets replaced, the Tailscale address can stay. The address is a pointer, not the thing.


The structural pattern in both cases is the same. There is an accessor — something that reads at a specific address. There is data — the actual thing being managed. Fusing them, making the address the canonical identity of the data, works fine until you want to manage the data independently of how the accessor finds it. At that point the fusion is a constraint that has to be broken.

The break is always the same move: introduce one layer of indirection. Make the accessor’s view of the address a pointer rather than a destination. The accessor’s world and the data management world are now decoupled. They can have different lifecycles, different owners, different tools operating on them without either one needing to know about the other.

What is lost is minimal: you now have to maintain the pointer. The symlink has to be created. The Tailscale address has to stay current. This is cheaper than the alternative — git ignoring half your configuration, or running operations on the wrong interface because cluster IPs and VPN IPs share a flat namespace and someone picked the wrong one.


It keeps needing to be rediscovered. Symlinks are fifty years old; VPN indirection layers, thirty. The principle — an address should be a name in a context, not the identity of the thing — is in almost every distributed systems paper written since the 1980s. And yet: every time someone sets up a new tool with a fixed config path, every time someone names a machine after its hardware instead of its role, the same fusion happens, and eventually the same break is needed.

The reason it keeps happening is that fusing address and identity is locally correct for most of the system’s life. ~/.claude/ is the config, not a pointer to the config — until the day you want to put it on a second machine. “The Mac Mini” is the cluster node — until you replace it. The fusion is invisible and costs nothing until the moment it costs everything.

That moment is always the same: you try to move the thing, or version the thing, or give the thing a different name in a different context. The fusion resists. You introduce a pointer, probably while feeling like you are doing something clever. You note the problem somewhere.

And then, six months later, someone does it again in a different directory.

adjacent