13 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Environment
This is a home-lab / managed-hosting environment. There is no local codebase to build or test — work consists of editing PHP/JS files on remote servers via SSH and managing infrastructure across several machines. All tool calls use sshpass with password auth.
Server Map
| Host | IP | SSH | Purpose |
|---|---|---|---|
| DO (main) | 165.22.1.228 | root / Gonewalk1974!@# |
CyberPanel/OLS — all websites + JARVIS |
| FusionPBX | 134.209.72.226 | root / Joker1974!@# |
FreeSWITCH PBX |
| PVE1 (Proxmox) | orbisne.fortiddns.com (10.48.200.90) | root / Joker1974!!! |
Primary hypervisor — FortiGate DDNS, auto-updates if IP changes |
| PVE2 (Proxmox) | 10.48.200.91 | root / Joker1974!!! |
Secondary hypervisor |
| Ollama VM | 10.48.200.95 | myron → sudo |
llama3.2 local LLM (PVE1 VM 210) |
| Home Assistant | 10.48.200.97 | myron → sudo |
HA VM 101 |
| NetworkBackup | 10.48.200.99 | myron → sudo |
Backup VM (PVE2 VM 302) |
| MediaStack | 10.48.200.35 | root via PVE1 key |
Sonarr/Radarr/Prowlarr/qBittorrent (PVE1 VM 113) |
SSH password order (try in sequence if first fails): Joker1974!@# → Joker1974!!! → Joker1974!
SSH pattern for all remote work:
sshpass -p 'Gonewalk1974!@#' ssh -o StrictHostKeyChecking=no root@165.22.1.228 'commands here'
For PVE1 from anywhere (FortiGate DDNS, survives IP changes):
sshpass -p 'Joker1974!!!' ssh -o StrictHostKeyChecking=no root@orbisne.fortiddns.com 'commands here'
For commands inside VMs on PVE1:
sshpass -p 'Joker1974!!!' ssh -o StrictHostKeyChecking=no root@orbisne.fortiddns.com \
'qm guest exec 210 -- bash -c "commands here"'
Websites on DO (165.22.1.228)
All sites live at /home/<domain>/public_html/ on DO. CyberPanel/OpenLiteSpeed serves them.
| Site | Path | GitHub |
|---|---|---|
| jarvis.orbishosting.com | /home/jarvis.orbishosting.com/ | myronblair/jarvis |
| tomsjavajive.com | /home/tomsjavajive.com/public_html/ | myronblair/tomsjavajive |
| epictravelexpeditions.com | /home/epictravelexpeditions.com/public_html/ | myronblair/epictravelexpeditions |
| parkerslingshotrentals.com | /home/parkerslingshotrentals.com/public_html/ | myronblair/parkerslingshotrentals |
| orbishosting.com | /home/orbishosting.com/public_html/ | myronblair/orbishosting |
| orbis.orbishosting.com | /home/orbis.orbishosting.com/public_html/ | myronblair/orbis-hosting-portal |
| tomtomgames.com | /home/tomtomgames.com/public_html/ | myronblair/tomtomgames |
Parker Slingshot is served from epictravelexpeditions.com, not its own domain:
- URL:
https://parkerslingshot.epictravelexpeditions.com - Path:
/home/epictravelexpeditions.com/parkerslingshot/ - GitHub:
myronblair/parkerslingshot(own repo, auto-deploy active) db.phpandconfig.phpare gitignored (credentials);db.php.exampleis the reference template
Deployment Workflow
Auto-deploy is active. Push to main on any site repo → GitHub webhook → server pulls automatically within 1 minute. PHP syntax is validated before deploy; bad commits are auto-reverted.
Webhook handler: https://jarvis.orbishosting.com/webhook.php (HMAC secret: 4c8805f0285214ff0a0602b5880270b935f36a896946c7f1)
Deploy queue: /tmp/jarvis-deploy-queue.txt | Runner: /usr/local/bin/jarvis-deploy.sh (cron every min)
Deploy log: /home/jarvis.orbishosting.com/logs/deploy.log
For hotfixes that can't wait 1 min, SCP directly:
sshpass -p 'Gonewalk1974!@#' scp -o StrictHostKeyChecking=no /tmp/changed.php \
root@165.22.1.228:/home/site.com/public_html/changed.php
GitHub PAT (embedded in remote URLs): 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 — expires ~2026-08-20.
Infra repo: myronblair/infra — cloned at /opt/infra on DO server.
DO server backup: myronblair/do-server-config — scripts, systemd units, WireGuard, OLS vhosts, cron, MySQL creds + 8-phase restore wizard. Weekly Sunday 4am. Launcher: /usr/local/bin/do-server-backup.
Gitignored credentials (never in GitHub): api/config.php (JARVIS, epictravelexpeditions), config/database.php (tomsjavajive).
JARVIS System
Iron Man-style AI dashboard at https://jarvis.orbishosting.com. All files on DO at /home/jarvis.orbishosting.com/.
Architecture:
public_html/api.php— API router; hassession_write_close()guard (must skip forauthendpoint to prevent LSAPI session deadlock)api/config.php— all credentials/constants (gitignored)api/endpoints/chat.php— 4-tier AI: KB intent → Ollama (10.48.200.95:11434) → Groq (compound-beta-mini) → Claude API; includes Tier 0.7 planner intents (tasks/appointments/briefing)api/endpoints/agent.php— push-based agent registration/heartbeat/metricsapi/endpoints/alerts.php— auto-generates alerts (CPU >85%, RAM >85%, disk >88%, offline agents, site down); dispatches restart commands to agents when their services failapi/endpoints/facts_collector.php— runs every 3 min via cron; collects agent metrics, KB facts, Proxmox/HA/Ollama status, and all 7 site HTTP health checksapi/endpoints/stats_cache.php— runs every 5 min via cron; weather/news/Proxmox cache refreshapi/endpoints/planner.php— tasks & appointments CRUD; routes:planner/tasks,planner/appointments,planner/today,planner/doneapi/endpoints/ha.php— HA entity list reads fromha_entitiestable (real-time agent push); service calls go direct to HA_URL (http://orbisne.fortiddns.com:8123)
Voice system (index.html):
- Continuous SpeechRecognition; mic stays open always (mute toggle button)
- Phase 1 wake: say "wake up JARVIS" or "daddy's home" → activates voice mode once
- Phase 2 command: say "JARVIS [command]" → executes; opens 17-second free-listen window (no prefix needed for follow-ups)
- After 30 min of no commands → voice sleeps; full wake phrase required again
- Mic paused during ElevenLabs TTS playback (
isSpeakingguard) to prevent feedback loop - Auto-reload after 5 min idle is silent (no greeting speech)
Planner system (2026-05-31):
- DB tables:
tasks(id, title, notes, category, priority, status, due_date, due_time, completed_at) andappointments(id, title, description, category, start_at, end_at, location, all_day, reminder_min, alerted) - Voice commands: "add task [title]", "my tasks", "mark [x] done", "schedule [title] on [date]", "my calendar", "daily briefing"
- Home page: small top-bar badge "N TASKS · N APPTS" when items due today (no panel added)
- Admin CRUD at
/adminunder PLANNER section → TASKS and APPOINTMENTS tabs
Agent system: Agents phone home every 10s (heartbeat) / 30s (metrics) to https://165.22.1.228 with Host: jarvis.orbishosting.com header (bypasses Cloudflare). Config at /opt/jarvis-agent/config.json on each Linux agent.
Agent installer (one-liner for any Linux host): curl -sk https://jarvis.orbishosting.com/install-agent.sh | bash -s <hostname> <linux|homeassistant|proxmox>
Self-healing: /usr/local/bin/jarvis-watchdog.sh runs every 5 min (root cron). Restarts lsws/mysql/redis if down, restarts offline Proxmox VM agents via qm guest exec, inserts alerts to DB, rotates logs.
Watchdog log: /home/jarvis.orbishosting.com/logs/watchdog.log
JARVIS DB: jarvis_db on localhost. User: jarvis_user / J4rv1s_Pr0t0c0l_2026!. phpMyAdmin at /phpmyadmin (myron / Joker1974!!!).
Tables (18 total): agent_commands, agent_metrics, alerts, api_cache, appointments, conversations, ha_entities, kb_facts, kb_intents, kb_ollama_models, kb_preferences, known_commands, metrics_history, network_devices, registered_agents, tasks, users + (see schema for full column list)
Groq API note: Use model name compound-beta-mini directly — NOT groq/compound-beta-mini (that's OpenAI router syntax and will 404 on api.groq.com).
Tom's Java Jive
PHP e-commerce site. DB: toms_tjj_db / toms_tjj_user / +60wlPc+55e@gFq4. Key quirks:
- No
slugcolumn on products — URLs use?id=product_id - All tables must be
utf8mb4_unicode_ci— mixed collation causes MySQL error 1267 on JOINs wallet_transactions.typeandloyalty_transactions.typehave strict enums (see memory for values)
MediaStack
Automated media server on PVE1 VM 113. All traffic routes through WireGuard VPN → DO, bypassing home ISP.
SSH: From PVE1: ssh -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa root@10.48.200.35
Services:
| Service | Port | Login |
|---|---|---|
| qBittorrent | :8080 | admin / Joker1974!!! |
| Sonarr | :8989 | API key: b43e04350a594846b4ee95261c29e9e0 |
| Radarr | :7878 | API key: 53c4268360444feeae5f98c0cc24e0e3 |
| Prowlarr | :9696 | API key: 9d0ce6c5660743b5bf1c7951efc62252 |
Media paths: downloads → /media/downloads/complete | movies → /media/movies | tv → /media/tv
Jellyfin NFS mounts (VM 112, 10.48.200.33): /mnt/mediastack/movies and /mnt/mediastack/tv
WireGuard: wg0 IP 10.200.0.4 → CT110 (10.48.200.19:51821) → DO. Kill-switch active; LAN always allowed.
DNS: FortiGate blocks port 53 outbound. PVE1 runs dnsmasq on :53 → 100.100.100.100. MediaStack uses DNS=10.48.200.90.
Indexer: IPTorrents via Prowlarr (cookie auth). Prowlarr syncs to Sonarr + Radarr automatically.
GitHub: myronblair/mediastack (private) — config files, systemd units, README with full setup notes.
JARVIS agent quirks: needs jarvis_url, registration_key (f846a9aaf7ce9a61742c63c87c4186052a71d2a580c65518), ssl_verify: false in config.
Parker Slingshot Rentals
Admin portal at /admin/index.php uses HMAC-signed cookie auth (not PHP sessions — sessions were unreliable under LiteSpeed caching). Admin: admin / Parker2026!. DB: epic_parkersling / epic_parkersling / Joker1974!!!.
FusionPBX / FreeSWITCH
Production at 134.209.72.226. Web: https://fusion.orbishosting.com (admin / fY7XP5swgtpbzrYLhkeVYkA4744). SIP profiles served via Lua XML handler — config changes require deleting /var/cache/fusionpbx/FusionPBX.configuration.sofia.conf to force reload. Extension 1000 (Yealink T48S at 10.48.200.43) registered on production server via port 5080 with aggressive-nat-detection=true to bypass FortiGate SIP ALG.
SSH access: Port 22 firewalled from internet — only from 107.178.2.130 / 97.154.109.245. Relay all SSH through DO:
sshpass -p 'Gonewalk1974!@#' ssh -o StrictHostKeyChecking=no root@165.22.1.228 \
'sshpass -p "Joker1974!@#" ssh -o StrictHostKeyChecking=no root@134.209.72.226 "command"'
Backup: myronblair/fusionpbx-config — PostgreSQL dump (gzip, ~29MB) + FreeSWITCH configs + restore wizard. Weekly Sunday 5am. Launcher: /usr/local/bin/fusionpbx-backup.
Proxmox
PVE1 at 10.48.200.90, PVE2 at 10.48.200.91. Root login direct. Run commands inside VMs via:
qm guest exec <VMID> -- bash -c 'command'
Proxmox --nameserver must be space-separated: "8.8.8.8 1.1.1.1" (comma causes netplan bug).
Backup: myronblair/proxmox-config — shared cluster configs (VM .conf, storage, HA, SDN) + per-node (network, cron, systemd, scripts). Weekly Sunday 3am. Launcher: /usr/local/bin/proxmox-backup on both nodes.
PHP / OLS Runtime
CyberPanel uses lsphp85. Run PHP scripts directly with:
/usr/local/lsws/lsphp85/bin/lsphp /path/to/script.php
For PHP syntax checking use php8.3 -l file.php — lsphp segfaults on -l flag.
When a PHP endpoint uses ob_start() + header.php pattern, add ob_end_clean() before any CSV/JSON response output.
GitHub Repos
| Repo | Site | DB Schema |
|---|---|---|
| myronblair/jarvis | jarvis.orbishosting.com | db/schema.sql (15 tables) |
| myronblair/tomsjavajive | tomsjavajive.com | db/schema.sql (45 tables) |
| myronblair/epictravelexpeditions | epictravelexpeditions.com | db/schema.sql (7 tables) |
| myronblair/parkerslingshot | parkerslingshot.epictravelexpeditions.com | (no schema file — DB managed directly) |
| myronblair/parkerslingshotrentals | parkerslingshotrentals.com | db/schema.sql (10 tables) |
| myronblair/orbishosting | orbishosting.com | — |
| myronblair/orbis-hosting-portal | orbis.orbishosting.com | — |
| myronblair/tomtomgames | tomtomgames.com | db/schema.sql (22 tables) |
| myronblair/infra | server configs | cron, systemd, agent configs |
| myronblair/mediastack | MediaStack VM 113 | config/, systemd units, wg0.conf, README |
| myronblair/do-server-config | DO server backup | scripts, systemd, WG, OLS vhosts, restore.sh |
| myronblair/proxmox-config | PVE1+PVE2 backup | shared cluster configs + per-node, restore.sh |
| myronblair/fusionpbx-config | FusionPBX backup | PostgreSQL dump (gzip) + FS configs, restore.sh |
All repos are private. Each has config/vhost/ with OLS vhost config. The jarvis repo also has deploy/ (watchdog, deploy runner, systemd units) and agent/jarvis-agent.py.