gkg (GitLab Knowledge Graph)
Code intelligence service providing semantic code understanding for GitLab.
Overview
| Property | Value |
|---|---|
| Service Type | Native macOS (launchd) |
| Internal Port | 27495 (localhost only) |
| Docker Port | 27496 (via socat proxy) |
| External URL | https://gkg.ravenhelm.dev |
| User | ravenhelm |
| Health Endpoint | /health |
Architecture
┌─────────────────────────────────────────────────────────────┐
│ odin │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ launchd │────▶│ gkg │────▶│ socat │ │
│ │ (manages) │ │ :27495/lo │ │ :27496/all │ │
│ └─────────────┘ └─────────────┘ └──────┬──────┘ │
│ │ │
│ ┌──────────────────────────────────────────────┼──────┐ │
│ │ Docker Network │ │ │
│ │ ┌─────────────┐ ▼ │ │
│ │ │ Traefik │◀───── host.docker.internal:27496 │ │
│ │ └──────┬──────┘ │ │
│ └─────────┼───────────────────────────────────────────┘ │
└────────────┼────────────────────────────────────────────────┘
│
▼
gkg.ravenhelm.dev (HTTPS)
Use Cases
- Code Navigation: Jump-to-definition, find references
- Code Intelligence: Semantic understanding of code structure
- GitLab Integration: Powers code intelligence features in GitLab
Quick Commands
# Check service status
launchctl list | grep gkg
# Health check (local)
curl -s http://localhost:27495/health
# Health check (via socat proxy)
curl -s http://localhost:27496/health
# Health check (external)
curl -s https://gkg.ravenhelm.dev/health
# View logs
tail -f ~/Library/Logs/gkg.log
# Restart service
launchctl kickstart -k user/$(id -u)/com.ravenhelm.gkg
# Stop service
launchctl bootout user/$(id -u)/com.ravenhelm.gkg
# Start service
launchctl bootstrap user/$(id -u) ~/Library/LaunchAgents/com.ravenhelm.gkg.plist
Configuration
LaunchAgent
/Users/ravenhelm/Library/LaunchAgents/com.ravenhelm.gkg.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.ravenhelm.gkg</string>
<key>ProgramArguments</key>
<array>
<string>/Users/ravenhelm/.local/bin/gkg</string>
<string>server</string>
<string>--port</string>
<string>27495</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/ravenhelm/Library/Logs/gkg.log</string>
<key>StandardErrorPath</key>
<string>/Users/ravenhelm/Library/Logs/gkg.log</string>
<key>LimitLoadToSessionType</key>
<array>
<string>Aqua</string>
<string>Background</string>
<string>LoginWindow</string>
<string>StandardIO</string>
<string>System</string>
</array>
</dict>
</plist>
Note: The
LimitLoadToSessionTypekey is essential for SSH-only users likeravenhelm. Without it, macOS only loads LaunchAgents in GUI (Aqua) sessions.
socat Proxy
/Users/ravenhelm/Library/LaunchAgents/com.ravenhelm.gkg-socat.plist:
The socat proxy exposes the localhost-bound gkg service on all interfaces so Docker containers can reach it via host.docker.internal.
socat TCP-LISTEN:27496,fork,reuseaddr TCP:localhost:27495
Traefik Routing
/Users/ravenhelm/ravenhelm/compose/traefik/dynamic/gkg.yml:
http:
routers:
gkg:
rule: "Host(\`gkg.ravenhelm.dev\`)"
service: gkg
entryPoints:
- websecure
tls:
certResolver: cloudflare
services:
gkg:
loadBalancer:
servers:
- url: "http://host.docker.internal:27496"
Monitoring
Prometheus (blackbox-exporter)
HTTP probe configured in blackbox-exporter scrape config:
- job_name: 'gkg'
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- http://host.docker.internal:27496/health
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:9115
Grafana Dashboard
- Dashboard: gkg Service Health
- UID: gkg-service
- URL: https://grafana.ravenhelm.dev/d/gkg-service
Panels:
- Service Status (stat panel with probe success)
- Response Time (time series of probe duration)
- HTTP Response Code (stat panel)
- Uptime History (time series of probe success over time)
- Response Time Distribution (histogram)
Health Check
# Full health check script
check_gkg() {
# Check launchd service
if ! launchctl list | grep -q com.ravenhelm.gkg; then
echo "ERROR: launchd service not running"
return 1
fi
# Check local port
if ! curl -sf http://localhost:27495/health > /dev/null; then
echo "ERROR: gkg not responding on localhost:27495"
return 1
fi
# Check socat proxy
if ! curl -sf http://localhost:27496/health > /dev/null; then
echo "ERROR: socat proxy not working on port 27496"
return 1
fi
echo "OK: gkg service healthy"
return 0
}
Troubleshooting
Service not starting
# Check if binary exists
ls -la ~/.local/bin/gkg
# Check launchd status
launchctl list | grep gkg
# View error logs
cat ~/Library/Logs/gkg.log
# Try running manually
~/.local/bin/gkg server --port 27495
Port already in use
# Find what's using the port
lsof -i :27495
# Kill existing process
pkill -f "gkg server"
socat proxy not working
# Check socat LaunchAgent
launchctl list | grep gkg-socat
# Test connectivity
nc -zv localhost 27496
# Restart socat
launchctl kickstart -k user/$(id -u)/com.ravenhelm.gkg-socat
Traefik not routing
# Test from inside Docker network
docker exec traefik wget -qO- http://host.docker.internal:27496/health
# Check Traefik logs
docker logs traefik 2>&1 | grep gkg
# Verify route is loaded
curl -s https://traefik.ravenhelm.dev/api/http/routers | jq '.[] | select(.name | contains("gkg"))'
Local Access (SSH Tunnel)
For development on ravenmask, an SSH tunnel provides local access:
/Users/nate/.claude/scripts/gkg-tunnel.sh maintains a tunnel from localhost:27495 to odin's gkg service.
# Check tunnel status
lsof -i :27495
# Manual tunnel (if LaunchAgent not running)
ssh -N -L 27495:localhost:27495 ravenhelm@100.115.101.81
Related
- Traefik - Reverse proxy configuration
- Prometheus - Metrics collection
- Grafana - Dashboard visualization
- GitLab - Integration target