From everything-claude-code-mobile
Provides Ktor client patterns for Android HTTP networking with content negotiation, timeouts, logging, authentication, API CRUD, and safe error handling.
How this skill is triggered — by the user, by Claude, or both
Slash command
/everything-claude-code-mobile:ktor-patternsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Modern HTTP client for Kotlin.
Modern HTTP client for Kotlin.
val httpClient = HttpClient(OkHttp) {
// JSON serialization
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
isLenient = true
prettyPrint = false
})
}
// Timeouts
install(HttpTimeout) {
requestTimeoutMillis = 30_000
connectTimeoutMillis = 10_000
socketTimeoutMillis = 30_000
}
// Logging (debug only)
install(Logging) {
logger = Logger.ANDROID
level = if (BuildConfig.DEBUG) LogLevel.BODY else LogLevel.NONE
}
// Default request config
defaultRequest {
url("https://api.example.com")
contentType(ContentType.Application.Json)
}
// Auth
install(Auth) {
bearer {
loadTokens {
BearerTokens(tokenStorage.accessToken, tokenStorage.refreshToken)
}
refreshTokens {
val response = client.post("auth/refresh") {
setBody(RefreshRequest(tokenStorage.refreshToken))
}
tokenStorage.save(response.body())
BearerTokens(response.body<TokenResponse>().accessToken, response.body<TokenResponse>().refreshToken)
}
}
}
}
class UserApi(private val client: HttpClient) {
suspend fun getUsers(): List<UserDto> {
return client.get("users").body()
}
suspend fun getUser(id: String): UserDto {
return client.get("users/$id").body()
}
suspend fun createUser(request: CreateUserRequest): UserDto {
return client.post("users") {
setBody(request)
}.body()
}
suspend fun updateUser(id: String, request: UpdateUserRequest): UserDto {
return client.put("users/$id") {
setBody(request)
}.body()
}
suspend fun deleteUser(id: String) {
client.delete("users/$id")
}
}
class ApiException(
val statusCode: Int,
override val message: String
) : Exception(message)
suspend inline fun <reified T> HttpClient.safeRequest(
block: HttpRequestBuilder.() -> Unit
): Result<T> = runCatching {
val response = request(block)
if (response.status.isSuccess()) {
response.body<T>()
} else {
throw ApiException(
statusCode = response.status.value,
message = response.bodyAsText()
)
}
}
// Usage
class UserRepository(private val api: UserApi, private val client: HttpClient) {
suspend fun getUser(id: String): Result<User> {
return client.safeRequest<UserDto> {
url("users/$id")
method = HttpMethod.Get
}.map { it.toDomain() }
}
}
@Serializable
data class UserDto(
val id: String,
val email: String,
@SerialName("first_name")
val firstName: String,
@SerialName("created_at")
val createdAt: String
)
fun UserDto.toDomain(): User = User(
id = id,
email = email,
name = firstName,
createdAt = Instant.parse(createdAt)
)
val client = HttpClient(OkHttp) {
// Request interceptor
install(HttpSend) {
intercept { request ->
request.headers.append("X-Client-Version", BuildConfig.VERSION_NAME)
execute(request)
}
}
}
val client = HttpClient(OkHttp) {
engine {
config {
certificatePinner(
CertificatePinner.Builder()
.add("api.example.com", "sha256/AAAA...")
.add("api.example.com", "sha256/BBBB...") // Backup pin
.build()
)
}
}
}
Remember: Ktor is coroutine-first. Embrace suspend functions, handle errors properly.
npx claudepluginhub ahmed3elshaer/everything-claude-code-mobile --plugin everything-claude-code-mobileConfigures Ktor client for KMP/Android projects: plugin install order, kotlinx.serialization flags, bearer auth refresh, MockEngine testing, and error mapping at the repository boundary.
Configures Ktor HTTP client for Kotlin Multiplatform with platform-specific engines: OkHttp for Android, Darwin for iOS. Includes JSON serialization, logging, and bearer auth.
Provides Ktor server patterns including routing DSL, plugin configuration (Auth, CORS, Serialization), Koin DI, kotlinx.serialization, WebSocket, and testApplication testing.