KB LabsDocs

dev.config.json

Last updated April 7, 2026


kb-dev service definitions — ports, commands, dependencies, health checks, groups.

.kb/dev.config.json is the service catalog consumed by kb-dev, the Go binary that manages local development processes. Every long-running daemon in a KB Labs deployment (REST API, workflow daemon, marketplace, gateway, state daemon, Studio, etc.) plus its infrastructure dependencies (Qdrant, Redis, Docker containers) is declared here.

This is not the platform config. kb.config.json tells the platform which adapters to load; dev.config.json tells kb-dev which processes to start, how to health-check them, and what they depend on. They're separate files with separate schemas.

The reference file in this repo is .kb/dev.config.json — read it alongside this page for a real example.

Top-level shape

TypeScript
interface DevConfig {
  version: string;                       // schema version — '1.0.0' today
  name: string;                          // display name of the environment
  description?: string;
  groups: Record<string, string[]>;      // group name → list of service IDs
  services: Record<string, ServiceDef>;  // service ID → service definition
}

Groups

Groups exist so you can start related services in one command: kb-dev start infra boots everything tagged infra, kb-dev start backend boots all backend services. A service can belong to exactly one group; the group name is also declared on the service itself as service.group.

Typical groups (from the reference config):

JSON
{
  "groups": {
    "infra":     ["qdrant", "redis", "state-daemon"],
    "backend":   ["workflow", "rest", "marketplace", "gateway"],
    "ui":        ["studio"],
    "ui-web":    ["kb-web", "kb-docs", "kb-app"],
    "local":     ["host-agent"],
    "execution": ["runtime-server"]
  }
}

The rule of thumb is:

  • infra — stateful infrastructure that platform services depend on (vector DB, cache, state daemon).
  • backend — HTTP daemons that serve the platform API.
  • ui — the main Studio app.
  • ui-web — marketing and docs sites.
  • local — daemons meant to run on end-user machines (host agent).
  • execution — container-mode execution backends.

Names are arbitrary — you can add your own groups and kb-dev will pick them up.

Service definition

TypeScript
interface ServiceDef {
  name: string;                  // human-readable display name
  description?: string;
  group: string;                 // must match a group key
  type: 'node' | 'docker';       // how to run it
  command: string;               // shell command to start it
  stopCommand?: string;          // shell command to stop it (for docker containers)
  healthCheck: string;           // URL for http check, or shell command
  port: number;                  // TCP port it listens on
  url?: string;                  // full URL (display + quick-open in CLI)
  optional?: boolean;            // kb-dev start won't fail if this one can't start
  dependsOn?: string[];          // service IDs that must start first
  env?: Record<string, string>;  // env vars passed to the process
  container?: string;            // for docker: the container name
  api?: {                        // display metadata
    docs?: string;               // URL of OpenAPI spec or docs
    endpoints?: string[];        // list of example endpoints
  };
}

The definition is deliberately flat — no nesting, no inheritance. kb-dev reads it literally and treats each entry as an independent process.

type

Two types today:

  • 'node' — a plain Node.js process. kb-dev runs the command as a subprocess, captures stdout/stderr, tracks the PID, and probes healthCheck.
  • 'docker' — a Docker container. kb-dev runs the command (typically docker-compose up -d <name>) and uses container to track the container by name instead of by PID.

The distinction matters because lifecycle management differs: Node processes are killed by PID via kb-dev stop, containers are stopped via docker stop (or whatever stopCommand specifies).

command

The shell command to start the service. Multi-line commands are allowed — use && or ; to chain operations. Common patterns:

Node service built and ready:

JSON
"command": "node ./platform/kb-labs-rest-api/apps/rest-api/dist/index.js"

The path is relative to the workspace root. kb-dev always runs commands with the workspace root as CWD, so you don't need to cd around.

Dev mode via pnpm filter:

JSON
"command": "cd platform/kb-labs-studio && pnpm --filter kb-labs-studio-app dev"

Use this for services you want hot-reload on. Studio is the canonical example.

Docker container with cleanup:

JSON
"command": "docker stop qdrant 2>/dev/null || true && docker rm qdrant 2>/dev/null || true && docker-compose -f deploy/docker/docker-compose.yml up -d qdrant"

The || true suppresses errors when the container doesn't exist yet — first-run safety.

healthCheck

How kb-dev decides the service is ready.

HTTP URLkb-dev polls until it gets a 2xx response:

JSON
"healthCheck": "http://localhost:5050/api/v1/health"

Shell commandkb-dev runs the command; exit code 0 means healthy:

JSON
"healthCheck": "redis-cli ping"

Both forms are supported; the choice depends on the service. Most HTTP daemons expose /health (or /api/v1/health for the REST API); infrastructure like Redis or Postgres uses shell commands (redis-cli ping, pg_isready).

The health check runs on start (to know when the service is ready) and periodically afterwards (to catch crashes and trigger restarts if watchdog mode is enabled).

dependsOn

List of service IDs that must be healthy before this one starts. Forms a DAG — kb-dev topologically sorts the graph and starts services in order.

JSON
{
  "rest": {
    "dependsOn": ["workflow"]
  },
  "workflow": {
    "dependsOn": ["state-daemon"]
  },
  "state-daemon": {
    "dependsOn": ["redis"]
  }
}

