Manage local development proxies using Caddy server's Admin API. Use when users need to allocate localhost ports, create reverse proxies for local dev servers, track which ports are in use across Claude Code sessions, or access apps via friendly URLs like myapp.localhost. Triggers on "set up a proxy", "allocate a port", "what's running on localhost", "register my app", or any Caddy configuration task.
Install
npx skillscat add muninn-huginn/caddy-skill/caddy Install via the SkillsCat registry.
Caddy Local Proxy Manager
Manage local development reverse proxies via Caddy's Admin API at localhost:2019.
Session Naming
When registering a proxy, use one of these approaches:
- User provides name: Use exactly what they specify
- Generate from context: Use project directory name + short random suffix (e.g.,
myapp-x7k2)
Example generation:
NAME="$(basename "$PWD" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g')-$(head -c4 /dev/urandom | xxd -p | head -c4)"Quick Reference
| Task | Command |
|---|---|
| Check status | curl -sf http://localhost:2019/config/ |
| List routes | curl -sf http://localhost:2019/config/apps/http/servers/local_proxies/routes |
| Add route | POST /config/apps/http/servers/local_proxies/routes |
| Delete route | DELETE /id/proxy_<name> |
Workflows
Check Caddy Status
curl -sf http://localhost:2019/config/ 2>/dev/nullIf fails: "Caddy not running. Install: brew install caddy, Start: caddy start"
List All Proxies
curl -sf http://localhost:2019/config/apps/http/servers/local_proxies/routes 2>/dev/nullDisplay as table: Name | URL | Backend
Register a Proxy
Get or generate name (ask user or generate from project + random)
Find available port (if not specified):
for port in $(seq 3000 3100); do
lsof -i :$port > /dev/null 2>&1 || { echo $port; break; }
done- Initialize server if needed:
curl -sf http://localhost:2019/config/apps/http/servers/local_proxies > /dev/null 2>&1 || \
curl -sf -X POST http://localhost:2019/load \
-H "Content-Type: application/json" \
-d '{"apps":{"http":{"servers":{"local_proxies":{"listen":[":80"],"routes":[]}}}}}'- Add route (replace NAME and PORT):
curl -sf -X POST "http://localhost:2019/config/apps/http/servers/local_proxies/routes" \
-H "Content-Type: application/json" \
-d '{"@id":"proxy_NAME","match":[{"host":["NAME.localhost"]}],"handle":[{"handler":"reverse_proxy","upstreams":[{"dial":"localhost:PORT"}]}],"terminal":true}'- Report: "Registered: http://NAME.localhost → localhost:PORT"
Remove a Proxy
curl -sf -X DELETE "http://localhost:2019/id/proxy_NAME"Update a Proxy
Delete then re-add with new port.
Route JSON Structure
{
"@id": "proxy_<name>",
"match": [{"host": ["<name>.localhost"]}],
"handle": [{"handler": "reverse_proxy", "upstreams": [{"dial": "localhost:<port>"}]}],
"terminal": true
}Error Handling
| Error | Solution |
|---|---|
| Caddy not running | brew install caddy && caddy start |
| Port 80 denied | sudo caddy start |
| Route exists | Ask to update or pick different name |
Platform Notes
- macOS:
*.localhostresolves to 127.0.0.1 automatically - Linux: May need
/etc/hostsentries