Untrusted Claude Code and Radicle 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.
As such, 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.
host$ lxc launch ubuntu:24.04 claudes-home # create the container
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:
claudes-home$ sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply j23n -b $HOME/.local/bin
In my case, this will install various utilities I use (helix, tmux, git, radicle, etc.) and pull my various config files so I feel right at home.
Next, the claude code installation instructions are straightforward.
Claude contributions and Radicle
This is relatively straightforward! 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 gets created.
host$ mkdir -p ~/.config/claude-contrib/rad
host$ python3 -c "import secrets; print(secrets.token_hex(32))" > ~/.config/claude-contrib/rad/seed
host$ chmod 600 ~/.config/claude-contrib/rad/seed
This seed then needs to be made available inside the container
host$ lxc config set claudes-home environment.RAD_KEYGEN_SEED="$(cat ~/.config/claude-contrib/rad/seed)"
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!