On this page

TRANSFER.md

Transfer

Aegis — Deployment Layout & Transfer Guide

Generated: 2026-09-21 14:18:35 PDT Host: ambassadorcrimson-node (kernel 7.0.0-31-generic) Generator: write_transfer_doc.sh This file is the authoritative record of how Aegis is split across the filesystem. Regenerate it with bash write_transfer_doc.sh after any structural change. Re-running backs up the previous copy first.

Purpose: Record exactly how Aegis is split across the filesystem, what each piece does, and how every piece references every other piece — so that moving Aegis to a new drive/location later is a mechanical operation, not an archaeology project.


1. The three layers

Aegis is split across three filesystem layers. This split is by role, not by accident. Each layer has a different lifetime and a different reason for existing where it does.

LayerRoleLocationMovable?
ApplicationThe actual Aegis code~/Documents/Aegis-Terminal/✅ Freely — this is the thing you relocate
LifecycleScripts that start/stop/verify Aegis~/ (currently)✅ Should move INTO the app dir (see §5)
System integrationThings the OS requires at fixed paths/usr/local/bin/, ~/.config/systemd/user/, /tmp/⚠️ Pointers only — cannot move, must be re-pointed

Rule of thumb: if it is Aegis, it belongs in the Application layer. If it is how the OS finds Aegis, it stays where the OS requires, as a thin pointer into the Application layer.


2. File inventory

Application layer — ~/Documents/Aegis-Terminal/

PathRoleReferenced by
.venv/Backend Python env (FastAPI/uvicorn)aegis_start.sh ($PY)
.venv-kokoro/Kokoro Python env (3.12, CPU torch)kokoro_server.py, speak, cache generator
main.pyBackend app, ~3480 linesaegis_start.sh (uvicorn)
kokoro_server.pyKokoro HTTP server on :5050systemd unit ExecStart
aegis_full_test.sh12/12 system test (currently in ~/)manual

Lifecycle layer — ~/ (to be consolidated — see §5)

PathRoleCalls
aegis_start.shStarts backend; speaks "backend online"$PY (venv), speak, /tmp/aegis-backend.log
aegis_shutdown.shStops stack; Kokoro lastsystemctl --user, project paths
aegis_full_test.sh12-point verificationboth endpoints

System integration layer

PathRolePoints atMovable?
/usr/local/bin/speakKokoro-only shell command:5050/speak via curl❌ symlink target only
/usr/local/bin/speak.piperManual Piper fallbackPiper❌ symlink target only
~/.config/systemd/user/kokoro-server.serviceKeeps Kokoro residentExecStart=.../kokoro_server.py❌ systemd fixed path
/tmp/aegis-backend.logBackend stdout/stderrwritten by aegis_start.sh✅ can move to app dir logs/

3. Reference map (who calls whom)

This is the critical section. Every arrow is a place that must be updated if a path changes.

aegis_start.sh
   ├─ $PY = ~/Documents/Aegis-Terminal/.venv/bin/python
   ├─ cd ~/Documents/Aegis-Terminal
   ├─ nohup $PY -m uvicorn main:app  → /tmp/aegis-backend.log
   └─ speak "Aegis backend online."   → /usr/local/bin/speak
                                            └─ curl :5050/speak

aegis_shutdown.sh
   └─ systemctl --user stop kokoro-server  (Kokoro last)

systemd unit kokoro-server.service
   └─ ExecStart = ~/Documents/Aegis-Terminal/.venv-kokoro/bin/python
                  ~/Documents/Aegis-Terminal/kokoro_server.py

main.py
   ├─ KOKORO_URL → :5050/synth   (must be /synth, not /speak)
   ├─ speak  (3 call sites, via /usr/local/bin/speak)
   └─ _maybe_speak_answer → :5050/speak (auto-speak, silent skip on fail)

/usr/local/bin/speak
   └─ curl :5050/speak           (no project path — talks over HTTP)

Key insight: almost all coupling is through HTTP (:5050, :8000) or through $PATH (speak). Very little is direct file-to-file coupling. That is good — it means relocation is mostly about fixing absolute paths inside scripts and the systemd unit, not untangling code.


