CLI Reference
The stylobot binary is a self-contained reverse-proxy + bot detection gateway. One AOT-compiled executable per platform; no .NET runtime needed on the host. Same binary the Linux apt repo installs and the same one the GitHub Releases page ships.
Install
# Debian/Ubuntu (apt repo, recommended)
curl -1sLf 'https://dl.cloudsmith.io/public/mostlylucid/stylobot/setup.deb.sh' | sudo bash
sudo apt update && sudo apt install stylobot
# macOS / Windows / Linux manual download
# https://github.com/scottgal/stylobot/releases
After install:
stylobot --version
stylobot man # full reference manual
Quick start
The shortest possible invocation is two positional args: the port the gateway listens on, and the upstream to proxy to.
# Demo mode (observe only, verbose logging, never blocks)
stylobot 5080 http://localhost:3000
# Production mode (blocking enabled at the configured threshold)
stylobot 5080 http://localhost:3000 --mode production
# Behind a Cloudflare quick-tunnel for public testing
stylobot 5080 http://localhost:3000 --tunnel
The gateway is then on http://localhost:5080 proxying to your upstream, with detection running on every request. Hit http://localhost:5080/_stylobot/ for the live dashboard.
Subcommands
| Command | What it does |
|---|---|
stylobot <port> <upstream> [opts] |
Run the gateway in the foreground. |
stylobot start <port> <upstream> [opts] |
Same, daemonised (background). -d / --daemon is the shorthand. |
stylobot stop |
Stop the running daemon. |
stylobot status |
Show whether the daemon is running and its PID. |
stylobot logs |
Tail the daemon log file. |
stylobot man |
Full reference manual. |
stylobot --version |
Print the binary version. |
stylobot --output-config <file> |
Dump the effective configuration (defaults + overrides) to a JSON file and exit. Useful for editing. |
stylobot llmtunnel [token] [opts] |
Start a local LLM agent (Ollama/LlamaSharp) exposed via a Cloudflare tunnel so a remote gateway can escalate to it. |
stylobot dashboard <url> [--api-key <k>] |
Open a remote-mode dashboard against another stylobot instance over its /api/v1/* surface. |
stylobot genkey |
Generate a random 32-byte base64 key (for BotDetection:SignatureHashKey). |
stylobot clear [--sessions] |
Wipe learned patterns. Add --sessions to also wipe sessions.db. |
stylobot setup [--check-only] [--force] |
Check and download any missing resources (LLM models, archetype YAMLs, etc). |
Flags
These are the flags the run-the-gateway invocation accepts. Most map 1:1 to a BotDetection:* configuration key.
| Flag | Purpose | Default |
|---|---|---|
--port <n> |
Listen port (positional arg also works). | required |
--upstream <url> |
Upstream to proxy to (positional arg also works). | required |
--mode <demo\|production> |
Detection mode. demo is observe-only; production enforces the configured action policy. |
demo |
--profile <name> |
Kestrel performance profile: balanced (default), api (no WebSockets, 64 KB body cap, 100/100 threads), site (10k WebSockets, 1 MB body, 120s keep-alive), highrisk (small body cap, 3s header timeout, 50/50 threads). |
balanced |
--policy <name> |
Default detection policy name (must exist in BotDetection:Policies). |
from config |
--threshold <0.0-1.0> |
Bot probability threshold. Above this counts as bot. | 0.7 |
--tunnel [token] |
Start a Cloudflare tunnel in front of the gateway. Bare --tunnel uses a one-shot quick tunnel; a named tunnel needs [token]. |
off |
--cert <path> |
TLS certificate (PEM or PFX). Enables HTTPS. | off |
--key <path> |
TLS private key (when --cert is PEM). |
off |
--cert-password <pw> |
PFX password. | off |
--config <path> |
Path to an appsettings.json override file. |
none |
--log-level <Trace\|Debug\|Information\|Warning\|Error> |
Serilog minimum level. | Information |
--llm <provider> |
LLM provider for escalation (ollama, llamasharp, openai, anthropic, azure). |
none |
--llm-key <key> |
API key for the LLM provider (when remote). | none |
--llm-url <url> |
Endpoint URL for the LLM provider (Ollama on a remote host, custom OpenAI-compatible URL). | provider default |
--model <name> |
Model name override. | provider default |
--origin-tunnel |
Treat the upstream as a Cloudflare origin tunnel (sets the right outbound headers). | off |
--enable-api |
Expose /api/v1/* REST endpoints (detect + read dashboard data) for a remote dashboard host. Requires at least one entry under BotDetection:ApiKeys. |
off |
-d / --daemon |
Fork to background and exit. Same as stylobot start .... |
off |
Environment variables
Every config key is exposed as an env var using the standard ASP.NET Core __ separator. The most common knobs:
| Variable | What it does |
|---|---|
STYLOBOT_PROFILE |
Kestrel profile (balanced/api/site/highrisk). Same as --profile. |
MODE |
demo or production. Same as --mode. |
BotDetection__BotThreshold |
Probability above which a request is treated as bot. 0.7 by default. |
BotDetection__AiDetection__Provider |
LLM provider. ollama, llamasharp, openai, anthropic, azure. |
BotDetection__AiDetection__Ollama__Endpoint |
Ollama HTTP URL (e.g. http://192.168.0.15:11434). |
BotDetection__AiDetection__Ollama__Model |
Ollama model name (e.g. gemma4:e2b). |
BotDetection__SignatureHashKey |
32-byte base64 key used to hash signatures (stable identity across restarts). Generate with stylobot genkey. |
ASPNETCORE_URLS |
Standard ASP.NET Core listen URL override. |
Env vars override --flags which override appsettings.json which override built-in defaults.
Common invocations
Drop in front of a Rails app on port 3000
stylobot 8080 http://localhost:3000 --mode production --profile site
Public API gateway, behind Cloudflare, blocking AI scrapers
stylobot 443 http://localhost:8080 \
--cert /etc/ssl/example.com.pem --key /etc/ssl/example.com.key \
--mode production --profile api --policy block-ai-scrapers
Remote LLM (Ollama on another host)
BotDetection__AiDetection__Provider=ollama \
BotDetection__AiDetection__Ollama__Endpoint=http://10.0.0.4:11434 \
BotDetection__AiDetection__Ollama__Model=gemma4:e2b \
stylobot 5080 http://localhost:3000 --mode production
Background daemon with logs to syslog
stylobot start 5080 http://localhost:3000 --mode production --policy throttle-stealth
stylobot status
stylobot logs
stylobot stop
Generate and edit the full effective config
stylobot --output-config /etc/stylobot/appsettings.json
# Edit the JSON, then re-run with --config pointing at it.
stylobot 5080 http://localhost:3000 --config /etc/stylobot/appsettings.json
Verifying detection works
Send a known bot UA against the gateway and check the response headers:
curl -is -A "curl/8.4.0" http://localhost:5080/ | grep -i ^x-bot
# X-Bot-Detection: true
# X-Bot-Probability: 0.82
# X-Bot-Risk-Band: VeryHigh
# X-Bot-Detectors: UserAgent,Ip,Heuristic
Watch the live dashboard in another tab while you send traffic:
http://localhost:5080/_stylobot/
More
- Running Locally: first-run smoke test on your laptop.
- Configuration: every
BotDetection:*key grouped by what it controls. - Troubleshooting: symptom-to-fix table for the common gotchas.
- Full FOSS docs: https://github.com/scottgal/stylobot/tree/main/docs
- Stylobot articles on the Mostlylucid blog: https://www.mostlylucid.net/blog/category/StyloBot