NewLive coding: one link for the candidate, one shared sandbox for everyone.See it ↓
KendorDocs

kendor.yaml reference

For challenge authors ·

Every key kendor.yaml accepts, from runtime and services to routing, databases and sandbox, with types, defaults and the rules checked on save.

kendor.yaml sits at the root of a challenge's project and tells the sandbox what to run: one language and version, optional extra languages and databases, and one or more services with their install, dev and test commands. Only version, runtime and services are required. Kendor checks the whole file when you save, and a file with errors is not saved.

Where the file lives and when it applies

The file is kendor.yaml at the workspace root. In an uploaded zip or imported repository, Kendor also accepts the kendor.yml spelling.

In the challenge editor, open Settings and choose Configure runtime…. The Runtime configuration dialog has a Form tab and a Raw YAML tab; saving writes kendor.yaml and restarts the preview. If you edit the file by hand instead, a kendor.yaml changed banner appears, because the sandbox still runs the previous setup until you choose Save & restart.

When you save, Kendor runs the checks listed under Validation rules and also checks that every language and database version is one Kendor offers. Each problem is reported with its path in the file, for example services.web.dev.port.

The copy of kendor.yaml inside a running sandbox is regenerated from the saved configuration each time the sandbox starts, so it always shows what the sandbox is running.

Tip. Start the file with # yaml-language-server: $schema=https://kendor.dev/config-schema/v1. Editors that use the YAML language server then offer autocomplete and inline errors for every key on this page.

What candidates can change

A candidate can edit kendor.yaml in their own workspace. Only four top-level keys are read from their copy: install, services, preview and routing. Their changes apply when the sandbox restarts, and only if the merged file still passes validation; otherwise your configuration stays in place. runtime, toolchains, databases, sandbox and kendor always come from your file, and so do test commands: any test a candidate writes is dropped, and your test commands are kept on the services you defined.

A complete example

A Node.js API and a Vite frontend, with PostgreSQL and Valkey, plus a Python worker:

kendor.yaml
# yaml-language-server: $schema=https://kendor.dev/config-schema/v1
version: 1
runtime:
  type: node
  version: "22"
  packageManager: npm
toolchains:
  - type: python
    version: "3.12"
databases:
  - type: postgres
    version: "18"
    name: shop
    init: db/init
  - type: valkey
    version: "9"
services:
  api:
    workDir: api
    install:
      commands:
        - npm ci
    dev:
      command: node --watch src/server.js
      port: 3000
      env:
        vars:
          WEB_URL: routing.web.url
          CACHE_URL: databases.valkey.url
          LOG_LEVEL: lit:debug
    test:
      command: node --test
  web:
    workDir: web
    install:
      commands:
        - npm ci
    dev:
      command: npm run dev -- --port $PORT
      port: 5173
      env:
        vars:
          VITE_API_URL: routing.api.url
    publicEnvPrefix: VITE_
  worker:
    workDir: worker
    install:
      commands:
        - pip install --user -r requirements.txt
    dev:
      command: python worker.py
preview:
  service: web
routing:
  - path: /api
    service: api
  - path: /
    service: web
requests:
  - name: List products
    url: http://localhost:3000/api/products
  - name: Create a product
    method: POST
    url: http://localhost:3000/api/products
    headers:
      Content-Type: application/json
    body: '{"name": "Mug", "price": 12}'
kendor:
  gradeService: api

Top-level keys

Unknown keys are rejected everywhere in the file except inside kendor.

Key Type Required Description
version number Yes The file format. Must be 1.
runtime mapping Yes The main language and its version.
toolchains list No Extra languages in the same sandbox.
databases list No PostgreSQL and Valkey servers inside the sandbox.
install mapping No Commands run once at the workspace root before any service.
services mapping Yes The processes to install, start and test, keyed by name. At least one.
preview mapping When there are 2+ services Which service the preview pane shows.
routing list No Path prefixes on the preview address and the service each one goes to.
sandbox mapping No Docker or Kubernetes inside the sandbox.
requests list No Example HTTP requests for the editor's Requests tab.
kendor mapping No Author-only settings.

