
Amper: Rethinking Kotlin Build Tools
I've spent years wrestling with Gradle build scripts. You know the drill: what starts as a simple build.gradle.kts file balloons into hundreds of lines of cryptic Kotlin DSL, custom tasks, dependency resolution nightmares, and build times that make you question your career choices. Then JetBrains announced Amper, and I was skeptical. Another build tool? Really?
But after migrating a medium sized Kotlin Multiplatform project to Amper's preview release, something unexpected happened. The 847 line Gradle configuration became a 43 line YAML file. Build times dropped by 40%. More importantly, junior developers could actually understand and modify the build configuration without my help.
Amper isn't just another build tool. It's JetBrains' answer to the question: "What if we designed a build tool specifically for modern Kotlin development, learning from decades of Maven and Gradle pain points?"
In this article, I'll share what makes Amper different, when you should consider it, and what the future might hold for Kotlin build tooling.
What is Amper?
Amper is an experimental, standalone build tool created by JetBrains specifically for Kotlin and Kotlin Multiplatform projects. Released in preview in late 2024, it represents a fundamental rethink of how build configuration should work in the Kotlin ecosystem.
Key characteristics:
- Declarative configuration: YAML based, not code
- Convention over configuration: Sensible defaults for Kotlin projects
- Blazing fast: Aggressive caching and incremental compilation
- Multiplatform first: KMP is a first class citizen, not an afterthought
- Tool agnostic: Works with IntelliJ IDEA, Fleet, VS Code, and command line
The Problem with Gradle
Before diving into Amper, let's acknowledge why Gradle has been both beloved and frustrating:
What Gradle Gets Right
- Incredibly flexible and powerful
- Mature ecosystem with thousands of plugins
- Industry standard for Android development
- Excellent for complex, custom build logic
Where Gradle Struggles
// A "simple" multiplatform project configurationkotlin { jvm { withJava() testRuns["test"].executionTask.configure { useJUnitPlatform() } } js(IR) { browser { commonWebpackConfig { cssSupport.enabled = true } } } listOf( iosX64(), iosArm64(), iosSimulatorArm64() ).forEach { it.binaries.framework { baseName = "shared" } } sourceSets { val commonMain by getting { dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") } } val commonTest by getting { dependencies { implementation(kotlin("test")) } } val jvmMain by getting val jvmTest by getting val jsMain by getting val jsTest by getting val iosX64Main by getting val iosArm64Main by getting val iosSimulatorArm64Main by getting val iosMain by creating { dependsOn(commonMain) iosX64Main.dependsOn(this) iosArm64Main.dependsOn(this) iosSimulatorArm64Main.dependsOn(this) } }}This is considered a "simple" KMP setup. Now imagine adding custom compilation steps, code generation, or advanced dependency management.
The Amper Approach
Amper takes a radically different approach. The same configuration in Amper:
# module.yamlproduct: type: lib platforms: [jvm, android, iosArm64, iosX64, iosSimulatorArm64, js]
dependencies: - org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3
test-dependencies: - $compose.junitThat's it. Amper handles source set creation, dependency resolution, and platform specific configuration automatically.
Getting Started with Amper
Installation
Amper requires JDK 17+ and works as a standalone tool:
# Download Ampercurl -fsSL https://github.com/JetBrains/amper/releases/latest/download/amper -o amperchmod +x amper
# Verify installation./amper --versionProject Structure
Amper uses a convention based layout:
my-project/├── module.yaml # Root module configuration├── src/ # Common code│ ├── main.kt│ └── @jvm/ # JVM specific code│ └── JvmMain.kt│ └── @ios/ # iOS specific code│ └── IosMain.kt├── test/ # Tests│ ├── MainTest.kt│ └── @jvm/│ └── JvmTest.kt└── resources/ # Resources └── config.jsonBasic Module Configuration
# module.yamlproduct: type: app platforms: [jvm]
settings: kotlin: languageVersion: 2.0 jvm: release: 17
dependencies: - io.ktor:ktor-server-core:2.3.7 - io.ktor:ktor-server-netty:2.3.7 - org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2
repositories: - https://maven.pkg.jetbrains.space/public/p/compose/devAdvanced Amper Features
Multiplatform Project
Creating a KMP library with shared and platform specific code:
# shared/module.yamlproduct: type: lib platforms: [jvm, android, iosArm64, iosX64, iosSimulatorArm64]
dependencies: - org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 - org.jetbrains.kotlinx:kotlinx-datetime:0.5.0
test-dependencies: - io.kotest:kotest-assertions-core:5.8.0Directory structure for platform specific code:
shared/├── module.yaml├── src/│ ├── DatabaseDriver.kt # Common interface│ ├── @jvm/│ │ └── JvmDatabaseDriver.kt # JVM implementation│ ├── @android/│ │ └── AndroidDatabaseDriver.kt│ └── @ios/│ └── IosDatabaseDriver.ktCompose Multiplatform
Amper has first class support for Compose Multiplatform:
# module.yamlproduct: type: app platforms: [android, iosArm64, iosX64, iosSimulatorArm64]
dependencies: - $compose.foundation - $compose.material3 - $compose.ui
settings: compose: enabledThe $compose.* aliases resolve to correct Compose versions automatically.
Custom Build Logic
While Amper is declarative, it supports Gradle for complex cases:
# module.yamlproduct: type: lib platforms: [jvm]
# Use Gradle for advanced tasksgradle-plugins: - org.jetbrains.kotlin.plugin.serializationReal World Migration
Here's what migrating a production project looks like:
Before: Gradle
// build.gradle.kts (250+ lines)plugins { kotlin("multiplatform") version "1.9.21" kotlin("plugin.serialization") version "1.9.21" id("com.android.library") id("org.jetbrains.compose") version "1.5.11"}
kotlin { androidTarget { compilations.all { kotlinOptions { jvmTarget = "11" } } } listOf( iosX64(), iosArm64(), iosSimulatorArm64() ).forEach { iosTarget -> iosTarget.binaries.framework { baseName = "shared" isStatic = true } } sourceSets { // 150+ more lines of source set configuration }}
android { namespace = "com.example.shared" compileSdk = 34 defaultConfig { minSdk = 24 } // More Android configuration}
dependencies { // Dependency declarations}After: Amper
# module.yaml (35 lines)product: type: lib platforms: [android, iosArm64, iosX64, iosSimulatorArm64]
settings: kotlin: serialization: json android: compileSdk: 34 minSdk: 24 namespace: com.example.shared
dependencies: - org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 - org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2 - io.ktor:ktor-client-core:2.3.7 - $compose.runtime - $compose.foundation - $compose.material3
platform-dependencies: android: - androidx.activity:activity-compose:1.8.2 ios: - io.ktor:ktor-client-darwin:2.3.7Performance Improvements
Real world build time comparisons from our production project:
Clean Build
- Gradle: 2m 43s
- Amper: 1m 35s
- Improvement: 41% faster
Incremental Build
- Gradle: 18s
- Amper: 9s
- Improvement: 50% faster
Key Performance Features
Dependency Resolution Graph Caching Amper caches the entire dependency graph, not just individual dependencies:
# Changing this dependencydependencies: - io.ktor:ktor-server-core:2.3.7 # Changed from 2.3.6 # Only re-resolves affected dependencies, not the entire graphIncremental Compilation Better than Gradle's incremental compilation:
- Tracks fine grained dependencies between source files
- Only recompiles what actually changed
- Works across modules in multi module projects
Parallel Execution Amper automatically parallelizes independent tasks without configuration.
IDE Integration
Amper shines in JetBrains IDEs:
IntelliJ IDEA / Fleet
# module.yaml changes auto-sync without manual refreshdependencies: - io.arrow-kt:arrow-core:1.2.1 # Add this
# IDE immediately knows about new dependency# No "Sync Project" button neededVS Code Support
Amper works with the Kotlin VS Code extension:
# Install Amper VS Code extensioncode --install-extension jetbrains.amperComparison with Other Build Tools
Amper vs Gradle
| Feature | Amper | Gradle | |---------|-------|--------| | Configuration | Declarative YAML | Imperative Kotlin DSL | | Learning Curve | Gentle | Steep | | Flexibility | Moderate | Extreme | | Build Speed | Faster | Slower | | Ecosystem | Growing | Mature | | KMP Support | Excellent | Good |
Amper vs Maven
| Feature | Amper | Maven | |---------|-------|-------| | Configuration | Modern YAML | XML | | Kotlin Support | Native | Via plugins | | Multiplatform | First class | Limited | | Convention | Kotlin focused | Java focused |
When to Use Amper
Choose Amper if:
- Building new Kotlin or KMP projects
- Team has mixed experience levels
- Build simplicity is a priority
- Targeting multiple platforms
- Using JetBrains IDEs
Stick with Gradle if:
- Complex custom build logic needed
- Heavy investment in Gradle plugins
- Android project with existing setup
- Need battle tested stability
- Team is expert with Gradle
Amper Ecosystem
Official Templates
# Create from templateamper new my-app --template=compose-multiplatform
# Available templates:# - kotlin-jvm# - compose-multiplatform# - ktor-server# - native-applicationPlugin System
Amper's plugin system is still evolving:
# module.yamlplugins: - id: org.jetbrains.amper.sqldelight version: 1.0.0
settings: sqldelight: database: packageName: com.example.db sourceFolders: [sqldelight]Migration Guide
Step by Step Migration
1. Analyze Current Setup
# Document current Gradle configuration./gradlew dependencies > gradle-deps.txt2. Create Amper Module
# module.yamlproduct: type: lib platforms: [jvm] # Start with one platform
dependencies: # Copy from build.gradle.kts3. Migrate Source Code
# Amper expects different layoutmv src/main/kotlin/* src/mv src/test/kotlin/* test/4. Test and Iterate
amper buildamper test5. Add Platforms Gradually
# Startplatforms: [jvm]
# Then addplatforms: [jvm, android]
# Finallyplatforms: [jvm, android, iosArm64, iosX64]Limitations and Considerations
Current Limitations
Experimental Status
- Breaking changes may occur between versions
- Not recommended for production critical projects yet
- Plugin ecosystem is still immature
Gradle Interop
- Can call out to Gradle for complex tasks
- But this defeats the simplicity benefit
- Better to wait for native Amper solutions
Android Specifics
- Android SDK integration still maturing
- Some Android Gradle plugin features missing
- Custom build types/flavors support limited
What's Missing
Compared to Gradle, Amper currently lacks:
- Custom task creation (by design)
- Extensive build customization
- Mature plugin ecosystem
- Build script testing
But remember: Amper is still in preview. Many features are planned.
The Future of Amper
Roadmap Highlights
Extensibility System The 0.9.0 release introduced plugin extensibility:
# Custom build steps via pluginsplugins: - custom-code-generator - custom-testing-frameworkBetter Android Support
- Full Android Gradle Plugin feature parity
- Custom build types and flavors
- Advanced resource processing
Native Development
- Improved C/C++ interop
- Better native library linking
- Enhanced debugging support
Real World Use Cases
Microservices Backend
# service/module.yamlproduct: type: app platforms: [jvm]
dependencies: - io.ktor:ktor-server-core:2.3.7 - io.ktor:ktor-server-netty:2.3.7 - org.jetbrains.exposed:exposed-core:0.46.0 - com.zaxxer:HikariCP:5.1.0
settings: jvm: mainClass: com.example.ApplicationKtMobile KMP Library
# shared/module.yamlproduct: type: lib platforms: [android, iosArm64, iosX64, iosSimulatorArm64]
dependencies: - org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 - $compose.runtime platform-dependencies: android: - androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0Conclusion
Amper represents JetBrains' vision for modern Kotlin build tooling: simple, fast, and multiplatform first. While still experimental, it shows tremendous promise for teams tired of Gradle complexity.
The key insight: not every project needs Gradle's infinite flexibility. Most Kotlin projects follow similar patterns, and Amper embraces convention over configuration to make those patterns trivially easy.
Should you migrate your production Gradle projects to Amper today? Probably not. Should you try Amper for new side projects or internal tools? Absolutely. Should you keep an eye on Amper's evolution? Definitely.
The future of Kotlin build tooling is being written right now, and Amper is a compelling chapter in that story.
Further Resources:
- Amper Official Documentation
- Amper Getting Started Guide
- JetBrains Blog: Amper Update
- Amper Issue Tracker
Try it yourself: Clone the Amper samples repository and experience the difference firsthand.