Skip to main content

gkg (GitLab Knowledge Graph)

Code intelligence service providing semantic code understanding for GitLab.

Overview

PropertyValue
Service TypeNative macOS (launchd)
Internal Port27495 (localhost only)
Docker Port27496 (via socat proxy)
External URLhttps://gkg.ravenhelm.dev
Userravenhelm
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 LimitLoadToSessionType key is essential for SSH-only users like ravenhelm. 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

Panels:

  1. Service Status (stat panel with probe success)
  2. Response Time (time series of probe duration)
  3. HTTP Response Code (stat panel)
  4. Uptime History (time series of probe success over time)
  5. 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