| name | ktor |
| description | Use when building, modifying, debugging, or reviewing Ktor 3.5.x server and client applications, including routing, requests/responses, plugins, serialization, authentication, sessions, WebSockets, SSE, engines, testing, deployment, and Kotlin multiplatform client work. |
Ktor
Use this skill for Ktor framework work: Kotlin HTTP servers, HTTP clients, multiplatform clients, REST APIs,
WebSockets, SSE, serialization, authentication, plugins, testing, and deployment.
Do not confuse Ktor with generic Kotlin, Spring Boot, ktorfit, Retrofit, OkHttp-only usage, or Kotlin Toolchain build
configuration. If the task is about module.yaml or the ./kotlin build CLI, load kotlin-toolchain too. If the task is
a standalone .main.kts script using Ktor, load main-kts too.
Source Snapshot
This skill is generated from the official Ktor documentation:
- Repository:
https://github.com/ktorio/ktor-documentation
- Ref:
main at the Ktor 3.5.x documentation line
- SHA:
d118418a65e03d73ad7c2d33bb68e979cebcb4e5
- Ktor version variable:
3.5.1
- Kotlin version variable:
2.3.21
- Coroutines version variable:
1.11.0
- Server guide:
references/server.md
- Client guide:
references/client.md
- Regeneration log:
generation/generation-steps.md
Version this skill by the Ktor minor line, like kotlin-toolchain: this default SKILL.md targets Ktor 3.5.x and
should keep immediate operational guidance here instead of becoming only a version index. If maintaining future docs,
create or update a minor-line snapshot such as Ktor 3.6.x; do not silently mix breaking or behavior-changing guidance
from a different minor line.
Ktor APIs move between minor releases. When exact syntax matters, inspect the project dependencies/build files first and
prefer the docs for the project's installed Ktor version.
First Moves
When working in a repository:
- Inspect build files first:
build.gradle.kts, settings.gradle.kts, gradle/libs.versions.toml, pom.xml,
module.yaml, or .main.kts annotations.
- Determine Ktor version and whether it is server, client, or both.
- For server work, load
references/server.md.
- For client or multiplatform client work, load
references/client.md.
- Preserve the project's build system and existing style. Do not introduce Gradle if the project uses Kotlin Toolchain;
do not introduce Kotlin Toolchain if the project uses Gradle or Maven.
- Add only the artifacts required for the plugins/features being installed.
- After changes, run the project's real tests or at least a compile/build task.
Core Coordinates and Imports
Ktor artifacts use Maven group io.ktor. In Gradle examples, use one version source:
val ktorVersion = "3.5.1"
implementation("io.ktor:ktor-server-core:$ktorVersion")
implementation("io.ktor:ktor-client-core:$ktorVersion")
Common server dependencies:
ktor-server-core
- engine:
ktor-server-cio, ktor-server-netty, ktor-server-jetty-jakarta, or ktor-server-tomcat-jakarta
- serialization:
ktor-server-content-negotiation + one of ktor-serialization-kotlinx-json, gson, jackson,
kotlinx-xml, kotlinx-cbor, kotlinx-protobuf
- auth:
ktor-server-auth, optional ktor-server-auth-jwt, ktor-server-auth-ldap
- sessions:
ktor-server-sessions
- testing:
ktor-server-test-host
- DI:
ktor-server-di
Common client dependencies:
ktor-client-core
- engine:
ktor-client-cio, ktor-client-okhttp, ktor-client-apache5, ktor-client-java,
ktor-client-jetty-jakarta, ktor-client-android, ktor-client-darwin, ktor-client-curl, ktor-client-winhttp,
or ktor-client-js
- serialization:
ktor-client-content-negotiation + one of the serialization artifacts above
- auth:
ktor-client-auth
- logging:
ktor-client-logging
- testing:
ktor-client-mock
For .main.kts, prefer JVM/platform leaf artifacts where needed, for example io.ktor:ktor-client-cio-jvm:3.5.1,
because script dependency resolution can miss Gradle module metadata for multiplatform root artifacts.
Server Minimal Shape
Load references/server.md before non-trivial server edits.
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.cio.*
import io.ktor.server.engine.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
fun main() {
embeddedServer(CIO, port = 8080, host = "0.0.0.0") {
install(ContentNegotiation) { json() }
routing {
get("/health") { call.respondText("OK") }
get("/") { call.respond(mapOf("status" to "up")) }
}
}.start(wait = true)
}
Prefer route extension functions once routing grows:
fun Application.module() {
configureSerialization()
configureRouting()
}
fun Application.configureRouting() = routing {
route("/api") { get("/health") { call.respond(HttpStatusCode.OK) } }
}
Client Minimal Shape
Load references/client.md before non-trivial client edits.
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.serialization.kotlinx.json.*
suspend fun main() {
val client = HttpClient(CIO) {
install(ContentNegotiation) { json() }
}
try {
val body: String = client.get("https://example.com").body()
println(body)
} finally {
client.close()
}
}
Use a singleton/DI-managed HttpClient in applications. Do not create and dispose a new client per request.
Mental Model
Ktor is plugin-oriented:
- A server
Application installs plugins and registers routes. The current request/response is an ApplicationCall.
- A client
HttpClient installs plugins and makes suspending requests. The current response is an HttpResponse.
- Most features require both an artifact and
install(PluginName) { ... }.
- Serialization is not implicit: install
ContentNegotiation and choose a serializer.
- Authentication is route-scoped on the server via
authenticate { ... }; on the client it is request-scoped/provider-
selected through the Auth plugin.
- Engines perform network I/O. Choose an engine compatible with the platform and features needed.
Frequent Pitfalls
- Missing plugin artifact:
install(ContentNegotiation) needs ktor-server-content-negotiation or
ktor-client-content-negotiation plus serializer artifacts.
- Wrong imports: server packages are under
io.ktor.server.*; client packages under io.ktor.client.*.
- Receiving request bodies twice on server without
DoubleReceive fails.
- Forgetting
@Serializable or the Kotlin serialization compiler plugin when using kotlinx.serialization.
- Creating an
HttpClient per request leaks resources and defeats pooling.
- In tests, use Ktor test hosts/mocks instead of binding real ports unless doing E2E.
- For Ktor 3.5 digest auth, prefer RFC 7616 APIs (
DigestAlgorithm, DigestQop, algorithm-aware digest provider) over
stringly legacy MD5-only examples.
Verification Checklist