---
title: "Which languages and versions can a coding challenge use"
description: "Node.js 22, Python 3.12, Go 1.27 and 1.26, Java 21, Rust 1.98, C++ (Clang 23) and PHP 8.3 and 8.4. Pick one with runtime.version in kendor.yaml."
updated: 2026-10-06
canonical: https://kendor.io/docs/environments/languages-and-versions
---

# Which languages and versions can a coding challenge use
A Kendor challenge can run Node.js 22, Python 3.12, Go 1.27 or 1.26, Java 21, Rust 1.98, C++ with
Clang 23, or PHP 8.3 or 8.4. You pick the language when you create the challenge and the version
with `runtime.version` in `kendor.yaml`. A project can add more languages beside the main one with
`toolchains`.

## Languages and versions available today

The value in the second column is what you write in `runtime.type`, and the third what you write in
`runtime.version`, always as a quoted string.

| Language | `runtime.type` | `runtime.version` | Exact build | Package managers and build tools | Test tooling |
|---|---|---|---|---|---|
| Node.js | `node` | `"22"` | 22.23.3 | npm, pnpm and yarn (through Corepack), Bun 1.4.2 | `node --test` |
| Python | `python` | `"3.12"` | 3.12.14 | pip (`pip install --user`) | pytest 8.3.4 with pytest-tap: `pytest --tap-stream` |
| Go | `go` | `"1.27"`, `"1.26"` | 1.27.1, 1.26.8 | Go modules | `go test -json ./... \| kendor-gotest-tap` |
| Java | `java` | `"21"` | Temurin 21.0.12.1 | Maven 3.9.16, Gradle 9.8.0 | JUnit console launcher 6.1.3 at `$JUNIT_CONSOLE`; `kendor-junit-tap` |
| Rust | `rust` | `"1.98"` | 1.98.1 | Cargo, Clippy, rustfmt | `cargo test --color never 2>&1 \| kendor-cargo-tap` |
| C++ | `cpp` | `"23"` | Clang/LLVM 23.1.2 | CMake, Ninja | Catch2 3.16.0 at `$CATCH2_DIR`; `kendor-junit-tap` |
| PHP | `php` | `"8.3"`, `"8.4"` | 8.3.32, 8.4.23 | Composer 2.10.3 | PHPUnit from your project, writing JUnit to `/tmp/kendor-phpunit.xml` |

Every language also comes with its language server, so the editor has completion, go-to-definition
and errors: typescript-language-server, Pyright, gopls, Eclipse JDT LS, rust-analyzer, clangd and
Intelephense. Every sandbox also has `git`, `make`, `cmake`, `ninja`, `sqlite3` and a C compiler,
whatever the language.

Go 1.22 also exists, but it's no longer offered for new challenges (see below).

## How the Tests tab reads results

The **Tests** tab runs the service's `test.command` and lists each test it finds. It reads
TAP (Test Anything Protocol) from the command's standard output, which is why the table lists a
converter for most languages: `kendor-gotest-tap`, `kendor-junit-tap` and `kendor-cargo-tap` are on
the `PATH` in every sandbox and turn `go test -json`, JUnit XML and `cargo test` output into TAP.
Send anything else your build prints to standard error. PHP is the exception: write PHPUnit's JUnit
report to `/tmp/kendor-phpunit.xml` with `--log-junit /tmp/kendor-phpunit.xml`.

```yaml file="kendor.yaml"
version: 1
runtime:
  type: go
  version: "1.27"
services:
  app:
    test:
      command: go test -json ./... | kendor-gotest-tap
```

## Pick a version

When you create a challenge, choose its **Language** and **Version**. The language can't change
after the challenge is created; the version can.

To change the version later, set `runtime.version` in `kendor.yaml`, either in the **Runtime
configuration** dialog or by editing the file, and save. Keep `runtime.type` the same as the
challenge's language: the version in the file is used only when the two match.

Use the short version from the table, such as `"1.27"`, not the exact build. Kendor checks the
version when you save and lists the ones it offers if yours isn't one of them.

## Add a second language

`toolchains` puts more languages in the same sandbox, each with its compiler, tools and language
server. This Laravel setup uses PHP as the main language and adds Node.js for the Vite asset build:

```yaml file="kendor.yaml"
version: 1
runtime:
  type: php
  version: "8.3"
toolchains:
  - type: node
    version: "22"
install:
  commands:
    - composer install --no-interaction --prefer-dist --no-progress
services:
  app:
    dev:
      command: php artisan serve --host $HOST --port $PORT
      port: 8000
  vite:
    install:
      commands:
        - npm ci
    dev:
      command: npm run dev -- --port $PORT
      port: 5173
preview:
  service: app
```

Each language can appear only once across `runtime` and `toolchains`.

## Retired versions

When a version leaves upstream support, Kendor stops offering it for new challenges but keeps it
running. A challenge already on that version keeps working and still saves, and its **Version** list
shows it as "no longer offered". You can't choose a retired version for a new challenge. Go 1.22 is
retired today.

When you're ready, move the challenge to a current version by changing `runtime.version`.

## Single-file or full project

When you add a coding challenge, you choose between two kinds:

- **Single-file challenge**: the candidate edits one file, such as `solution.py`, and runs the tests
  you wrote from the **Tests** tab. There is no preview, only the editor, a terminal and the tests.
  Every language in the table has a single-file starter.
- **Coding challenge**: a whole project. Start from a starter scaffold or a blank workspace, upload
  a zip, or import a repository. It can have a preview, several services, databases and more than one language.

The starter scaffolds for a full project today are:

| Language | Starters |
|---|---|
| Node.js | Vite + React (TypeScript), Vite + React (JavaScript), Express + PostgreSQL + Valkey |
| Python | Flask, FastAPI |
| Go | net/http, Command-line app |
| Java | Spring Boot, Java + Go + C++ services |
| Rust | axum |
| C++ | Command-line app (CMake) |
| PHP | Laravel 11, Simple PHP |

Each starter ships its own `kendor.yaml`, so it runs as soon as the sandbox starts. Read it to see
a working setup for that language, then change what you need.
