
pCloud Backup choked on my dev directory. Hundreds of “doesn’t have permissions to upload this item” errors, all on .part files inside node_modules, dist, and .next build outputs. The errors weren’t really about permissions. pCloud was racing the build tools, trying to upload files that disappeared between scan and transfer.
That kicked off a rethink of how I back up my Claude Code workspace. If you use Claude Code seriously, you build up a hidden layer of state in your dev directories that no one tells you to back up. Lose your laptop and a chunk of it is gone forever.
This post is the setup I landed on after rejecting pCloud Backup, Dropbox sync, and Arq (which I didn’t want to pay for). It runs on a schedule, encrypts everything before it leaves your machine, and ignores the kind of build junk that breaks sync apps. No subscription required.
What you’re actually backing up
Most “back up your dev folder” advice assumes the folder is just code. Code goes to GitHub, you don’t need backups. Done.
But Claude Code (and the agentic tooling around it) creates a layer of state that isn’t code:
~/.claude/projects/holds every conversation transcript, project memory, and agent state. Often gigabytes after a few months. None of it is in git.- MCP server data. Most MCPs cache an OAuth token, a session, sometimes a SQLite database. Lose those and you re-authenticate and re-sync everything.
- Custom skills, slash commands, agents under
.claude/. Some are in git. Many aren’t, because they’re personal and contain workflow details you don’t want public. - Drafts and content. Markdown files for posts, newsletter outlines, notes. Mid-flight work that doesn’t belong in a Git repo yet.
- Business stuff like invoices, contracts, financial models. Not code, but lives next to code because that’s where modern work happens.
.envfiles with API keys for everything you’re building locally. Not in git for obvious reasons.- Configs and notes. Half-written PRDs, scratchpads, screenshots, exported reports.
A typical working developer’s ~/code/ tree is mostly stuff like this. Maybe a quarter is in some Git repo somewhere. The rest is irreplaceable if it’s gone.
Why sync apps fail at this
Dropbox, pCloud Drive, iCloud Drive, Google Drive all use the same architectural pattern. Watch the file system, upload changes file by file, mirror state to the cloud. That model breaks down on a working dev tree for three reasons.
Build tool churn. Run npm install and tens of thousands of files appear in node_modules/. Run a build and dist/ fills with files that get rewritten on every save. Sync apps see the churn and try to upload everything, fall behind, and watch files get deleted before they finish uploading. That’s where the error spam comes from.
No real exclusion patterns. pCloud Backup’s exclusion list is a literal list of absolute paths. There’s no way to say “exclude any folder named node_modules.” You’d have to enumerate every one, then re-enumerate every time you start a new project.
Sync isn’t backup. If a file gets corrupted on your Mac, the corruption syncs to the cloud. If you delete a file by mistake, it disappears from the cloud (most services have a 30-day trash, but that’s it). There’s no point-in-time restore, no rolling back to the version of a file from three weeks ago.
What you actually want is a backup tool. Something that takes encrypted, versioned snapshots on a schedule, with proper pattern-based exclusions, and lets you restore selectively from any point in history.
The setup: restic + rclone + your existing cloud storage
The combination I landed on:
- restic is an open source backup tool. Encrypted, deduplicated, versioned snapshots. Glob exclusions that match folder names anywhere in the tree. Has been used for years on production servers.
- rclone is a universal cloud storage CLI with native connectors for dozens of providers including pCloud, Backblaze B2, S3, Google Drive, and Dropbox.
- Your cloud storage of choice. I’m using pCloud, but the same setup works with Backblaze B2 (around $6/TB/month, often free for small datasets), Wasabi, S3, or even a local NAS.
Restic does the snapshotting, rclone bridges to the cloud. Combined, you get a backup pipeline that’s better than any commercial product I’ve tried.
The full setup, end to end
Here’s the exact walkthrough. Around 30 minutes start to finish. Adjust paths and the cloud destination to your setup.
1. Install both tools.
brew install restic rclone
2. Configure rclone for your cloud provider. For pCloud:
rclone config create pcloud pcloud
This opens your browser for OAuth. Click Allow, and rclone catches the callback and writes the token to ~/.config/rclone/rclone.conf. For Backblaze B2 use rclone config create b2 b2 account=YOUR_ID key=YOUR_KEY. The rclone docs cover every provider.
3. Generate a strong restic password and store it in macOS Keychain so the backup script doesn’t need to prompt:
RESTIC_PW=$(openssl rand -base64 32)
security add-generic-password -a "$USER" -s "restic-pcloud-password" -w "$RESTIC_PW"
Save the password somewhere safe too (1Password, Bitwarden, a printed copy in a drawer). Lose it and your backups are unrecoverable. That’s the price of client-side encryption.
4. Initialize the restic repo on your cloud:
export RESTIC_PASSWORD=$(security find-generic-password -s restic-pcloud-password -w)
export RESTIC_REPOSITORY="rclone:pcloud:restic-mac"
restic init
This creates an encrypted repo at pcloud:restic-mac/. Everything restic uploads from now on is encrypted before it leaves your machine.
5. Write your exclusion file at ~/.config/restic/excludes.txt:
# Dev artifacts
node_modules
.next
.turbo
dist
build
DerivedData
.build
# Python
.venv
venv
__pycache__
*.pyc
.pytest_cache
# Git internals (code is in git already)
.git
# macOS junk
.DS_Store
.Spotlight-V100
.Trashes
.fseventsd
# Editor
.vscode
.idea
# Logs
*.log
These are folder name patterns that match anywhere in the tree. New node_modules/ directories created next month are excluded automatically.
6. Write a wrapper script at ~/.local/bin/backup-restic.sh:
#!/bin/zsh
set -euo pipefail
LOG_DIR="$HOME/Library/Logs/restic"
mkdir -p "$LOG_DIR"
exec >> "$LOG_DIR/backup.log" 2>&1
echo "===== $(date '+%Y-%m-%d %H:%M:%S') START ====="
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
export RESTIC_REPOSITORY="rclone:pcloud:restic-mac"
export RESTIC_PASSWORD="$(security find-generic-password -s restic-pcloud-password -w)"
restic backup
"$HOME/code"
"$HOME/.claude"
"$HOME/.config"
"$HOME/Documents"
"$HOME/Desktop"
"$HOME/Pictures"
--exclude-file="$HOME/.config/restic/excludes.txt"
--exclude-caches
--one-file-system
--tag scheduled
restic forget
--keep-hourly 24
--keep-daily 14
--keep-weekly 8
--keep-monthly 12
--prune
echo "===== $(date '+%Y-%m-%d %H:%M:%S') DONE ====="
chmod +x ~/.local/bin/backup-restic.sh
The retention policy keeps 24 hourly, 14 daily, 8 weekly, and 12 monthly snapshots, around 60 versions covering a year. Restic’s deduplication means this costs almost no extra storage. Identical file blocks are stored once.
Note that the script includes ~/.claude and ~/.config so your Claude Code state and your CLI tool configs (rclone, restic, others) are part of the backup, not just your project tree.
7. Schedule it via launchd. Save this as ~/Library/LaunchAgents/com.youruser.restic-backup.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key><string>com.youruser.restic-backup</string>
<key>ProgramArguments</key>
<array>
<string>/Users/youruser/.local/bin/backup-restic.sh</string>
</array>
<key>StartInterval</key><integer>3600</integer>
<key>RunAtLoad</key><false/>
<key>LowPriorityIO</key><true/>
<key>Nice</key><integer>10</integer>
</dict>
</plist>
Load it:
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.youruser.restic-backup.plist
It runs every hour in the background, low priority so it doesn’t get in the way of actual work.
8. Verify your first snapshot:
restic snapshots
restic stats
To restore a file:
restic restore latest --target /tmp/restore --include "/Users/you/code/some-project/specific-file.md"
Restic can also mount the entire backup as a read-only filesystem (restic mount /tmp/backup), which is the easiest way to browse and grab old versions interactively. On macOS this needs macFUSE installed first.
A note on initial backup speed
pCloud can throttle uploads, sometimes dropping from a few MB/s to a few hundred KB/s after the first few minutes. For a couple of GB of initial data the upload generally finishes in well under an hour, even with throttling. After the initial sync, hourly incrementals are tiny because restic only uploads changed blocks, not changed files. A typical hourly run uploads a few megabytes and finishes inside a minute.
If you care about restore speed (large dataset, fast recovery), pair this with Time Machine to an external SSD. Restic to the cloud handles offsite disaster recovery, while Time Machine handles “I deleted that file ten minutes ago.” The combination gets you a proper 3-2-1 backup strategy: three copies, two media, one offsite.
What this protects against
- Lost or stolen laptop. Full restore from any snapshot.
- Drive failure. Same.
- Accidental delete. Restore from the most recent snapshot before the delete.
- Ransomware. Restic snapshots are immutable from the local machine’s perspective, so ransomware on your Mac can’t encrypt past versions.
- Cloud provider going down. Your data is encrypted client-side, so even if pCloud disappears, you can rclone-copy the repo to another provider and restic will still read it.
What it doesn’t protect against: the password living only in your head and your laptop’s Keychain. Print the password, put it in a sealed envelope, store it somewhere physical. The whole point of client-side encryption is that no one can decrypt your data without it, including you.
What I left behind
I uninstalled pCloud Backup from my dev directory. pCloud Drive (the file mount) still works fine for synced documents and photos, I’m just not using its backup product anymore. Same logic for Dropbox and iCloud Drive: useful for actual sync use cases, wrong tool for working dev directories.
If you’ve been wrestling with sync app errors on your dev folder, this is the way out. Total cost is zero if you have any cloud storage. Total setup time is under an hour. After that, it just runs in the background and you forget about it.

Leave a Reply