Track sleeping_since (ISO timestamp) in ServerState; auto-cleared by _set() whenever state leaves sleeping. Frontend runs a 1s interval showing elapsed time as "Xs", "Xm Ys", or "Xh Ym" in a new ASLEEP stat row (visible only during state-sleeping). Timer survives page reload via server-side timestamp. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Llamagochi
A browser-based virtual pet llama that mirrors a running llama-server instance by tailing its log file. The llama animates differently depending on what the server is doing — loading a model, processing a prompt, generating tokens, sleeping, or erroring out.
IDLE PROCESSING PROMPT GENERATING SLEEPING
ear twitches eyes scan left/right mouth talks zzz floats up
progress bar shown tail wags
Requirements
- Python 3.10+
llama-serverrunning in router mode (the multi-model router that logscmd_child_to_router:state:{...}JSON lines)- The log file must be accessible from the machine running Llamagochi (local path or a mount)
Installation
git clone <repo>
cd llamagochi
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
Running
python server.py --log /path/to/llama-server.log
The web UI is then available at http://localhost:8080.
Options
| Flag | Default | Description |
|---|---|---|
--log PATH |
— | Path to the llama-server log file (required unless set in config.json or $LLAMAGOCHI_LOG) |
--port PORT |
8080 |
HTTP port to listen on |
--reopen-log |
off | Close and reopen the log file on every poll cycle. Use this when the log is on a network filesystem (sshfs, NFS) that caches file content at open time |
Configuration file
Instead of passing --log every time, create config.json in the project directory:
{
"log": "/path/to/llama-server.log",
"reopen_log": true
}
reopen_log in the config is equivalent to --reopen-log on the command line. CLI flags take precedence.
Environment variable
export LLAMAGOCHI_LOG=/path/to/llama-server.log
python server.py
Reverse proxy (HTTPS)
Llamagochi uses WebSocket (/ws) and HTTP polling (/state). Both must be proxied. Example nginx snippet:
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
The frontend automatically uses wss:// when the page is served over HTTPS.
States
| State | What it means |
|---|---|
idle |
Server is up, no active request |
waiting |
Router received a request, slot not yet assigned |
loading |
Model is loading into VRAM (progress bar shown) |
warming_up |
Model weights loaded, running warmup pass |
processing_prompt |
Evaluating the prompt (progress bar 0–100%) |
generating |
Generating tokens |
sleeping |
Server idle-timeout reached, model evicted |
unloading |
LRU eviction in progress |
error |
Model failed to load |
offline / LOG OFFLINE |
Llamagochi cannot read the log file |
Connection status dot (top-right of screen)
| Colour | Meaning |
|---|---|
| Green | WebSocket live — real-time updates |
| Amber | WebSocket down, falling back to HTTP polling every 2 s |
| Red | Both WebSocket and HTTP polling are unreachable |
When the WebSocket reconnects, polling stops automatically.
Log file format
Llamagochi expects the log produced by llama-server router mode, optionally prefixed with timestamps by the ts utility:
[2026-06-22 20:09:31] [51201] 3.13.636.722 I srv update_slots: all slots are idle
[2026-06-22 20:09:31] 339.42.030.150 I srv proxy_reques: proxying request to model ...
Lines prefixed with [PORT] are child-process lines; unprefixed lines are router-level. Both are understood.
Running tests
pytest
32 tests covering the log parser state machine and log watcher.