Every Kotlin codebase has that file. Forty lines of id = id, name = name, email = email that nobody wanted to write and nobody wants to review. Kraft deletes it:
- fun User.toUserDto(): UserDto = UserDto(
- id = id,
- name = name,
- email = email,
- )
+ @MapConfig(source = User::class, target = UserDto::class)
+ object UserMapperval dto = user.toUserDto() // generated at compile timeThat's the whole mapper. Kraft is a KSP processor that generates type-safe extension functions between your data classes — plain, readable Kotlin you can inspect in build/generated. No reflection, no runtime library, nothing to ship.
- Breaks at build time, not in production — rename a property and the generated mapper stops compiling right there, instead of passing
nullaround at runtime. - Zero runtime cost — the generated code is exactly what you'd have written by hand, minus the writing.
- Multiplatform from the start — annotations live in
commonMain; JVM, Android, iOS, JS, and WasmJs all work. - Escape hatches everywhere — renames, ignores, custom converters, enum tables: when your models disagree, you override one property, not the whole mapper.
- Automatic property matching — same-name properties mapped without configuration
- Field renaming —
@MapFieldor@FieldMappingfor cross-name mapping - Nested objects — auto-detected when types differ, including renamed properties
- Collections —
List<T>andSet<T>with nested element mapping - Enum mapping —
@MapEnumwith auto-matching and custom entry pairs - Reverse mapping —
@MapReversegenerates the inverse mapper automatically
- Custom converters —
@MapUsingfor property-source or whole-source transformations - Global converters —
@KraftConverteron a top-level extension is auto-discovered across the module and the classpath, with@OptInmarkers propagated onto the generated mapper - Ignore rules —
@MapIgnoreand@MapIgnoreFieldwith directional control - Configuration objects —
@MapConfigfor mapping without modifying data classes - Layer-aware aliases — register
Dto/Domain/Entitysides via thekraft { }Gradle DSL to emit short.toDomain()/.toEntity()extensions alongside the verbose mappers
- Kotlin Multiplatform — annotations work on JVM, iOS, JS, and WasmJs
- Plugin SPI — implement
MapperGeneratorProviderto plug in your own code generator
- Kotlin 2.2+ (built and tested with Kotlin 2.2.21)
- KSP 2 — 2.3.3 is the tested reference; other KSP 2 releases are not CI-tested but a version matching your Kotlin is expected to work (KSP 1-era versions are not supported)
- JDK 17+ build toolchain — the processor runs at compile time only
Kraft runs entirely at build time; the generated mappers are plain Kotlin and the annotations target JVM 1.8, so legacy apps on older runtimes are supported — see Compatibility and legacy projects.
Kraft is published to Maven Central under the com.blu3berry.kraft group (latest version shown in the badge above). Make sure mavenCentral() is in your repositories { } block.
The Gradle plugin is the one-line setup for Kotlin Multiplatform, JVM, and Android modules — it adds the version-aligned dependencies and all wiring:
// build.gradle.kts
plugins {
kotlin("multiplatform") // or kotlin("jvm") / kotlin("android")
id("com.google.devtools.ksp") version "<ksp-version>"
id("com.blu3berry.kraft") version "<version>"
}Optional configuration goes through the typed kraft { } extension:
kraft {
side("dto") { packagePattern = "com.example.dto.**" } // emits .toDto() aliases
side("domain") { packagePattern = "com.example.domain.**" } // emits .toDomain() aliases
}Prefer explicit control, or need the legacy-project integration patterns? See Getting Started for manual wiring.
Full guides for every feature live on the docs site:
- Getting Started — install, first mapper, legacy-project patterns
- User Guide — every feature with examples (KSP options &
kraft { }DSL, side aliases) - Architecture & SPI
- AI Integration — ship the Kraft skill to your coding agent
- Contributing
| Annotation | Purpose | Placement |
|---|---|---|
@MapConfig |
Standalone mapping config | On object |
@MapFrom |
Map from source class | On target data class |
@MapTo |
Map to target class | On source data class |
@MapField |
Rename a property | On property in @MapFrom/@MapTo class |
@MapNested |
On property in @MapFrom/@MapTo class |
|
@MapIgnore |
Skip a property | On property (must have default value) |
@MapUsing |
Custom converter function | On function in @MapConfig object |
@KraftConverter |
Globally discoverable converter | On top-level extension function |
@MapEnum |
Enum-to-enum mapping | On object |
@MapReverse |
Generate inverse mapper | On class or @MapConfig object |
aliasEmitMode |
Per-mapper alias control (AliasEmitMode enum) |
Parameter on @MapConfig and @MapEnum |
ConverterDirection |
Direction selector for @MapUsing (AUTO / FORWARD / REVERSE) |
Parameter on @MapUsing(direction = …) |
IgnoreSide |
Direction selector for @MapIgnoreField (TARGET / SOURCE / BOTH) |
Parameter on @MapIgnoreField(direction = …) |
@FieldMapping |
Config-level rename | In @MapConfig.fieldMappings |
@NestedMapping |
In @MapConfig.nestedMappings |
|
@MapIgnoreField |
Config-level ignore | In @MapConfig.ignoredMappings |
Copyright Kraft Contributors
Licensed under the Apache License, Version 2.0
See LICENSE for the full text.