4. Why the split exists (so future-you doesn't "fix" it wrongly)


5. Target layout (the consolidation)

Goal: all Aegis-authored files in one directory, with three thin pointers left outside.

~/Documents/Aegis-Terminal/            ← ONE Aegis directory
├── .venv/                             (backend venv)
├── .venv-kokoro/                      (Kokoro venv)
├── main.py
├── kokoro_server.py
├── aegis_start.sh                     ← MOVED from ~/
├── aegis_shutdown.sh                  ← MOVED from ~/
├── aegis_full_test.sh                 ← MOVED from ~/
├── speak                              ← MOVED from /usr/local/bin/
├── speak.piper                        ← MOVED from /usr/local/bin/
├── aegis_activate.sh                  ← NEW (orchestrator + loading window)
├── aegis_loading_window.py            ← NEW
├── gen_voice_cache.py                 ← NEW
├── aegis_voice_cache/                 ← NEW (cached WAVs)
└── logs/                              ← NEW (was /tmp/aegis-backend.log)

Left outside (pointers only):
  /usr/local/bin/speak         → symlink → <appdir>/speak
  /usr/local/bin/speak.piper   → symlink → <appdir>/speak.piper
  ~/.config/systemd/user/kokoro-server.service
                               → ExecStart points into <appdir>

Invariant after consolidation: the Application layer is the only place real Aegis content lives. Everything outside is a pointer.


6. Relocation procedure (when Aegis moves to its own drive)

Phase 0 — Pre-flight (do this NOW, before the move, while it works)

# Snapshot the reference map so drift is visible later
cd ~/Documents/Aegis-Terminal
grep -rnE 'Documents/Aegis-Terminal|/usr/local/bin|aegis-backend.log|:5050|:8000' \
  . --include='*.py' --include='*.sh' \
  ~/aegis_*.sh /usr/local/bin/speak* \
  ~/.config/systemd/user/kokoro-server.service 2>/dev/null \
  > TRANSFER_refs_$(date +%Y%m%d).txt

Phase 1 — Stop the stack

~/Documents/Aegis-Terminal/aegis_shutdown.sh   # Kokoro stops last

Phase 2 — Copy (never move first; copy, verify, then swap)

rsync -aHAX --info=progress2 \
  ~/Documents/Aegis-Terminal/ \
  /new/drive/Aegis-Terminal/

Phase 3 — Re-point the three externals

ExternalChange
/usr/local/bin/speakln -sfn /new/drive/Aegis-Terminal/speak /usr/local/bin/speak
/usr/local/bin/speak.piperln -sfn /new/drive/Aegis-Terminal/speak.piper /usr/local/bin/speak.piper
systemd unitedit ExecStart= paths → /new/drive/Aegis-Terminal/..., then systemctl --user daemon-reload

Phase 4 — Fix absolute paths inside scripts

# Find anything still pointing at the old location
grep -rn 'Documents/Aegis-Terminal' /new/drive/Aegis-Terminal/

Replace every hit with the new root. The venvs are the usual trap — pyvenv.cfg and console scripts contain hardcoded absolute paths, so venvs often need recreating (python -m venv) rather than moving.

Phase 5 — Verify

systemctl --user daemon-reload
systemctl --user start kokoro-server
/new/drive/Aegis-Terminal/aegis_start.sh
/new/drive/Aegis-Terminal/aegis_full_test.sh   # expect 12/12
speak "Relocation complete."                    # must work via $PATH

Phase 6 — Rollback (if needed) The old copy is untouched until Phase 5 succeeds. To revert: re-point the three externals at the old location and daemon-reload. Nothing is lost.


7. Known traps on relocation

  1. Venvs contain absolute paths. bin/python, pyvenv.cfg, and console scripts embed the build-time path. Moving a venv usually breaks it. Recreate venvs at the new location rather than copying:
  1. KOKORO_URL must be /synth, not /speak. Easy to get wrong during a rewrite.
  2. systemd user units do not auto-reload. Always daemon-reload after editing.
  3. /tmp log is not moved — decide whether to migrate it to <appdir>/logs/ during this relocation (recommended).
  4. ~/.bashrc Kokoro warning-suppression block — one copy only. Check for duplicates after moving anything that touches $PATH.
  5. Two venvs must stay separate unless you deliberately merge them (§4).

8. One-line summary

Aegis is one app directory + three OS-mandated pointers. Relocation = copy the directory, re-point the three pointers, recreate the venvs, verify 12/12. Nothing else.