ct-homelab part 3: claude code on a raspberry pi 5
Greetings, fellow silicon soldiers. Today we're installing Claude Code on the Pi we set up in part 1 so it runs as a persistent session you can SSH into from anywhere. Your dev environment, always on, always where you left it. This is part 3 of the CTLab Homelab series.
Again, these are detailed instructions on how to do this for the wannabe wizards. If you want to be a lame voodoo programmer you can also just skip to the warez section and use the bootstrap to get this all running immediately.
Most of this you are going to be familiar with if you went through the Getting Started with Claude Code article, but there's a few more nifty things for running on a pi.
Why Run Claude Code on the Pi
It's Thursday evening. I'm watching Jeopardy, keeping track of my Coryat score when I have this brilliant idea for a new blog post. Or maybe it was something I remembered I needed to fix. Or was it a calendar entry that needed updating? Whatever. I realized that I have to go ALL THE WAY DOWNSTAIRS to my computer running Claude to update whatever it was I was updating.
If you know me in real life, you know that I am very lazy. I do not want to go up and down the stairs. I am getting old. This is not enjoyable for me.
I need access to Claude from my phone1, from my upstairs laptop, from any place I have a terminal. It is just much more convenient.
Running Claude Code on your local machine means your session dies when you close the terminal. Running it on the Pi means it keeps going. SSH in from your laptop, your phone, or a machine at work and you get the same session, same context, and same working directory. Pair it with tmux and you have a persistent AI-assisted dev environment that survives disconnects.
The Pi 5 has enough headroom for this alongside the rest of the stack. Claude Code itself is lightweight. The API calls do the heavy lifting, not the local process.
Setup Steps
- Install nvm + Node.js (LTS)
- Install Claude Code (
npm install -g @anthropic-ai/claude-code) - Configure API key
- Install tmux
- Set up a persistent tmux session
- Test SSH + attach workflow from another machine
- Optional: add tmux auto-attach to .zshrc
Install nvm + Node.js
Everything from here on happens on the Pi. SSH in first if you are not already there:
ssh raspberrypi
Claude Code runs on Node.js. The easiest way to manage Node versions on Linux is nvm. It installs Node in your home directory so you never need sudo for global packages.
Install nvm:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash
The version above may be out of date by the time you read this. Check the latest:
curl -s https://api.github.com/repos/nvm-sh/nvm/releases/latest | grep '"tag_name"' | cut -d'"' -f4
The installer adds the nvm initialization lines to your .zshrc automatically. Reload your shell to pick them up:
source ~/.zshrc
Install the current LTS release and set it as default:
nvm install --lts
Verify:
node --version
npm --version
You should see version numbers for both. If nvm: command not found appears after reloading, check that the installer added the init block to ~/.zshrc and not ~/.bashrc.
Install Claude Code
With Node in place, install Claude Code globally:
npm install -g @anthropic-ai/claude-code
Verify the install:
claude --version
Configure API Key
You need an Anthropic API key. If you do not have one yet, go read the Getting Started with Claude Code post and come back when you are done. I will wait.
If you already have one from your other machine, just run claude on the Pi. It will ask for the key on first launch and store it in ~/.claude.
Pull Your Config from GitHub
Your CLAUDE.md files and context documents are sitting in your claude-config repo from the Getting Started post. Let's get them on the Pi.
The claude auth step already created ~/.claude/ with your credentials in it. We need to back those up, clone your repo into that directory, then put the credentials back.
Back up your credentials first:
cp ~/.claude/.credentials.json ~/claude-credentials.bak
Remove the directory so git can clone into it cleanly:
rm -rf ~/.claude
Clone your config repo:
git clone https://YOUR_USERNAME@github.com/YOUR_USERNAME/claude-config.git ~/.claude
Git will prompt for your GitHub password, use the Personal Access Token you created in the Getting Started post, not your GitHub account password.
Restore your credentials:
cp ~/claude-credentials.bak ~/.claude/.credentials.json
rm ~/claude-credentials.bak
Your CLAUDE.md, context files, and memory are now on the Pi. Claude Code will pick them up automatically on the next run.
If you are using the ct-homelab repo, restore_claude.sh does all of the above interactively, prompts for your username and PAT so nothing ends up in shell history.
Update your CLAUDE.md for this machine.
Your config was written on another machine, if it describes your environment (OS, shell, paths), add a note for the Pi so Claude knows where it is. For example, if your CLAUDE.md says WSL2/zsh, add a line like main-laptop: WSL2/zsh and a new one for the Pi: homelab-pi: Raspberry Pi OS/zsh, Node via nvm, working in /home/yourname. You can also just tell Claude to do this when you first run it on the Pi, it will update its own config.
Clone or copy over any projects Claude needs.
If your contexts reference local project paths (~/projects/conspicuoustechnologist, ~/blog-writings, etc.), clone those repos on the Pi too, or rsync them over if they are not in version control. If rsyncing, don't exclude .git, without it you lose history and any per-repo git config you have set. Claude can't work on files that aren't there.
You will also need to re-auth GitHub on the Pi separately, run gh auth login and follow the prompts. Your credentials from your other machine do not transfer.
Remember that any deployment functions in your .zshrc might also need updating. For me, ctpi from part 1 has been renamed to ctdev, and what was a remote host is now just a local directory. If you built your own version, the generic form is:
ctdev() {
( cd /path/to/your/site && \
your-build-command && \
rsync -av --delete your-output-dir/ $MAIN_SITE_DIR/ && \
docker restart nginx )
}
Install dev tools for your projects.
The projects you cloned have build tool dependencies that won't install themselves. Node is already there from nvm, but anything else needs manual setup before Claude can actually work on your code. Remember other things like Hugo, Python, or other utilities in your dev workflow.
Install tmux
screen, the GNU-era terminal multiplexer that predates tmux by about a decade, this is the same idea, just less awful to configure.tmux is a terminal multiplexer. It keeps sessions alive after you disconnect, lets you split the terminal into panes, and is the piece that makes the persistent Claude workflow actually work.
sudo apt install -y tmux
Set Up a Persistent Session
Create a named session in the background:
tmux new-session -d -s claude
The -d flag starts it detached (no terminal attached yet). The -s claude names it. You can use any name. claude is used here because that is what you will be attaching to.
Verify it is running:
tmux ls
You should see claude: 1 windows. This session persists until the Pi reboots. To start Claude Code inside it, attach and run it:
tmux attach -t claude
claude
Detach without stopping anything: Ctrl+b, then d. The session keeps running. Claude keeps running. Come back to it anytime. This also means if you get disconnected, the session survives. Just SSH back in and attach.
Test SSH + Attach from Another Machine
From your laptop (or any machine with SSH access to the Pi):
ssh raspberrypi
Once connected, check that the session is there:
tmux ls
Attach:
tmux attach -t claude
You should land directly in your Claude Code session, same context, same working directory as when you left it. Detach again with Ctrl+b d and your SSH session ends cleanly.
Auto-Attach on SSH (optional)
If you want to land directly in the tmux session every time you SSH into the Pi, add this to the bottom of ~/.zshrc:
if [ -z "$TMUX" ] && [ -n "$SSH_CONNECTION" ]; then
tmux attach -t claude 2>/dev/null || tmux new-session -s claude
fi
The $SSH_CONNECTION check limits this to SSH logins only. It will not fire if you open a local terminal on the Pi directly. If the claude session exists, you attach to it. If not (e.g. after a reboot), a new one is created.
Reload your shell to apply:
source ~/.zshrc
Test it by exiting and SSHing back in. You should drop straight into tmux.