Note. Write versions as quoted strings: version: "3.12", not version: 3.12. Unquoted, YAML reads 3.12 as a number and the file fails validation. The top-level version: 1 is the exception; it must be the number 1.

runtime

Key Type Required Default Description
type string Yes One of node, php, python, go, java, rust, cpp.
version string Yes A version Kendor offers for that language, such as "22" or "1.27". See Languages and versions.
packageManager string No Not set npm, pnpm, yarn or bun. Recorded for reference; what actually installs is your install commands.

A challenge's language is fixed when it's created, but its version isn't: when runtime.type is the challenge's language, runtime.version decides which version the sandbox runs.

toolchains

A list of extra languages, each with its compiler, tools and language server on the PATH beside the main one. Use it for a Go service next to a Node app, or Node for asset builds in a PHP project.

Key Type Required Description
type string Yes Same choices as runtime.type.
version string Yes A version Kendor offers for that language.

Each language may appear once across runtime and toolchains.

databases

A list of database servers that run inside the sandbox on 127.0.0.1 and start before any install command. See Databases in the sandbox for connection details.

Key Type Required Default Description
type string Yes postgres or valkey. Each type at most once.
version string Yes "18" for PostgreSQL, "9" for Valkey.
name string No app PostgreSQL only. The database to create: lowercase letters, digits and underscores, starting with a letter or underscore, at most 63 characters, and not postgres, template0 or template1.
init string No Not set PostgreSQL only. A .sql file, or a folder whose .sql files run in name order, relative to the workspace root. Runs once, after the database is created.

install

Commands that run once at the workspace root, before any service starts. Use it for a single install that covers the whole repository, such as pnpm install in a monorepo.

Key Type Required Description
commands list of strings Yes At least one. They run in order; if one exits non-zero, the commands after it are skipped.

Databases are already running when these commands start, so a migration step here can reach them.

services

A mapping from service name to service. Names start with a lowercase letter and contain only lowercase letters, digits and hyphens, for example api or web-app. The name kendor-db is reserved. Each service runs in its own process window in the sandbox.

Key Type Required Default Description
workDir string No . Folder the service's install, dev and test commands run in, relative to the workspace root. No leading / and no ...
install mapping No commands: a list of at least one command, run in order in workDir after the top-level install. If one fails, the service's dev command doesn't start.
dev mapping No The long-running process. See below.
test mapping No command: the command the Tests tab runs.
publicEnvPrefix string No The prefix of variables that are safe to expose to browser code, such as VITE_. Accepted and stored; the sandbox doesn't act on it.

Every service needs at least a dev or a test. A service with only test (and no install) gets no process window: this is how single-file challenges are set up.

When a service restarts, its install is skipped if the dependency files in its workDir (package.json, lockfiles, composer.json, requirements.txt, pyproject.toml, go.mod and similar) haven't changed.

dev

Key Type Required Description
command string Yes The command that starts the service, for example npm run dev -- --port $PORT.
port integer No 1 to 65535. The port the service listens on. Two services can't share a port.
env.vars mapping No Environment variables for this command. Names match [A-Za-z_][A-Za-z0-9_]*; values are references, described below.

Kendor sets these variables for every dev command, and they override anything in env.vars:

Variable Value
HOST 0.0.0.0
PORT The service's port, when it has one.
KENDOR_PUBLIC_HOST The sandbox's public preview host name.
KENDOR_VITE_ORIGIN The service's public origin: the preview address for the preview service, or the service's own port address for any other service with a port. Read by the @kendordev/vite plugin.

Bind your server to $HOST and $PORT (or 0.0.0.0 and the declared port) so the preview can reach it.

Environment variable references

A value in env.vars must use one of four forms. Anything else fails validation.

Form Example Resolves to
routing.<service>.url routing.api.url That service's public URL: the preview address plus the service's longest routing path. The preview address alone when the service's path is / or it has no route. The service must exist.
databases.<type>.url databases.postgres.url The connection URL of a database declared under databases.
vars.<NAME> vars.sessionId A value Kendor provides: assessmentId, challengeId or sessionId. Other names fail validation.
lit:<text> lit:debug The text after lit:, as is.

