A small self-hosted HTTP service that acts as a multi-provider search router.
It exposes a single OpenSearch description that you can register in your browser's address bar. When you type a query, a short prefix decides which upstream search engine handles it.
Browsers let you add at most one default search engine. If you regularly
search Urban Dictionary, GitHub, and Steam, you end up adding three
engines and learning three keywords per browser. This service collapses
that into a single <link rel="search"> and a unified prefix grammar
that works in any browser, on any device.
| Prefix | Provider | Upstream |
|---|---|---|
ud |
Urban Dictionary | urbandictionary.com/define.php |
gh |
GitHub | github.com/search |
steam |
Steam Store | store.steampowered.com/search |
Both ud foo bar and ud:foo bar work. With no recognized prefix the
query falls through to the configured default provider.
| Method | Path | Purpose |
|---|---|---|
| GET | / |
Landing page advertising the OSD via <link> |
| GET | /search?q=... |
302 redirect to the chosen provider |
| GET | /providers |
JSON list of registered providers |
| GET | /opensearch.xml |
Unified OSD pointing at /search |
| GET | /opensearch/{provider}.xml |
Per-provider OSD pointing directly upstream |
| GET | /healthz, /readyz |
Liveness & readiness probes |
cp config.example.yaml config.yaml
# edit server.public_url to match your deployment
just dev
# then open http://localhost:8080/ in a browser and add the search engine
Config is YAML. Every field can be overridden by an environment variable
prefixed APP_ with . replaced by _, e.g. APP_SERVER_PORT=9000.
server:
host: "0.0.0.0"
port: 8080
public_url: "https://search.example.com" # used in OSD XML
search:
default_provider: gh # ud | gh | steam
log:
level: info
format: human # human | json
just build # produces ./huntsman
just test # unit tests
just lint # golangci-lint
just docker-build # container image
just docker-run # docker compose up -d --build