Reusable skill for installing Nous Research Hermes Agent on any Linux VPS with: - Custom OpenAI-compatible LLM gateway (e.g. LiteLLM, LocalAI, OpenRouter) - Telegram bot gateway (systemd 24/7 service) - GitHub CLI authentication
All lessons from real deployments baked in — no guesswork on interactive prompts, root restrictions, tool-calling API quirks, or Windows encoding issues.
install-hermes-vps/
├── README.md ← this file
├── .env.example ← copy → .env, fill in credentials
├── vps_ssh.py ← SSH runner (needs paramiko)
├── claude-command/
│ └── install-hermes-vps.md ← Claude Code slash command
└── scripts/
├── _01_install.sh ← Phase 1: install Hermes
├── _02_config_provider.sh ← Phase 2: configure LLM provider (Hermes ≥0.16 OK)
├── _03_gateway.sh ← Phase 3: Telegram systemd service
├── _04_ghauth.sh ← Phase 4: GitHub CLI auth (tự cài gh nếu thiếu)
├── _engine_tools.sh ← Phase 4b (ENGINE, chung mọi product): cài gws CLI + creds dir (chưa login/key)
├── _extract_bundle.sh ← Phase 5a: giải nén _bundle.tgz đã upload tại /opt/ai-os
├── _load_ceo.sh ← Phase 5b CANONICAL: nạp bundle layout products/ceo
│ (tạo lib symlink, merge personalities, cwd, start+verify)
├── _05_load_bundle.sh ← (tên ổn định) → shim gọi _load_ceo.sh
└── azure/ ← biến thể sudo cho Azure (_05 → _load_ceo với SUDO=sudo)
Flow: build tarball → upload → _extract_bundle.sh → _load_ceo.sh.
1. Tại thư mục dist: tar --exclude=__pycache__ --exclude='*.pyc' -czf _bundle.tgz core products *.md BUILD.txt
(.env đã được build loại; vps_ssh.py --upload cũng tự bỏ qua .env/*.pyc khi đẩy thư mục — không lo rò secret).
2. Upload: python vps_ssh.py --upload _bundle.tgz /opt/ai-os/_bundle.tgz
⚠️ Windows: chạy từ PowerShell (Git Bash/MSYS bóp méo path remote /opt/... → C:/.../opt/...).
3. python vps_ssh.py --file scripts/_extract_bundle.sh rồi --file scripts/_05_load_bundle.sh (≡ _load_ceo.sh).
Cross-platform:
vps_ssh.py+ cácscripts/*.shchạy trên Windows, macOS, Linux. Windows:python/pip(PowerShell). macOS / Linux:python3/pip3(bash/zsh — không vướng quoting như PowerShell, không có cảnh báo CRLF). SSH: điền password (VPS_PASSWORD) hoặc key (VPS_SSH_KEY_PATH) trong.env— xem.env.example.
pip install paramiko # macOS/Linux: pip3 install paramiko
Windows:
Copy-Item "claude-command\install-hermes-vps.md" "$env:USERPROFILE\.claude\commands\"
macOS / Linux:
cp claude-command/install-hermes-vps.md ~/.claude/commands/
Copy to your project folder:
your-project/
├── .env ← copy from .env.example, fill in real values
├── vps_ssh.py ← copy from this package
└── scripts/ ← copy the scripts/ folder
.envcp .env.example .env
# Edit .env with your real VPS credentials and API keys
In Claude Code, navigate to your project and type:
/install-hermes-vps
Claude will walk through all 5 phases automatically.
Each script uses {{ENV:VARNAME}} placeholders. vps_ssh.py injects real values at runtime.
# Run a specific phase
python vps_ssh.py --file scripts/_01_install.sh
python vps_ssh.py --file scripts/_02_config_provider.sh
python vps_ssh.py --file scripts/_03_gateway.sh
python vps_ssh.py --file scripts/_04_ghauth.sh
python vps_ssh.py --file scripts/_engine_tools.sh # engine: gws CLI (chung mọi product)
Or run an inline command:
python vps_ssh.py --cmd "hermes --version && systemctl is-active hermes-gateway"
| Key | Required | Description |
|---|---|---|
VPS_IP_ADDRESS |
✅ | VPS IP address |
VPS_USER_NAME |
✅ | SSH username (usually root) |
VPS_PASSWORD |
✅ | SSH password |
LLM_API_KEY |
✅ | API key for LLM gateway |
LLM_BASE_URL |
✅ | LLM gateway base URL (e.g. https://gateway.example.com/v1) |
LLM_MODEL |
✅ | Codex/Responses API model (used with api_mode: codex_responses) |
TELEGRAM_BOT_TOKEN |
Optional | Telegram bot token from @BotFather |
TELEGRAM_OWNER_ID |
Optional | Numeric Telegram user ID (bot only accepts this user) |
GITHUB_TOKEN |
Optional | GitHub PAT with repo + workflow scopes |
| Issue | Fix |
|---|---|
UnicodeEncodeError (cp1252) on Windows |
vps_ssh.py already handles this with reconfigure(encoding='utf-8') |
Inline && commands fail on Windows |
Always use --file mode (never --cmd with && chains) |
| Empty output with pty | vps_ssh.py uses bash -l -c without pty — correct by design |
| HTTP 400 when agent uses tools | Use api_mode: codex_responses → routes through /v1/responses |
hermes gateway install hangs |
_03_gateway.sh pipes y\ny\n automatically |
| Refuses to run as root | _03_gateway.sh uses --system --force --run-as-user root |
| Wrong Telegram allowlist var | Use TELEGRAM_ALLOWED_USERS (not TELEGRAM_ALLOWED_CHATS) |
| Classifier blocks scripts with API keys | {{ENV:VAR}} placeholders — real values injected in-memory only |
| Issue | Fix (đã có sẵn trong script) |
|---|---|
hermes config get bị bỏ |
Dùng hermes config show (đã sửa trong _02) |
hermes run '...' bị bỏ |
One-shot = hermes -z 'PROMPT' (đã sửa trong _02 smoke test) |
Bundle: skill nằm 2 cấp (learn/ai-mentor) không được quét |
skills.external_dirs = LIST 3 cấp (skills, skills/learn, skills/operate) — _05 set bằng python (config set lưu list thành chuỗi → vô hiệu) |
| Gateway xưng "Hermes" + bỏ qua AGENTS.md | systemd WorkingDirectory phải = bundle (/opt/ai-os), KHÔNG phải ~/.hermes. terminal.cwd không đổi được. _05 sed lại + daemon-reload |
Tool-trace lộ ra chat (skill_view…) |
display.tool_progress: "off" (CHUỖI — off trần bị YAML hiểu thành bool false) |
Telegram bold: ** hiện thô ở clarify |
Tin THƯỜNG render **bold** (MarkdownV2); clarify dùng HTML+escape → viết PLAIN. SOUL hướng dẫn đúng. |
| Model chậm (~37s/lượt) | Gateway raw nhanh (1–3s) nhưng prompt ~17k token (47KB tool schemas) + model reasoning. gemini-* TREO/chậm qua Hermes. Để tối ưu: giảm tool/skill. |
| Deploy bundle lộ nội bộ | Upload dist/<client> đã lọc bằng vps_ssh.py --upload (SFTP) — KHÔNG git clone repo thô |
Windows/Git Bash: --cmd đa lệnh bị xé (;/&&/{{}}) → argparse "expected one argument", có khi vô tình gọi hermes local |
LUÔN --file — script content được PIPE nguyên khối (không qua shell splitting/argparse). Cần check nhanh thì viết 1 script .sh tạm rồi --file, đừng nhồi vào --cmd |
Windows: background Bash mất cwd → python vps_ssh.py ... không thấy file (No such file or directory) khi cwd reset về thư mục khác |
Gọi vps_ssh.py bằng ĐƯỜNG TUYỆT ĐỐI + --env <abs>/.env + --file <abs>/scripts/x.sh — không lệ thuộc cwd. Lỗi này xảy ra TRƯỚC khi kết nối → retry sạch, không để rác trên VPS |
Windows: upload remote /opt/... bị MSYS mangle thành C:/.../opt/... |
Chạy --upload từ PowerShell (không phải Git Bash); vps_ssh.py cũng có _demangle_remote nhưng PowerShell là chắc nhất |
api_mode: codex_responsesIf your LLM gateway's /chat/completions endpoint returns HTTP 400 when Hermes sends a tools parameter (common on gateways proxying OpenAI Responses API / GPT-5.5 "codex" models), set:
providers.yourprovider.api_mode: codex_responses
This tells Hermes to call /v1/responses instead, using the flat Codex tool schema. Works perfectly even when /chat/completions + tools is broken.
# Service
hermes gateway status / restart / stop
systemctl status hermes-gateway
journalctl -u hermes-gateway -f
tail -f ~/.hermes/logs/gateway.log
# Test
hermes -z 'Run bash: echo "hello from hermes"'
# Config
hermes config show
hermes config show