kendor.yaml reference
Este artigo ainda não está traduzido, por isso aparece em inglês.
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:
# 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: apiTop-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.
version: 1
runtime:
type: node
version: "22"
sandbox:
containers: true
services:
app:
install:
commands:
- npm ci
dev:
command: docker compose uprequests
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:
versionis1, andruntimeand at least one service are present.- No unknown keys outside
kendor. - Service names match
^[a-z][a-z0-9-]*$and none iskendor-db. - Every service has a
devor atest. workDiranddatabases[].initare relative paths inside the workspace: no leading/, no drive letter, no...- No two services use the same
dev.port. preview.servicenames an existing service, andpreviewis present when there are two or more services.- Every
routing[].servicenames an existing service, and everypathstarts with/. - Every
env.varsvalue uses one of the four reference forms;routing.<service>.urlnames an existing service,databases.<type>.urlnames a declared database, andvars.<NAME>isassessmentId,challengeIdorsessionId. - Each language appears once across
runtimeandtoolchains, and each database type once. nameandinitappear only on apostgresdatabase, andnamefollows the naming rule above.kendor.gradeServiceand every entry ofkendor.gradeServicesname existing services, entries ofgradeServiceshave atest, and the two keys aren't used together.- With
sandbox.containersorsandbox.kubernetes, no service has atestand neithergradeServicenorgradeServicesis 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.