Date: 2026-04-27
Author: SCOUT
Scope: Move TITAN from primary Windows PC to a second machine — Windows or Mac — for a weekend validation test.
Status: DRAFT — ready for this weekend
---
All versions listed are current as of 2026-04-27. "Pin" column = what to lock in requirements.txt for reproducibility.
| Component | Current version (source PC) | Windows install | Mac install | Pin |
|---|---|---|---|---|
| Python | 3.14.x (3.14.3 released 2026-02-03) | winget install Python.Python.3.14 or python.org installer | brew install python@3.14 or uv python install 3.14 | ==3.14.3 in .python-version |
| Claude Code (CLI/app) | Latest (auto-updates) | Native installer: curl -fsSL https://claude.ai/install.sh \| bash (WSL) OR desktop app from claude.com/download | brew install --cask claude-code OR curl -fsSL https://claude.ai/install.sh \| bash | Lock via claude --version post-install |
| AWS CLI v2 | v2.x | Download .msi from https://awscli.amazonaws.com/AWSCLIV2.msi | Download .pkg from https://awscli.amazonaws.com/AWSCLIV2.pkg (universal binary, Apple Silicon + Intel) | Check aws --version |
| cloudflared | Latest | winget install --id Cloudflare.cloudflared -e | brew install cloudflared | Check cloudflared --version |
| Git | 2.x | winget install Git.Git | brew install git (or Xcode CLT) | — |
| Node.js | 18+ (only needed if using npm install path for Claude Code) | winget install OpenJS.NodeJS | brew install node | Optional — native installer skips this |
Defined in F:\TITAN\server\requirements.txt:
fastapi>=0.136.0
uvicorn[standard]>=0.44.0
pydantic-settings>=2.13.0
httpx>=0.28.0
python-multipart>=0.0.26
openai-whisper>=20250625
torch>=2.9.0
resend>=0.7.0
jinja2>=3.1.0
Additional packages used in scripts (not in requirements.txt — add to a requirements-scripts.txt):
| Package | Used by | Install |
|---|---|---|
| pypdf | RAG/document ingestion | pip install pypdf |
| python-docx | md_to_docx.py | pip install python-docx |
| tldextract | URL parsing in various scripts | pip install tldextract |
| boto3 | AWS SES/SNS/S3/Polly | pip install boto3 |
| anthropic | claude backend | pip install anthropic |
| python-telegram-bot | Telegram client | pip install python-telegram-bot |
| openai | Whisper and Qwen compat layer | pip install openai |
| rich / typer | CLI scripts | pip install rich typer |
Generate a pinned freeze on source PC before migrating:
pip freeze > F:\TITAN\requirements-freeze-2026-04-27.txt
| Service | Usage | Credential path |
|---|---|---|
| SES | Outbound email (titan_email.py) | C:\Users\Harnoor\.aws\ |
| SNS | Notifications | same |
| S3 | Backups (titan_s3_backup.py) | same |
| Polly | TTS voice route | same |
AWS credentials file: C:\Users\Harnoor\.aws\credentials and C:\Users\Harnoor\.aws\config
Mac equivalent: ~/.aws/credentials and ~/.aws/config — same format, different path.
| What | Source path | Target path |
|---|---|---|
| Claude Code auth/session | C:\Users\Harnoor\.claude\ | Mac: ~/.claude/ |
| TITAN CLAUDE.md | C:\Users\Harnoor\.claude\CLAUDE.md | ~/.claude/CLAUDE.md |
| Agent memory | C:\Users\Harnoor\.claude\agent-memory\ | ~/.claude/agent-memory/ |
| Knowledge/hot feedback | C:\Users\Harnoor\.claude\knowledge\ | ~/.claude/knowledge/ |
| Settings | C:\Users\Harnoor\.claude\settings.json | ~/.claude/settings.json |
Critical: Claude Code auth is tied to account, not machine. You must re-authenticate (claude first launch triggers OAuth) on the new machine. The session files under .claude/ include auth tokens — copy them OR re-auth; do NOT assume copy alone is sufficient for session continuity. Re-auth is safer.
| What | Source | Size estimate |
|---|---|---|
| TITAN source + scripts | F:\TITAN\ | ~500 MB (excluding data/) |
| TITAN data (memory, embeddings, queue) | F:\TITAN\data\ | variable — can be large |
| TITAN logs | F:\TITAN\logs\ | skip — regenerate |
| TITAN state | F:\TITAN\state\ | ~few MB — include |
| GitHub mirror | github.com/harnoorsinghminhas/titan-os | pull on target |
These are registered tasks — not portable files. They must be re-created on the target machine:
| Task name | Trigger | Script |
|---|---|---|
| TITAN-Server | At logon | F:\TITAN\server\run.bat |
| titan-inbox-watch | Every 15 min | claude -p + scheduled-tasks/titan-inbox-watch/SKILL.md |
| nightly-report-writer | Nightly | scheduled-tasks/nightly-report-writer/SKILL.md |
| titan-daily-pa-email | Daily | scheduled-tasks/titan-daily-pa-email/SKILL.md |
| titan-daily-newsletter | Daily | scheduled-tasks/titan-daily-newsletter/SKILL.md |
| agentic-247-watchdog | Frequent | scheduled-tasks/agentic-247-watchdog/SKILL.md |
| swarm-health-orchestrator | Periodic | scheduled-tasks/swarm-health-orchestrator/SKILL.md |
| TITAN Bridge | At startup | F:\TITAN\scripts\start_titan_bridge.bat |
Registered as a Windows Service via NSSM or cloudflared service install. Configuration lives in ~/.cloudflared/config.yml and cert at ~/.cloudflared/cert.pem. The tunnel identity (UUID) is the credential — it is stored in ~/.cloudflared/<tunnel-uuid>.json. This file travels with the migration; re-authenticating creates a new tunnel ID.
titan@livegroweveryday.com — stays in AWStitan.livegroweveryday.com — stays in Cloudflare dashboard.envharnoorsinghminhas/titan-os — stays on GitHub, just git pull on target---
[ ] Run: pip freeze > F:\TITAN\requirements-freeze-2026-04-27.txt
[ ] Commit and push to GitHub mirror:
cd F:\TITAN
git add -A
git commit -m "pre-migration snapshot 2026-04-27"
git push origin main
[ ] Export AWS credentials: confirm F:\TITAN\secrets\ does NOT contain .aws creds
(creds are at C:\Users\Harnoor\.aws\ — copy separately)
[ ] Copy .env files:
F:\TITAN\server\.env
F:\TITAN\clients\telegram\.env
F:\TITAN\.env (root, if it exists)
[ ] Note current TITAN_API_TOKEN (in server/.env — clients need it)
[ ] Export Cloudflare tunnel credential:
copy %USERPROFILE%\.cloudflared\ to a USB or secure location
specifically: cert.pem + <tunnel-uuid>.json + config.yml
[ ] Verify GitHub mirror is up to date:
git log --oneline -5
[ ] Note Python version: python --version
[ ] Note all running scheduled tasks:
schtasks /query /fo LIST /v > F:\TITAN\state\scheduled-tasks-export-2026-04-27.txt
[ ] Confirm AWS CLI works: aws sts get-caller-identity
[ ] Drain inbox queue: check F:\TITAN\state\inbox-queue.jsonl — no pending items
Transfer via USB drive, LAN share, or GitHub. Recommended: GitHub for code + secure USB for secrets.
From code (via git):
# On source — push everything
cd F:\TITAN
git add -A
git commit -m "migration bundle 2026-04-27"
git push
Secrets bundle (USB only — never git):
C:\Users\Harnoor\.aws\ → copy entire folder
C:\Users\Harnoor\.cloudflared\ → copy entire folder
F:\TITAN\server\.env
F:\TITAN\clients\telegram\.env
Claude Code config (semi-sensitive):
C:\Users\Harnoor\.claude\ → copy entire folder
Step 1 — Core runtimes
# Python 3.14 (run as admin)
winget install Python.Python.3.14
# Verify
python --version
# AWS CLI
# Download from https://awscli.amazonaws.com/AWSCLIV2.msi and run installer
# cloudflared
winget install --id Cloudflare.cloudflared -e
# Git (if not present)
winget install Git.Git
Step 2 — Claude Code
# Option A: desktop app (recommended — same as source machine)
# Download from https://claude.com/download
# Install and sign in with Anthropic account
# Option B: native installer (WSL/terminal)
curl -fsSL https://claude.ai/install.sh | bash
Step 3 — Clone TITAN
# Create F: drive if needed, or adjust TITAN_ROOT
git clone https://github.com/harnoorsinghminhas/titan-os F:\TITAN
cd F:\TITAN
Step 4 — Restore secrets
# From USB:
xcopy /E /I USB:\\.aws\ C:\Users\<TargetUser>\.aws\
xcopy /E /I USB:\\.cloudflared\ C:\Users\<TargetUser>\.cloudflared\
copy USB:\\server.env F:\TITAN\server\.env
copy USB:\\telegram.env F:\TITAN\clients\telegram\.env
xcopy /E /I USB:\\.claude\ C:\Users\<TargetUser>\.claude\
Step 5 — Set TITAN_ROOT env var (if drive letter differs)
# If TITAN is not on F: — set system env var
setx TITAN_ROOT "D:\TITAN" /M
# Restart terminal after this
Step 6 — Python venv + dependencies
cd F:\TITAN
python -m venv venv
venv\Scripts\activate
pip install -r server\requirements.txt
pip install pypdf python-docx tldextract boto3 anthropic python-telegram-bot openai rich typer
Step 7 — Re-authenticate Claude Code
# Launch Claude Code — it will prompt for OAuth login
claude
# Sign in with same Anthropic account
Step 8 — Verify AWS
aws sts get-caller-identity
aws ses list-identities
Step 9 — Cloudflare Tunnel
# Re-use existing tunnel credentials from USB
# Config should already be in C:\Users\<User>\.cloudflared\
# Install as Windows Service
cloudflared service install
# Start it
sc start cloudflared
# Verify tunnel is up
cloudflared tunnel info titan
Step 10 — Re-register Scheduled Tasks
# TITAN Server (at logon)
F:\TITAN\server\install-service.bat
# TITAN Bridge (at startup)
schtasks /create /tn "TITAN-Bridge" /tr "F:\TITAN\scripts\start_titan_bridge.bat" /sc onstart /rl highest /ru SYSTEM /f
# For each scheduled-task skill (titan-inbox-watch, etc.) — re-create manually
# Example for 15-min inbox watch:
schtasks /create /tn "titan-inbox-watch" /tr "claude -p --allowedTools=Edit,Write,Read,Bash --print \"$(type F:\TITAN\scheduled-tasks\titan-inbox-watch\SKILL.md)\"" /sc minute /mo 15 /f
# Note: the exact command pattern depends on how Claude Code is invoked — verify against source PC export
# 1. Server responds
curl http://localhost:8765/api/health
# Expected: {"ok": true, ...}
# 2. Auth works
set TOKEN=<from server/.env>
curl -H "Authorization: Bearer %TOKEN%" http://localhost:8765/api/status
# 3. AWS credentials
aws sts get-caller-identity
aws s3 ls s3://<your-backup-bucket>
# 4. Cloudflare tunnel public URL
curl https://titan.livegroweveryday.com/api/health
# 5. Claude Code functional
echo "reply with: TITAN is alive" | claude -p --print
# 6. Python packages
python -c "import fastapi, boto3, pypdf, docx, tldextract; print('all imports OK')"
# 7. SES send test
python F:\TITAN\scripts\titan_email.py --to harnoors@gmail.com --subject "A075 smoke test" --body "Target PC online"
If the target fails:
1. Stop the TITAN server on target: schtasks /end /tn "TITAN-Server"
2. All data is still intact on source PC — no data was moved, only copied
3. Remove or suspend scheduled tasks on target to avoid double-processing inbox-queue
4. Update DNS/Cloudflare if you pointed a new tunnel — revert CNAME to original tunnel UUID
5. Source PC resumes immediately — no config change needed
---
| Windows path | Mac equivalent |
|---|---|
| F:\TITAN | ~/titan (set TITAN_ROOT=~/titan) |
| C:\Users\Harnoor\.aws\ | ~/.aws/ |
| C:\Users\Harnoor\.claude\ | ~/.claude/ |
| C:\Users\Harnoor\.cloudflared\ | ~/.cloudflared/ |
| F:\TITAN\server\run.bat | ~/titan/server/run.sh |
| F:\TITAN\logs\ | ~/titan/logs/ |
| python (cmd) | python3 or python (after brew) |
| venv\Scripts\activate | venv/bin/activate |
| Task Scheduler | launchd (plist in ~/Library/LaunchAgents/) |
| sc start cloudflared (Windows service) | sudo launchctl start com.cloudflare.cloudflared |
| taskkill | kill $(lsof -ti :8765) |
| schtasks /query | launchctl list |
| %USERPROFILE% | $HOME |
Same Friday-night checklist from Section 2 applies. Additionally:
[ ] Note any Windows-specific paths hardcoded in scripts (see Section 5 for list)
[ ] Note any .bat files that have no .sh equivalent — you'll need to port them
Step 1 — Homebrew (if not present)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Apple Silicon: add to PATH
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
Step 2 — Python 3.14
# Option A: Homebrew (may lag behind patch releases)
brew install python@3.14
echo 'export PATH="/opt/homebrew/opt/python@3.14/bin:$PATH"' >> ~/.zprofile
source ~/.zprofile
# Option B: uv (recommended — pinnable, fast)
curl -LsSf https://astral.sh/uv/install.sh | sh
uv python install 3.14
# Use uv run or uv venv going forward
# Verify
python3 --version
Step 3 — Claude Code
# Option A: Homebrew cask (recommended for Mac — desktop app)
brew install --cask claude-code
# Option B: native installer (terminal-only)
curl -fsSL https://claude.ai/install.sh | bash
# Option C: npm (requires Node 18+)
npm install -g @anthropic-ai/claude-code
# Verify
claude --version
Note on Claude Code MAX on Mac: As of April 2026, Claude Code on Mac is fully supported and the MAX subscription works identically. The Mac version runs natively (no WSL required, unlike Windows where WSL is recommended for the npm path). The desktop app and native installer both work on Apple Silicon.
Step 4 — AWS CLI (universal binary — works on Intel + Apple Silicon)
# Download pkg installer
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o /tmp/AWSCLIV2.pkg
sudo installer -pkg /tmp/AWSCLIV2.pkg -target /
aws --version
Step 5 — cloudflared
brew install cloudflared
cloudflared --version
Step 6 — Other tools
brew install git
# pandoc (used by md_to_docx.py via subprocess — optional)
brew install pandoc
Step 7 — Clone TITAN
git clone https://github.com/harnoorsinghminhas/titan-os ~/titan
Step 8 — Set TITAN_ROOT
# Add to ~/.zprofile (zsh default on Mac)
echo 'export TITAN_ROOT="$HOME/titan"' >> ~/.zprofile
source ~/.zprofile
Note: server/config.py already handles this — it checks TITAN_ROOT env var first, then falls back to ~/TITAN on POSIX. Using ~/titan (lowercase) requires the env var to be set explicitly.
Step 9 — Restore secrets
# From USB (mounted at /Volumes/USB or similar):
cp -r /Volumes/USB/.aws/ ~/.aws/
cp -r /Volumes/USB/.cloudflared/ ~/.cloudflared/
cp /Volumes/USB/server.env ~/titan/server/.env
cp /Volumes/USB/telegram.env ~/titan/clients/telegram/.env
cp -r /Volumes/USB/.claude/ ~/.claude/
chmod 600 ~/.aws/credentials
Step 10 — Python venv + dependencies
cd ~/titan
python3 -m venv venv
source venv/bin/activate
pip install -r server/requirements.txt
pip install pypdf python-docx tldextract boto3 anthropic python-telegram-bot openai rich typer
Note on torch (in requirements.txt): torch>=2.9.0 installs fine on Mac but CUDA is not available. WHISPER_DEVICE must be set to cpu in .env. Voice transcription will be slower but functional.
Step 11 — Re-authenticate Claude Code
claude
# OAuth flow opens in browser — sign in with same Anthropic account
Step 12 — Cloudflare Tunnel as launchd service
# Re-use credentials from ~/.cloudflared/
# Option A: launchd launch agent (runs at login, recommended for test)
cloudflared service install
# This creates ~/Library/LaunchAgents/com.cloudflare.cloudflared.plist
# Start it:
launchctl start com.cloudflare.cloudflared
# Option B: launchd launch daemon (runs at boot, requires sudo)
sudo cloudflared service install
sudo launchctl start com.cloudflare.cloudflared
# Verify
cloudflared tunnel info titan
curl https://titan.livegroweveryday.com/api/health
Step 13 — Scheduled tasks via launchd
For each Windows scheduled task, create a .plist file. Example for titan-inbox-watch (every 15 min):
cat > ~/Library/LaunchAgents/com.titan.inbox-watch.plist << 'EOF'
<?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.titan.inbox-watch</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-c</string>
<string>source $HOME/titan/venv/bin/activate && claude -p --allowedTools=Edit,Write,Read,Bash --print "$(cat $HOME/titan/scheduled-tasks/titan-inbox-watch/SKILL.md)" >> $HOME/titan/logs/inbox-watch.log 2>&1</string>
</array>
<key>StartInterval</key>
<integer>900</integer>
<key>RunAtLoad</key>
<false/>
<key>StandardOutPath</key>
<string>/Users/YOURUSERNAME/titan/logs/inbox-watch-launchd.log</string>
<key>StandardErrorPath</key>
<string>/Users/YOURUSERNAME/titan/logs/inbox-watch-launchd-err.log</string>
</dict>
</plist>
EOF
# Replace YOURUSERNAME with actual username
# Load it:
launchctl load ~/Library/LaunchAgents/com.titan.inbox-watch.plist
# Verify:
launchctl list | grep titan
Repeat the plist pattern for each scheduled task (nightly-report, daily-pa-email, daily-newsletter, watchdogs). Use StartCalendarInterval for time-of-day tasks:
<!-- Daily at 7am -->
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>7</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
Step 14 — TITAN Server as launchd service
# Create run.sh (Mac equivalent of run.bat)
cat > ~/titan/server/run.sh << 'EOF'
#!/bin/bash
source $HOME/titan/venv/bin/activate
cd $HOME/titan
python -m uvicorn server.app:app --host 127.0.0.1 --port 8765 >> $HOME/titan/logs/titan-server.log 2>&1
EOF
chmod +x ~/titan/server/run.sh
# Create launchd plist
cat > ~/Library/LaunchAgents/com.titan.server.plist << 'EOF'
<?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.titan.server</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/YOURUSERNAME/titan/server/run.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/YOURUSERNAME/titan/logs/titan-server.log</string>
<key>StandardErrorPath</key>
<string>/Users/YOURUSERNAME/titan/logs/titan-server-err.log</string>
</dict>
</plist>
EOF
launchctl load ~/Library/LaunchAgents/com.titan.server.plist
# 1. Server health
curl http://localhost:8765/api/health
# 2. Auth
TOKEN=$(grep TITAN_API_TOKEN ~/titan/server/.env | cut -d= -f2)
curl -H "Authorization: Bearer $TOKEN" http://localhost:8765/api/status
# 3. AWS
aws sts get-caller-identity
# 4. Cloudflare public URL
curl https://titan.livegroweveryday.com/api/health
# 5. Claude Code
echo "reply with: TITAN is alive on Mac" | claude -p --print
# 6. Python imports
python3 -c "import fastapi, boto3, pypdf, docx, tldextract; print('all imports OK')"
# 7. Port check (titan_bridge on 8765)
lsof -i :8765
# 8. SES test
python3 ~/titan/scripts/titan_email.py --to harnoors@gmail.com --subject "A075 Mac smoke test" --body "Mac target online"
---
| Dimension | Windows PC-2 | Mac (M-series) |
|---|---|---|
| Setup friction | Low — identical to source, copy-paste runbook works verbatim | Medium — path rewrite, bat->sh port, launchd vs Task Scheduler |
| Daemon reliability | Task Scheduler is battle-tested for TITAN; already proven on source | launchd is stable and runs at boot; TITAN untested here |
| Claude Code parity | Full parity — same Windows app, same session behavior | Full parity — Mac is Anthropic's primary dev platform; native installer first-class |
| AWS CLI parity | Full parity | Full parity (universal binary since v2.30.0) |
| Python parity | Full parity | Full parity; Apple Silicon uses arm64 wheels — most packages have them; torch is CPU-only (no CUDA) |
| Whisper/voice | CUDA if GPU present — fast | CPU only on Mac — slower transcription (~3-5x slower for large model) |
| M-series perf (non-CUDA) | N/A | M3/M4 CPU is fast; single-threaded Python perf comparable or better; RAM bandwidth superior for LLM inference |
| Battery / always-on | Desktop PC = always plugged in, no sleep concerns | MacBook: sleepd can interrupt daemons; must set caffeinate or disable sleep for background tasks |
| Storage | Typically large, fast NVMe | MacBooks: smaller SSD (256/512 GB common) — TITAN data dir can be large |
| Path hardcoding | F:/TITAN — if same drive letter, zero rewrites | ~/titan — requires env var + script audits |
| titan_bridge.py | Works as-is | Requires rewrite of hardcoded F:/TITAN paths (see Section 5) |
| start_titan_bridge.bat | Runs natively | Must port to run.sh |
| start-titan.bat / run.bat | Runs natively | Must port to .sh equivalents |
| Win32 API usage | N/A currently | None detected in TITAN scripts — safe |
| os.name == "nt" branches | Covered | POSIX branch already exists in config.py |
| Claude Code MAX subscription | Works | Works — same Anthropic account |
| Long-term recommendation | Lower risk for this weekend test | Better long-term if you want laptop portability and M-series efficiency |
Summary verdict: For THIS WEEKEND, Windows-PC-2 is lower risk and faster to execute — zero path rewrites, same Task Scheduler mechanics, identical .bat launchers. Mac is the right long-term play (M-series perf, portability, Unix toolchain alignment with TITAN's architecture) but costs 2-3 extra hours on the first setup.
---
server/config.py already has a clean TITAN_ROOT abstraction:
def _default_titan_root() -> str:
env = os.environ.get("TITAN_ROOT")
if env:
return env
if os.name == "nt":
return "F:/TITAN"
return str(Path.home() / "TITAN")
This means server/ is already portable. The problem is the scripts layer.
High priority — must fix before Mac is viable:
| File | Hardcoded references | Fix |
|---|---|---|
| scripts/titan_bridge.py | _TITAN_ROOT = Path("F:/TITAN") (line 55) + 15+ derivative paths | Replace with Path(os.environ.get("TITAN_ROOT", "F:/TITAN" if os.name=="nt" else str(Path.home()/"TITAN"))) |
| scripts/titan_bridge.py | _INNERVERSE_SRC = Path("F:/projects/innerverse/...") (line 47) | Add INNERVERSE_SRC env var or make optional with try/except |
| start-titan.bat | cd /d F:\TITAN | Port to run.sh with $TITAN_ROOT |
| start_titan_bridge.bat | F:\TITAN\logs\ | Port to shell script |
| server/run.bat | implicit F:\TITAN working dir | Port to run.sh |
| server/install-service.bat | multiple F:\TITAN references | Port to launchd plist generator |
| orchestrator.py | cd /d F:\TITAN in .bat reference | Audit |
| scripts/*.py (various) | F:/TITAN/ string literals in log paths, state paths | Replace with Path(os.environ.get("TITAN_ROOT", ...)) pattern |
| scheduled-tasks/*/SKILL.md | F:/TITAN/state/ in JSONL path references | These are prompts — update path examples in each SKILL.md |
| RUNBOOK.md | F:\TITAN\server\run.bat doc references | Documentation only — update after code |
Step 1 — Add a shared path helper to scripts/_titan_paths.py:
from pathlib import Path
import os
def titan_root() -> Path:
env = os.environ.get("TITAN_ROOT")
if env:
return Path(env)
if os.name == "nt":
return Path("F:/TITAN")
return Path.home() / "TITAN"
TITAN_ROOT = titan_root()
Step 2 — In each script that has hardcoded paths, replace:
# Before
_TITAN_ROOT = Path("F:/TITAN")
# After
from _titan_paths import TITAN_ROOT as _TITAN_ROOT
Step 3 — Create server/run.sh as Mac/Linux equivalent of run.bat
Step 4 — Create a scripts/create_launchd_agents.py that generates all plist files from the scheduled-tasks/ SKILL.md roster
Step 5 — Update SKILL.md files to use $TITAN_ROOT variable notation in path examples
Files that do NOT need editing (already abstracted):
server/config.py — already has full TITAN_ROOT awarenessserver/app.py — uses settings from config.pyserver/routes/*.py — use settings.titan_rootserver/backends/*.py — no direct path references---
These items require manual re-creation or special handling. Do not assume they transfer automatically.
Task Scheduler tasks are registered in the Windows registry + XML task definitions. They do not travel in a git clone. On target Windows PC: run server/install-service.bat and re-create each task manually. The state/scheduled-tasks-export-2026-04-27.txt pre-flight export gives you the exact trigger/action config to replicate.
On Mac: every task becomes a launchd .plist file. There is no automated converter. The SKILL.md files contain the command logic — wrap each in a plist as shown in Section 3, Step 13.
~/.cloudflared/cert.pem is the Cloudflare-issued cert that authorizes this machine to manage the tunnel. Options:
cloudflared tunnel login): creates a NEW cert. You then need to either create a new tunnel or re-associate the existing tunnel UUID with the new cert. Requires Cloudflare dashboard changes.cloudflared service simultaneously with the same tunnel config, you may get split traffic. Confirm the source PC's cloudflared service is stopped before starting on target..claude/ contains auth tokens AND the conversation memory index. After copying:
1. Verify auth still works: claude --print "hello" — if it prompts for login, OAuth re-auth is needed.
2. Session project memory at ~/.claude/projects/ or equivalent may reference source machine paths (C:\Users\Harnoor\Desktop\...). These will resolve to stale paths on target. This is cosmetic for the weekend test but matters for production.
3. Agent memory at ~/.claude/agent-memory/ should be intact — these are flat markdown files with no machine-specific paths.
scripts/titan_bridge.py line 47 imports from F:/projects/innerverse/backend/src — this is a separate project that lives outside F:/TITAN. On target machines this path likely does not exist. The bridge will crash at startup unless:
try/except ImportError_INNERVERSE_SRC path is made configurable via env varFor the weekend test: comment out the innerverse import block and any rendering functions that depend on livedash. The bridge's core API endpoints (/api/health, /api/cmd, /api/queue) do not need livedash.
server/requirements.txt requires torch>=2.9.0. On Mac, this installs the CPU-only build. Set WHISPER_DEVICE=cpu in .env before starting. Voice endpoints will be significantly slower. If Whisper/voice is not being tested this weekend, this is not blocking.
start-titan.bat, run.bat, install-service.bat, start_titan_bridge.bat — none of these work on Mac. You must run server manually via terminal or create .sh equivalents (see Section 3 steps 13-14). For the weekend test, running manually from terminal is sufficient.
SES sender identity titan@livegroweveryday.com is already verified in AWS — this is fine. But if your target machine's outbound IP differs significantly (e.g., different ISP), SES has no issue since it uses IAM credentials not IP allowlisting. This is not a blocker.
---
Goal: Confirm TITAN runs on target machine end-to-end. Not a full production cutover — source stays live as fallback.
Pre-session prep (Friday night, 30 min):
00:00 - 00:15 INSTALL RUNTIMES
Python 3.14, Claude Code, AWS CLI, cloudflared, Git
(Win: winget commands | Mac: brew commands)
Verify: python --version, claude --version, aws --version
00:15 - 00:30 CLONE + SECRETS
git clone titan-os to target path
Copy .aws/, .cloudflared/, .env files from USB
Set TITAN_ROOT env var if path differs
00:30 - 00:45 PYTHON DEPS + AUTH
Create venv, pip install requirements
Run: claude (triggers OAuth if needed)
Run: aws sts get-caller-identity
00:45 - 01:00 START TITAN SERVER
Activate venv
Win: server\run.bat | Mac: bash server/run.sh
Test: curl http://localhost:8765/api/health
Expected: {"ok": true}
01:00 - 01:15 CLOUDFLARE TUNNEL
cloudflared service install
Start service (sc start / launchctl start)
Test: curl https://titan.livegroweveryday.com/api/health
If no response in 2 min: cloudflared tunnel run titan (manual)
01:15 - 01:30 CORE SMOKE TESTS
Auth endpoint
Python imports check
AWS S3 list
Claude Code echo test
01:30 - 01:45 REGISTER ONE SCHEDULED TASK
Re-create titan-inbox-watch (15-min Gmail bridge)
Trigger it manually once
Verify log output in titan/logs/
01:45 - 02:00 SEND TEST EMAIL + DOCUMENT
python scripts/titan_email.py (SES test)
Note what broke, what was slow, what needs the F:/ refactor
Decide: promote to primary or leave as standby
Push notes to F:/TITAN/plans/advisors/A075-RESULTS-2026-04-27.md
Success criteria:
/api/health returns 200 on localhost AND via Cloudflare tunnelaws sts get-caller-identity succeedsAcceptable failures for weekend test (non-blocking):
---
# Create .python-version file in TITAN root
echo "3.14.3" > F:\TITAN\.python-version
# pyenv / uv will respect this
Before migrating, generate a complete freeze on source PC:
# Source PC
cd F:\TITAN
venv\Scripts\activate
pip freeze > requirements-freeze-2026-04-27.txt
git add requirements-freeze-2026-04-27.txt
git commit -m "pin: freeze requirements 2026-04-27 pre-migration"
git push
On target, use the freeze for exact reproduction:
pip install -r requirements-freeze-2026-04-27.txt
| Package | Why lock | Pinned version |
|---|---|---|
| torch | Large, ABI-sensitive, CUDA/CPU wheels differ | Lock to exact version from source |
| openai-whisper | Tied to torch version | Lock together |
| anthropic | API client — breaking changes possible | Lock to minor version |
| fastapi + uvicorn | Server stability | Lock to minor |
| pydantic-settings | Settings parsing | Lock to minor |
| boto3 | AWS SDK — new service APIs released frequently | Lock to minor |
# Check current version
cloudflared --version
# Pin in a VERSION.txt or doc
echo "cloudflared: $(cloudflared --version)" >> F:\TITAN\state\component-versions.txt
Claude Code auto-updates. For reproducibility, note the version at test time:
claude --version >> F:\TITAN\state\component-versions.txt
Claude Code does not support pinning — it is always the latest. This is acceptable since Anthropic maintains backward compatibility with the agent SDK interface.
requirements-scripts.txt (create this file)
pypdf>=4.0.0
python-docx>=1.1.0
tldextract>=5.0.0
boto3>=1.34.0
anthropic>=0.49.0
python-telegram-bot>=21.0.0
openai>=1.50.0
rich>=13.0.0
typer>=0.12.0
Commit this alongside server/requirements.txt so any machine can run both the server and the scripts layer.
---
winget install Python.Python.3.14
winget install Git.Git
winget install --id Cloudflare.cloudflared -e
# AWS CLI: manual .msi from https://awscli.amazonaws.com/AWSCLIV2.msi
# Claude Code: https://claude.com/download
brew install python@3.14
brew install git
brew install cloudflared # Formula: formulae.brew.sh/formula/cloudflared
brew install --cask claude-code # Desktop app — recommended
# AWS CLI: curl pkg from https://awscli.amazonaws.com/AWSCLIV2.pkg
curl -fsSL https://claude.ai/install.sh | bash
---
~/titan/server/.env (TITAN_API_TOKEN, secrets)
~/.aws/credentials (AWS access key + secret)
~/.aws/config (region, output format)
~/.cloudflared/cert.pem (Cloudflare tunnel auth)
~/.cloudflared/<tunnel-uuid>.json (tunnel identity)
~/.cloudflared/config.yml (tunnel → localhost:8765 mapping)
~/.claude/ (Claude Code auth + agent memory)
Missing any of these = service fails to start or has no auth.
---
1. Python 3.14 release: https://www.python.org/downloads/release/python-3143/
2. Claude Code Mac install: https://claude.com/download + https://formulae.brew.sh/cask/claude-code (verify cask name on install)
3. AWS CLI v2 universal binary: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
4. cloudflared Homebrew: https://formulae.brew.sh/formula/cloudflared
5. cloudflared launchd service: https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/as-a-service/macos/
6. launchd scheduling: https://blog.serghei.pl/posts/scheduling-recurring-tasks-on-macos-using-launchd/
7. Claude Code Windows vs Mac: https://docs.bswen.com/blog/2026-03-21-claude-code-terminal-vs-desktop/