Untrusted Claude Code and radicle.xyz setup
Written on by j23n in privacy ai chezmoi radicleClaude confinement
I don't trust Claude Code, and especially myself, to not inadvertently upload any or all of my private data to Anthropic's servers and thus be immortalized in logs.
That's why Claude lives in a dedicated lxc container on my machine. If need be, I can mount shared volumes, or forward ports to/from the host, but I find that's rarely necessary.
Here's how I've set things up.
j23n@host$ lxc launch ubuntu:24.04 claudes-home # create the container
j23n@host$ lxc exec claudes-home /bin/bash # get a shell inside the container
I use chezmoi to manage my dotfiles, so getting set up on a new machine is trivial:
claude@claudes-home$ sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply j23n -b $HOME/.local/bin
This will install utilities I use frequently (helix, tmux, git, radicle, etc.) and pull in my various config files so I feel right at home.
Next, the claude code installation instructions are straightforward.
Claude contributions and radicle
I treat Claude as a contributor to my repositories. It looks at open issues, works on solutions, submits PRs, and I review and merge.
To do so, Claude needs it's own radicle DID inside its container. Radicle makes this easy by accepting a RAD_KEYGEN_SEED environment variable, which I can pass in when a container is created.
j23n@host$ mkdir -p ~/.config/claude-contrib/rad
j23n@host$ python3 -c "import secrets; print(secrets.token_hex(32))" > ~/.config/claude-contrib/rad/seed
j23n@host$ chmod 600 ~/.config/claude-contrib/rad/seed
j23n@host$ lxc config set claudes-home environment.RAD_KEYGEN_SEED="$(cat ~/.config/claude-contrib/rad/seed)"
j23n@host$ lxc config set claudes-home environment.RAD_SEED_REPOS="rad:z31hE1wco9132nedsomethingrandom"
The environment variable persists through restarts and is available for any process started using lxc exec.
My dotfiles include a radicle guide for Claude to properly understand delegates, patches, seeding, etc.
Workflow
When I want Claude to work on something, I tell claude to clone a given repository (say, rad:zVdCS3rdBtnLLui7jaHTf4X9j6FD).
It can look at issues or I can assign issues directly to Claude as it has its own DID, an it can submit patches. Since it's not a delegate of any of my repositories, only I can merge patches, so changes always go through a PR process.
This works surprisingly well for me!