Developer Guide
Set up a complete local development environment with a single command.
Table of contents
- Overview
- Prerequisites
- Quick Start
- Step-by-Step Walkthrough
- Command Reference
- Configuration
- Useful Commands
- Troubleshooting
- Architecture
- MCP Integration
Overview
The kedge dev command creates a complete local development environment with:
- Hub cluster — A kind cluster running kedge-hub with embedded kcp
- Agent cluster — A second kind cluster for deploying the kedge-agent
Both clusters share a Docker network, allowing the agent to connect to the hub.
Prerequisites
| Tool | Description |
|---|---|
| Docker | Container runtime (must be running) |
| kind | Kubernetes in Docker (installed automatically by the command) |
| Helm | For deploying the agent chart |
Quick Start
1. Build the CLI
make build-kedge
2. Create the development environment
./bin/kedge dev init --worker-count 1 --chart-path deploy/charts/kedge-hub
This creates two kind clusters:
kedge-hub— Hub cluster with kedge-hub installedkedge-agent— Worker cluster (empty, ready for agent deployment)
The default --worker-count is 0 (hub only). Use --worker-count N to
spin up additional worker kind clusters when developing agents.
3. Follow the printed instructions
The command outputs step-by-step instructions for:
- Setting up kubeconfig
- Logging into the hub
- Creating a site
- Deploying the agent
Step-by-Step Walkthrough
Set kubeconfig to access hub cluster
export KUBECONFIG=kedge-hub.kubeconfig
Login to authenticate to the hub
kedge login --hub-url https://kedge.localhost:9443 --insecure-skip-tls-verify --token=dev-token
Create a site in the hub
kedge site create my-site --labels env=dev
Wait for the site kubeconfig secret and extract it
kubectl get secret -n kedge-system site-my-site-kubeconfig \
-o jsonpath='{.data.kubeconfig}' | base64 -d > site-kubeconfig
The secret is created automatically after the site is registered.
Deploy the agent into the agent cluster
First, create a namespace and secret with the site kubeconfig:
kubectl --kubeconfig kedge-agent.kubeconfig create namespace kedge-system
kubectl --kubeconfig kedge-agent.kubeconfig create secret generic site-kubeconfig \
-n kedge-system \
--from-file=kubeconfig=site-kubeconfig
Then install the agent Helm chart:
helm install kedge-agent deploy/charts/kedge-agent \
--kubeconfig kedge-agent.kubeconfig \
-n kedge-system \
--set agent.edgeName=my-edge \
--set agent.hub.existingSecret=site-kubeconfig
Verify the agent is connected
kedge site list
kedge site get my-site
The site should show tunnelConnected: true and have a recent heartbeat.
Command Reference
kedge dev init
Initializes a local kedge environment.
kedge dev init [flags]
Flags:
| Flag | Default | Description |
|---|---|---|
--hub-cluster-name |
kedge-hub |
Name of the hub kind cluster |
--agent-cluster-name |
kedge-agent |
Name of the worker (agent) kind cluster(s) |
--worker-count |
0 |
Number of worker kind clusters (0 = hub only) |
--chart-path |
oci://ghcr.io/faroshq/charts/kedge-hub |
Hub Helm chart (local path or OCI) |
--chart-version |
(auto) | Helm chart version (for OCI charts) |
--image |
ghcr.io/faroshq/kedge-hub |
Hub container image |
--tag |
(auto) | Hub image tag |
--kind-network |
kedge-dev |
Docker network for kind clusters |
--wait-for-ready-timeout |
2m |
Timeout waiting for cluster readiness |
--agent-count is accepted as a deprecated alias for --worker-count.
Examples:
# Hub-only local environment (end users)
kedge dev init
# Hub + 1 worker (typical developer setup)
kedge dev init --worker-count 1 --chart-path deploy/charts/kedge-hub
# Hub + 3 workers
kedge dev init --worker-count 3
# Published OCI chart, pinned version
kedge dev init --chart-path oci://ghcr.io/faroshq/charts/kedge-hub --chart-version 0.1.0
kedge dev update
Upgrades the kedge-hub Helm release on the existing hub kind cluster (image, tag, chart version, …). Kind clusters themselves are not modified.
kedge dev update [flags]
kedge dev delete
Deletes the local kedge environment.
kedge dev delete [flags]
This removes the hub kind cluster, any worker kind clusters that were
created (pass the same --worker-count you used at init time), and cleans
up kubeconfig files.
Configuration
Hub cluster
The hub cluster is configured with:
- Port mappings:
localhost:9443-> hub service - NodePort service on port 31443
- Self-signed TLS certificate
- Static auth token:
dev-token - Dev mode enabled (relaxed security)
Agent cluster
The agent cluster is a plain kind cluster with no special configuration. The agent is deployed via Helm chart and connects to the hub through the shared Docker network.
Docker network
Both clusters are created on the kedge-dev Docker network, allowing them to communicate using container IPs. The hub’s internal IP is displayed after cluster creation.
Useful Commands
# List all sites
kedge site list
# Get site details
kedge site get my-site
# Check agent logs
kubectl --kubeconfig kedge-agent.kubeconfig logs \
-n kedge-system \
-l app.kubernetes.io/name=kedge-agent -f
# Check hub logs
kubectl --kubeconfig kedge-hub.kubeconfig logs \
-n kedge-system \
-l app.kubernetes.io/name=kedge-hub -f
# Delete the dev environment
kedge dev delete
Troubleshooting
Tilt-cluster E2E: a resource never becomes Ready
The Tilt E2E workflow waits for each Tilt resource (e.g. kedge-hub) to reach
update=ok runtime=ok. When one times out, the wait helper now prints a
collapsible diagnostics for stuck resource '<name>' group in the job log
containing: the resource’s own Tilt logs (e.g. the hub’s klog stdout, which
shows where bootstrap stalled), a cluster-wide kubectl get pods -A, a
describe + log tail for every non-Running pod, and the recent cluster events.
Open that group first when a run times out — it usually points straight at the
stuck step (slow kcp bootstrap, a crashlooping pod, an image pull, …).
Hub chart not found
If you see:
Error: failed to locate OCI chart: ghcr.io/faroshq/charts/kedge-hub:0.1.0: not found
Use the local chart path instead:
kedge dev init --chart-path deploy/charts/kedge-hub
Agent can’t connect to hub
- Check the hub is running:
kubectl --kubeconfig kedge-hub.kubeconfig get pods -n kedge-system - Verify the site kubeconfig has the correct hub IP:
cat site-kubeconfig | grep serverThe server URL should use the hub’s Docker network IP, not
localhost. - Check agent logs:
kubectl --kubeconfig kedge-agent.kubeconfig logs \ -n kedge-system \ -l app.kubernetes.io/name=kedge-agent
Site kubeconfig secret not created
The secret is created by the hub’s RBAC controller after the site is registered. Wait a few seconds and check:
kubectl get secret -n kedge-system site-my-site-kubeconfig
If it doesn’t appear, check hub logs for errors.
Cluster already exists
If the clusters already exist, the command will skip creation and reuse them. To start fresh:
kedge dev delete
kedge dev init --chart-path deploy/charts/kedge-hub
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Docker Network (kedge-dev) │
│ │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ kedge-hub cluster │ │ kedge-agent cluster │ │
│ │ │ │ │ │
│ │ ┌───────────────────┐ │ │ ┌───────────────────┐ │ │
│ │ │ kedge-hub │ │◄───┼──│ kedge-agent │ │ │
│ │ │ (StatefulSet) │ │ │ │ (Deployment) │ │ │
│ │ └───────────────────┘ │ │ └───────────────────┘ │ │
│ │ │ │ │ │
│ │ Port: 31443 (NodePort) │ │ │ │
│ └───────────┬─────────────┘ └─────────────────────────┘ │
│ │ │
└──────────────┼──────────────────────────────────────────────────┘
│
▼
localhost:9443
(for CLI access)
The agent establishes a reverse WebSocket tunnel to the hub, allowing the hub to proxy API requests to the agent’s cluster.
MCP Integration
kedge exposes all connected Kubernetes clusters as a single Model Context Protocol (MCP) server.
URL format
https://<hub>/services/mcp/<workspace-cluster-id>/apis/kedge.faros.sh/v1alpha1/kubernetesmcps/<name>/mcp
Getting the URL
kedge mcp url --name default
This prints the URL and a ready-to-use claude mcp add command with your bearer token.
Kubernetes resource
A default Kubernetes object is auto-created in every tenant workspace. It selects which kubernetes-type edges are included via spec.edgeSelector (empty = all connected kubernetes edges).
How it works
- The hub’s MCP virtual workspace handler validates the bearer token.
- Lists all
Edgeobjects in the workspace, filters tospec.type: kubernetes+ connected + label selector. - Builds a
MultiEdgeKedgeEdgeProviderthat dials each edge over its revdial tunnel. - Passes control to
kubernetes-mcp-serverwhich implements the MCP protocol.
See DEVELOPERS.md for the full internals reference.