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:
mainat the Ktor3.5.xdocumentation 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.ktsannotations. - 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, orktor-server-tomcat-jakarta - serialization:
ktor-server-content-negotiation+ one ofktor-serialization-kotlinx-json,gson,jackson,kotlinx-xml,kotlinx-cbor,kotlinx-protobuf - auth:
ktor-server-auth, optionalktor-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, orktor-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
Applicationinstalls plugins and registers routes. The current request/response is anApplicationCall. - A client
HttpClientinstalls plugins and makes suspending requests. The current response is anHttpResponse. - Most features require both an artifact and
install(PluginName) { ... }. - Serialization is not implicit: install
ContentNegotiationand choose a serializer. - Authentication is route-scoped on the server via
authenticate { ... }; on the client it is request-scoped/provider- selected through theAuthplugin. - Engines perform network I/O. Choose an engine compatible with the platform and features needed.
Frequent Pitfalls
- Missing plugin artifact:
install(ContentNegotiation)needsktor-server-content-negotiationorktor-client-content-negotiationplus serializer artifacts. - Wrong imports: server packages are under
io.ktor.server.*; client packages underio.ktor.client.*. - Receiving request bodies twice on server without
DoubleReceivefails. - Forgetting
@Serializableor the Kotlin serialization compiler plugin when usingkotlinx.serialization. - Creating an
HttpClientper 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
- Project Ktor version and build system were inspected.
- Server/client/reference file was loaded as appropriate.
- Required artifacts match installed plugins/features.
- Code compiles against the project's Ktor minor version.
- Tests/build were run, or any blocker is reported explicitly.