Databases also set their own variables, such as DATABASE_URL and REDIS_URL, for every process in the sandbox. You only need databases.<type>.url when your code reads a different name.

preview

Key Type Required Description
service string Yes, when preview is present The service whose dev server the preview pane shows. It must exist.

preview is required when there is more than one service. With one service, that service is the preview. A project whose services have no dev command has no preview, only a terminal.

routing

A list of routes on the sandbox's preview address. Each request goes to the route with the longest matching path prefix. The full path is passed on, so a service routed at /api receives /api/products, not /products.

Key Type Required Description
path string Yes Starts with /. Add a / route as the catch-all.
service string Yes An existing service. Routes to a service without a dev.port are skipped.

With routes declared, the preview shows a short waiting page until every routed service is accepting connections. See Multi-service apps.

sandbox

Lets the sandbox run its own container tools.

Key Type Default Description
containers boolean false A Docker daemon inside the sandbox, with docker, docker compose and buildx.
kubernetes boolean false A single-node k3s cluster started at boot, with kubectl and helm. Turns on containers too.

Either one gives the sandbox more memory and CPU. The preview can open ports published by docker run -p or Compose, and kubectl port-forward with --address 0.0.0.0. A configuration with containers or kubernetes can't define any test command, so there's nothing to run from the Tests tab; use it for challenges you review by reading the work. The pricing page lists container environments under the Enterprise plan.

kendor.yaml
version: 1
runtime:
  type: node
  version: "22"
sandbox:
  containers: true
services:
  app:
    install:
      commands:
        - npm ci
    dev:
      command: docker compose up

requests

Example HTTP requests that appear, ready to send, in the editor's Requests tab. Requests are sent from inside the sandbox, so localhost works as it does with curl in the terminal. They never change how the sandbox starts.

Key Type Required Default Description
name string Yes The label shown in the list.
method string No GET GET, POST, PUT, PATCH, DELETE, HEAD or OPTIONS.
url string Yes A full URL such as http://localhost:3000/api/todos, or a path such as /api/todos, which is sent to the preview service's port.
headers mapping No Header name to value.
body string No The request body.

An example with a mistake is left out of the tab; the others still show.

kendor

Author-only settings. A candidate can't change them. The block accepts extra keys without error.

Key Type Description
gradeService string The service whose test.command the Tests tab runs. Defaults to the preview service. Must name an existing service.
gradeServices list of strings Several services whose test commands the Tests tab runs, each in its own workDir. Results are listed as service › test. Every service named must exist and have a test. Use either this or gradeService, not both.

The block also holds keys that Kendor's own starter catalog uses to describe its starters: title, entryFile, order, type, difficulty, category, tags, editablePaths and solutionDir. They have no effect on your challenge.

Validation rules

A file is saved only when all of these hold:

  • version is 1, and runtime and at least one service are present.
  • No unknown keys outside kendor.
  • Service names match ^[a-z][a-z0-9-]*$ and none is kendor-db.
  • Every service has a dev or a test.
  • workDir and databases[].init are relative paths inside the workspace: no leading /, no drive letter, no ...
  • No two services use the same dev.port.
  • preview.service names an existing service, and preview is present when there are two or more services.
  • Every routing[].service names an existing service, and every path starts with /.
  • Every env.vars value uses one of the four reference forms; routing.<service>.url names an existing service, databases.<type>.url names a declared database, and vars.<NAME> is assessmentId, challengeId or sessionId.
  • Each language appears once across runtime and toolchains, and each database type once.
  • name and init appear only on a postgres database, and name follows the naming rule above.
  • kendor.gradeService and every entry of kendor.gradeServices name existing services, entries of gradeServices have a test, and the two keys aren't used together.
  • With sandbox.containers or sandbox.kubernetes, no service has a test and neither gradeService nor gradeServices is set.
  • Every language and database version is one Kendor offers. Versions that are no longer offered for new challenges still pass, so a challenge that uses one keeps saving.
Was this article helpful?