- Python 69.6%
- Shell 26.6%
- Dockerfile 3.8%
- Replace personal-auto passthrough with 6 domain-specific routers:
auto-code-{low,high}, auto-agent-{low,high}, auto-work-{low,high}
- Add mysubs/claudecode/claude-haiku-4.5 passthrough
- Remove work-auto local complexity router (handled by cluster)
- Update comments referencing work-auto
|
||
|---|---|---|
| claude | ||
| compose | ||
| docs | ||
| profiles | ||
| scripts | ||
| skills | ||
| tests | ||
| zsh | ||
| .env.example | ||
| .gitignore | ||
| .justfile | ||
| a2a-wire.py | ||
| compose.yaml | ||
| config.yaml | ||
| Dockerfile | ||
| entrypoint.sh | ||
| pytest.ini | ||
| README.md | ||
Perch
A Docker Compose homelab stack for Hermes, specialist agents, model routing,
memory and tools. The gateway exposes an OpenAI-compatible API on
127.0.0.1:8642. ph is an optional zsh shortcut for the just recipes, not a
separate CLI.
Setup
Requires Docker with Compose; just is recommended for the commands below.
just setup # interactive wizard: image tools, services, memory
# or: cp .env.example .env # configure by hand
just up # one Hermes gateway
just health # checks a real model turn, not just liveness
At minimum, set API_SERVER_KEY (e.g. openssl rand -hex 32),
GATEWAY_BASE_URL (OpenAI-compatible URL ending in /v1), GATEWAY_API_KEY,
and model names served by that URL in .env. The example's
HERMES_MODEL=work-auto needs the local litellm profile and its
configured upstream; for a remote proxy, use a model it actually serves.
just setup generates service credentials but leaves the gateway URL, key and
model selection to you. It prints the next commands; it does not start the
stack.
config.yaml defines Hermes' default profile; .env supplies
deployment-specific URLs, keys and model names. See
configuration and services for the routing, profiles,
ports and persistence details. .env.example is the complete list of switches
and defaults.
Everyday commands
| Command | Purpose |
|---|---|
just up [mem0 litellm …] |
Start Hermes and selected optional Compose profiles |
just up agents [litellm …] |
Instead run four always-on agents with A2A |
just down [agents] |
Stop the stack (use agents for agents mode) |
just chat [--profile code-agent] |
Hermes CLI; validates profile names and reports active wrappers |
just agent claude|pi|aider [args] |
Run a coding CLI inside the container |
just mcp-setup |
Configure the remote MCP gateway for Hermes, Claude and Pi |
just run <subcommand> |
Run any Hermes subcommand, e.g. just run kanban watch |
just health [--quick] |
Check the gateway (--quick skips the model turn) |
just logs [service …] / just shell |
Diagnose a running container |
just rebuild [profiles …] |
Rebuild after Dockerfile, entrypoint or image-tool changes |
just agents-status / just peers |
Inspect the agents mode mesh |
just volumes ls|inspect|prune |
Inspect or delete persistent state (prune asks for confirmation) |
Examples:
just up litellm # local proxy; requires POSTGRES_PASSWORD
just up mem0 litellm # memory plus proxy
just up hindsight litellm # start memory service; see backend switch below
just up searxng browser # search and Chromium
just up litellm llamacpp # local GPU model behind LiteLLM
just chat --profile research-agent
just agent aider -m "refactor the parser"
just up and just up agents are mutually exclusive: both would claim port
8642. just restart restarts existing containers but does not load changes to
.env; run just up again to recreate them. A changed HERMES_WITH_* build
switch needs just rebuild (and preferably a new PERCH_TAG). Running plain
Compose is possible (docker compose up -d), but the recipes also set host
uid/gid and mount the directory where you invoked just as
/opt/data/workspace.
To make recipes available from any directory, source zsh/perch.zsh in your zsh
config. ph forwards to any recipe (ph up agents); phc, pha, phu,
phd, phr, phl, phst, phsh are shortcuts. Set PERCH_ZSH_SHORT=0
before sourcing to keep only long names.
Choose your stack
Each service is opt-in; a bare just up starts only Hermes. All published ports
bind to loopback.
| Profile | Host endpoint | What it does / required configuration |
|---|---|---|
litellm |
:4000 |
Model proxy and registry in compose/inference/litellm.config.yaml; set POSTGRES_PASSWORD, HOMELAB_PROXY_URL for hosted models |
mem0 |
:8000 |
Memory; set POSTGRES_PASSWORD, MEM0_JWT_SECRET, MEM0_HOST=http://localhost:8000 |
hindsight |
:8888 (UI :9999) |
Alternative memory; set POSTGRES_PASSWORD; run alongside litellm for LLM/embedding calls |
searxng |
:8080 |
Private search; set SEARXNG_URL=http://searxng:8080 |
browser |
:9222 |
Headless Chromium; set BROWSER_CDP_URL=http://172.28.99.10:9222 |
llamacpp |
:8081 |
GPU-backed llama.cpp model for local LiteLLM; configured for AMD/ROCm |
ollaya |
:11435 |
Separate gateway for typed decision models (routing/triage/intent), not chat; upstream CPU/CUDA image; TypeSafe-compatible POST /v1/systemone; registered in LiteLLM as a pass-through |
ollaya-rocm |
:11435 |
Experimental TUX-specific Ollaya build with llama.cpp HIP/ROCm support for GGUF decision models; mutually exclusive with ollaya (same port) |
headroom |
:8787 |
Optional context-compression proxy; must also set routing URLs |
mem0, hindsight and litellm pull in a single, unpublished Postgres
with separate databases. Starting Hindsight does not change Hermes' memory
provider: set HINDSIGHT_API_URL=http://hindsight:8888 to switch from the
mem0 provider in config.yaml. This same URL enables Pi and Aider's Hindsight
integrations. Keep it empty if you only want Hindsight's MCP endpoint
(http://hindsight:8888/mcp/<bank>/). See
memory and model routing.
The image includes all optional tools by default; HERMES_WITH_* flags in
.env.example select smaller builds (coding CLIs, language toolchains, DinD,
etc.). The code-agent and code-review-agent profiles depend on claude and
pi respectively. Image tools are independent of Compose service profiles;
selecting a service does not install a CLI. See
image variants.
Agents and integrations
Four profiles live under profiles/: general-agent, code-agent,
research-agent, code-review-agent. In single-container mode Kanban
dispatches profile workers; in just up agents each has a gateway, isolated
home and authenticated A2A endpoint. See agents and A2A for
ports, delegation and adding profiles.
Claude Code, Pi and Aider use your proxy, not a separate subscription. Claude
needs ANTHROPIC_BASE_URL without /v1; Pi and Aider inherit
GATEWAY_BASE_URL unless overridden. To share a remote streamable-HTTP MCP
endpoint across every running Hermes agent plus Claude and Pi, set
MCP_UPSTREAM_URL and optionally MCP_UPSTREAM_NAME, recreate the stack with
just up [agents], then run just mcp-setup. The command configures all three
clients and walks through their OAuth approvals; each client persists and
refreshes its own tokens. Optional Headroom, Caveman and Ponytail
operate at different layers, and enabling one for Hermes does not automatically
enable it for the coding CLIs. See
coding CLIs and token reduction.
To connect Neovim or another OpenAI client, use base URL
http://127.0.0.1:8642/v1, model hermes-agent, and bearer token
API_SERVER_KEY.
Development and reference
uv venv .venv --python 3.13
uv pip install --python .venv/bin/python pytest pyyaml
just test # static checks, no Docker
just test-integration # requires a running stack
just eval -k code-agent # profile evals; requires `just up agents`
- Configuration, services, routing and state
- Profiles, coding CLIs, compression and A2A
- Troubleshooting and implementation notes
.env.example— exhaustive environment variables, build switches and version pinscompose/— service definitions;profiles/— source of truth for agent configs