vps-cpu Quickstart — CPU-only DepthFusion + research tools
Note: This doc describes V1 behavior. V2 server setup is documented in
docs/v2/admin-runbooks.md(§1 Initial Server Setup + First-User Enrollment). The V2 installer adds OIDC configuration, database initialization, and TLS setup steps not covered here. If you are running thev2-enterprisebranch, refer to the V2 admin runbooks instead.Target: current Hetzner VPS or any CPU-only Linux host Time: ~10 minutes hands-on Produces: working DepthFusion in
vps-cpumode + weekly regression monitor + initial prompt corpus Estimated first-run size on disk: ~150 MB (Python deps) + corpus growth
This is the complete path for running DepthFusion on a CPU-only host with the research tooling active. At the end you'll have:
- DepthFusion library installed with
[vps-cpu]extras (Haiku reranker, ChromaDB Tier 2) - Claude Code MCP integration wired
- Weekly autonomous regression monitor scheduled
- Initial session-history corpus mined (first baseline for eval)
0. Prerequisites
# Python 3.11 or 3.12 — that is the whole tested range (>=3.11,<3.13,
# S-316). 3.13+ is refused at install time by `requires-python` and at
# startup by the runtime guard, so do not reach for the newest interpreter.
# Ubuntu 24.04 ships 3.12 as default, which is exactly what you want.
python3 --version
# Build tools + venv module. On fresh Ubuntu 24.04 the venv module is
# not pre-installed — this is the most common first-install gotcha.
sudo apt update
sudo apt install -y python3-full python3-venv build-essential python3-dev
# systemd --user — needed for the weekly regression monitor (§4).
# On most Hetzner boxes this works out of the box. If it reports
# "No session" or similar:
systemctl --user status || sudo loginctl enable-linger $USER
Why
python3-full? On Debian/Ubuntu,python3is a minimal bootstrap;python3-fullbrings invenv,pip, and the standard library components DepthFusion's dependencies need to compile.build-essential+python3-devcover the native-compile step forchromadb(which pulls inhnswlib).
You'll also need a DepthFusion API key:
# Check: is DEPTHFUSION_API_KEY already set anywhere?
grep DEPTHFUSION_API_KEY ~/.claude/depthfusion.env 2>/dev/null || echo "not set"
If not set, create a key from the Anthropic console and have it
ready for step 2. Important: use DEPTHFUSION_API_KEY, NOT
ANTHROPIC_API_KEY — see the billing-safety note in §2.
1. Clone, create a venv, and install
On modern Ubuntu (24.04+) pip refuses system-wide installs by design (PEP 668). You must install DepthFusion into a virtualenv. This section walks through the full pattern.
1a. Clone the repo
# Pick a stable location you won't delete
git clone https://github.com/gregdigittal/depthfusion.git ~/projects/depthfusion
cd ~/projects/depthfusion
1b. Create and activate a virtualenv
# Pin an explicit interpreter (3.11 or 3.12 — 3.13+ untested, S-316).
# On Ubuntu 24.04 this is 3.12.
python3.12 -m venv ~/venvs/depthfusion
source ~/venvs/depthfusion/bin/activate
Your prompt should now show (depthfusion) at the front:
(depthfusion) gregmorris@host:~/projects/depthfusion$
If it doesn't, source failed — check that ~/venvs/depthfusion/bin/activate
exists and run the source line again.
1c. Install DepthFusion with vps-cpu extras
# Upgrade pip first — venvs ship with a several-year-old pip
pip install --upgrade pip
# Install the library. The quotes around '.[vps-cpu]' are required —
# most shells treat [brackets] as glob characters.
pip install -e '.[vps-cpu]'
Takes 2-4 minutes; anthropic and chromadb are the big deps.
Verify:
python3 -c "import depthfusion; print('ok')"
# -> ok
1d. Make the venv auto-activate in new shells
Otherwise every ssh or tmux new-session drops you back to the
system Python and DepthFusion won't import. This block is idempotent
— safe to run multiple times.
grep -q "# depthfusion venv auto-activate" ~/.bashrc || cat >> ~/.bashrc <<'EOF'
# depthfusion venv auto-activate
if [ -z "$VIRTUAL_ENV" ] && [ -f "$HOME/venvs/depthfusion/bin/activate" ]; then
source "$HOME/venvs/depthfusion/bin/activate"
fi
# depthfusion PS1 prefix enforcement — robust against whatever the
# activate script does or doesn't do with PS1 (Ubuntu 24.04's Python
# 3.12 venv sometimes fails to apply the (depthfusion) prompt prefix).
if [ -n "$VIRTUAL_ENV" ] && [[ "$PS1" != *"(depthfusion)"* ]]; then
PS1="(depthfusion) $PS1"
fi
EOF
⚠ DO NOT
source ~/.bashrcwhile the venv is already active. Ubuntu's default.bashrcunconditionally reassignsPS1, which leaves your shell in a half-activated state ($VIRTUAL_ENVset but$PATHclobbered). If you want to test the auto-activate block without logging out, usedeactivate; exec bash— that replaces the current shell with a fresh one that starts with empty state and re-runs.bashrccleanly.
Test in a fresh shell:
exec bash # replace current shell; picks up .bashrc fresh
which python3 # should print ~/venvs/depthfusion/bin/python3
echo "$VIRTUAL_ENV" # should print /home/$USER/venvs/depthfusion
Prompt should show (depthfusion) …$. If it doesn't, the PS1
enforcement line isn't firing — check declare -p PS1 output for
clues and see the §1d troubleshooting in
../runbooks/gpu-vps-migration.md
(applies identically to vps-cpu installs).
From here on, every new SSH session auto-activates the venv.
2. Run the installer and add credentials
The installer merges with any existing ~/.claude/depthfusion.env —
credentials you add before or after are preserved across re-installs.
2a. Run the installer
python3 -m depthfusion.install.install --mode=vps-cpu
The installer:
- Writes mode-specific defaults to ~/.claude/depthfusion.env
- Registers PreCompact + PostCompact hooks in ~/.claude/settings.json
- Registers the DepthFusion MCP server with Claude Code via claude mcp add (if the claude CLI is present)
- Warns that Haiku is disabled until you set the API key (next step)
2b. Add your credentials to the env file
Both DEPTHFUSION_API_KEY and DEPTHFUSION_HAIKU_ENABLED=true are
required for Haiku features to activate — the key alone isn't enough.
You can do this before or after the installer runs; re-running the
installer will not wipe these lines.
# Replace with your real key from https://console.anthropic.com/settings/keys
cat >> ~/.claude/depthfusion.env <<'EOF'
DEPTHFUSION_API_KEY=sk-ant-api03-your-real-key-here
DEPTHFUSION_HAIKU_ENABLED=true
EOF
chmod 600 ~/.claude/depthfusion.env # file now contains a secret
# Sanity-check both made it in
grep -E "^(DEPTHFUSION_API_KEY|DEPTHFUSION_HAIKU_ENABLED)=" ~/.claude/depthfusion.env
⚠ Billing safety — use
DEPTHFUSION_API_KEY, NOTANTHROPIC_API_KEY. Claude Code readsANTHROPIC_API_KEYas its own auth credential and will switch your Pro/Max subscription to pay-per-token API billing for all Claude Code usage — not just DepthFusion. The separateDEPTHFUSION_API_KEYname exists specifically to prevent this (see E-12 S-22 in BACKLOG.md). The installer explicitly refuses to useANTHROPIC_API_KEYeven if it's set, by design.
2c. Make the shell auto-load the env file
Writing to depthfusion.env doesn't put variables in your shell
environment — nothing auto-sources it. Python tools read os.environ,
so without this block the factory check in 2e will route everything to
null despite the env file being correct. Append this alongside the
venv auto-activate block from §1d:
grep -q "# depthfusion env auto-source" ~/.bashrc || cat >> ~/.bashrc <<'EOF'
# depthfusion env auto-source — export vars from the config file
# so Python processes spawned from this shell see them via os.environ
if [ -f "$HOME/.claude/depthfusion.env" ]; then
set -a
source "$HOME/.claude/depthfusion.env"
set +a
fi
EOF
The
set -a/set +awrapper turns every plainKEY=valueline in the env file into an exported variable, without requiring the file itself to useexport KEY=valuesyntax.
2d. Reload the shell so the env file loads
Do NOT source ~/.bashrc while the venv is active — same half-activated-
state trap as §1d. Instead deactivate first, then exec bash so the
new shell starts with empty state and runs all auto-blocks from scratch:
deactivate 2>/dev/null; exec bash
Your prompt should still show (depthfusion), and these env vars
should now be live:
echo "haiku: $DEPTHFUSION_HAIKU_ENABLED"
echo "key: ${DEPTHFUSION_API_KEY:0:16}..."
Expected:
haiku: true
key: sk-ant-api03-xxx...
2e. Verify the factory now routes to Haiku
python3 -c "
from depthfusion.backends.factory import get_backend
for cap in ('reranker', 'extractor', 'linker', 'summariser', 'decision_extractor'):
b = get_backend(cap)
print(f'{cap:22} -> {b.name:10} (healthy={b.healthy()})')
"
Expected: every LLM capability routes to haiku with healthy=True.
If any route to null, step through the checks in 2d — specifically
that echo $DEPTHFUSION_API_KEY returns a non-empty value in this
shell. If the env var is empty but the file contains the key, the
auto-source block didn't run (check that 2c actually appended to
.bashrc via tail ~/.bashrc).
3. Install the research tools
bash ~/projects/depthfusion/scripts/install-research-tools.sh
This installs:
~/.config/systemd/user/ciqs-weekly.service+.timer— autonomous regression monitor; fires every Monday 06:00 local time- Initial session-history corpus at
~/.local/share/depthfusion/corpus/
Dry-run first if you want to see what it'll do:
bash ~/projects/depthfusion/scripts/install-research-tools.sh --dry-run
Verify:
# Timer should be listed, active, next run scheduled
systemctl --user list-timers ciqs-weekly.timer --no-pager
# Corpus file should exist and contain > 0 lines
ls -lh ~/.local/share/depthfusion/corpus/
head -1 ~/.local/share/depthfusion/corpus/corpus-*.jsonl | python3 -m json.tool
4. Smoke test the full pipeline
# End-to-end recall query via the MCP server's tool interface
python3 -c "
from depthfusion.mcp.server import _tool_recall
import json
result = json.loads(_tool_recall({'query': 'install verification test', 'top_k': 3}))
print(f'blocks returned: {len(result.get(\"blocks\", []))}')
print(f'error: {result.get(\"error\", \"none\")}')
"
Expected: some number of blocks (depends on what's indexed on this host), no error. If the project has been in use, you'll see recall results; on a fresh host the index is empty and you'll see 0 blocks — that's fine, indexing populates as you use Claude Code.
5. Trigger the weekly monitor manually (optional sanity check)
# Fire once without waiting for Monday
systemctl --user start ciqs-weekly.service
# Read what it logged
journalctl --user -u ciqs-weekly.service -n 50 --no-pager
ls -t ~/.local/share/depthfusion/weekly-reports/ | head -5
On a fresh install the report will show "no data" — this is correct and expected. Re-run after a week of real usage to see a populated report.
Done
You now have:
- ✅ DepthFusion running in
vps-cpumode (Haiku-backed) - ✅ Weekly regression monitor scheduled
- ✅ Initial prompt corpus mined
- ✅ All three research tools (
ciqs_compare.py,mine_session_prompts.py,ciqs_weekly.py) available underscripts/
What's next
For the parallel-comparison plan (measuring vps-gpu improvement
later): let this host run for 1-2 weeks of real usage to accumulate
a CIQS baseline. When your GPU VPS comes online and you complete
vps-gpu-quickstart.md, run three CIQS
baseline trials on each host (via scripts/ciqs_harness.py), then:
python3 scripts/ciqs_compare.py \
--baseline-label "vps-cpu (this host)" \
--baseline docs/benchmarks/YYYY-MM-DD-vps-cpu-run{1,2,3}-scored.jsonl \
--candidate-label "vps-gpu (new host)" \
--candidate <scp-ed-from-gpu-host>/*-scored.jsonl \
--out docs/benchmarks/comparison.md
For weekly monitoring: the timer runs autonomously. Check
~/.local/share/depthfusion/weekly-reports/ every so often. Any
regression flags the systemd unit as failed — you'll see it in
systemctl --user status ciqs-weekly.timer immediately.
For freshness: re-run the install script monthly to re-mine the prompt corpus (captures new usage patterns):
bash ~/projects/depthfusion/scripts/install-research-tools.sh
It's idempotent — existing systemd units won't be disturbed.