When you run kb-dev start rest, kb-dev walks the dependency chain (rest → workflow → state-daemon → redis) and starts them bottom-up, waiting for each to pass its health check before moving on.

A dependsOn target that's optional doesn't block startup if it fails — kb-dev logs a warning and continues.

env

Environment variables passed to the subprocess. Values can reference other env vars (${KB_STATE_DAEMON_PORT}), but resolution happens in the shell, not inside kb-dev.

JSON
{
  "state-daemon": {
    "env": {
      "KB_STATE_DAEMON_PORT": "7777",
      "KB_STATE_DAEMON_HOST": "localhost"
    }
  }
}

These are merged with the process env that kb-dev itself was started with — don't repeat PATH or HOME unless you need to override them.

optional

When true, kb-dev treats a start failure as a warning instead of an error. Used for services that aren't strictly required in every dev setup:

JSON
{
  "redis": {
    "optional": true,
    "group": "infra"
  }
}

If Redis fails to start, kb-dev start infra still succeeds and continues to the next service. Downstream services can still depend on an optional — they'll start successfully if the optional dependency is missing, but their health check may reveal runtime errors later.

api (display metadata)

Optional block with links and endpoints shown in kb-dev status and the CLI's service-info view. Purely cosmetic — doesn't affect runtime.

JSON
{
  "api": {
    "docs": "http://localhost:5050/openapi.json",
    "endpoints": [
      "GET /api/v1/health",
      "GET /api/v1/routes",
      "POST /api/v1/workflows/runs"
    ]
  }
}

Use it to document the most useful endpoints and link to OpenAPI specs. It's the fastest way to give a new developer "here's where to look" context when they run kb-dev status.

Full example

A minimal entry for a typical platform service:

JSON
{
  "rest": {
    "name": "REST API",
    "description": "Main platform REST API",
    "group": "backend",
    "type": "node",
    "command": "node ./platform/kb-labs-rest-api/apps/rest-api/dist/index.js",
    "healthCheck": "http://localhost:5050/api/v1/health",
    "port": 5050,
    "url": "http://localhost:5050",
    "dependsOn": ["workflow"],
    "api": {
      "docs": "http://localhost:5050/openapi.json",
      "endpoints": [
        "GET /api/v1/health",
        "GET /api/v1/routes",
        "POST /api/v1/workflows/runs"
      ]
    }
  }
}

A Docker infrastructure service:

JSON
{
  "qdrant": {
    "name": "Qdrant Vector DB",
    "description": "Vector database for Mind RAG search",
    "group": "infra",
    "type": "docker",
    "container": "qdrant",
    "command": "docker stop qdrant 2>/dev/null || true && docker rm qdrant 2>/dev/null || true && docker-compose -f deploy/docker/docker-compose.yml up -d qdrant",
    "stopCommand": "docker stop qdrant",
    "healthCheck": "http://localhost:6333/",
    "port": 6333,
    "url": "http://localhost:6333"
  }
}

Adding a new service

  1. Pick a group. Usually one that already exists; make a new one only if nothing fits.
  2. Pick a port. Make sure it doesn't collide with other services. The convention is backend on 4000–8000, UI on 3000s.
  3. Add an entry to dev.config.json with the required fields (name, group, type, command, healthCheck, port).
  4. Update the group's list to include your new service ID.
  5. Add dependsOn if your service needs another service to be healthy first.
  6. Run kb-dev start <your-service> to verify it boots.

If the service is a platform daemon, it should also have a ServiceManifest (kb.service/1) in its source — that manifest is what lets kb-dev know how to install and update it when the service is published to npm. See Services → Overview for the relationship between ServiceManifest and dev.config.json.

kb-dev commands that read this file

Everything in kb-dev reads dev.config.json:

CommandUses
kb-dev start [service|group]services, groups, dependsOn
kb-dev stop [service|group]services, stopCommand, container
kb-dev restart [service]all of the above
kb-dev statusservices, healthCheck, port, url, api
kb-dev logs [service]services (to know what process to tail)
kb-dev ensure [service]services, dependsOn, healthCheck — idempotent start
kb-dev ready [service]services, healthCheck — block until healthy
kb-dev doctorservices — check env, ports, dependencies

None of them modify the file. To change the environment, edit dev.config.json and re-run the command.

Gotchas

  • cwd is always the workspace root. Don't rely on relative paths that assume you're inside a sub-directory; prefix with cd if you need to.
  • Commands run in a shell. Use && and || true for chaining, but be aware that this isn't a cross-platform shell — the dev config assumes Unix-style shells. Windows users need WSL or similar.
  • Port collisions are silent. If two services declare the same port, kb-dev won't warn you at startup — it'll just fail health-checking the second one. Run kb-dev doctor to detect collisions explicitly.
  • Docker cleanup is your responsibility. stopCommand runs when you say kb-dev stop, but if kb-dev crashes mid-run, you may end up with orphaned containers. docker ps -a and manual cleanup.
  • dev.config.json is not versioned by plugins. Plugin services need to be added manually. Future versions may auto-generate the file from ServiceManifest declarations at install time.
dev.config.json — KB Labs Docs