跪拜 Guibai
← Back to the summary

Amper Is Dead: JetBrains Folds Its Build Tool Into a Unified Kotlin CLI

000.png

I've been learning about Agent-related topics recently and updating a series of articles — Building Your First Agent with Kotlin.

This series was going to avoid Gradle and use the latest build tool, Amper. Then last week, Amper released version 0.11, and the biggest change was that Amper is gone!

Gone, but not entirely. More precisely, it has been integrated into Kotlin Toolchain.

With the release of Kotlin Toolchain 0.11.0, Amper has officially been upgraded to Kotlin Toolchain and entered the Alpha stage.

In addition to the product change, this version brings JVM library publishing capabilities, a new plugin development API, and some developer experience improvements.

To use the latest features of Kotlin Toolchain, you need IntelliJ IDEA 2026.1.2 or later, and the latest Kotlin Toolchain plugin.

Amper Renamed to Kotlin Toolchain

Amper's original goal was to explore a unified, declarative build experience.

As the project evolved, JetBrains realized that the ecosystem didn't need yet another build tool, but a unified Kotlin entry point. Kotlin Toolchain is that entry point.

I actually wasn't optimistic about Amper as a build tool from the start. Although Gradle has various shortcomings, the recent versions after 9.0 are actually quite usable:

  1. There are signs of a turnaround, with build speeds continuously being optimized;
  2. Although no one who has written Gradle plugins doesn't complain about its ecosystem, it is now too vast and has almost monopolized the entire JVM world.

No matter how excellent Amper is, it cannot bridge this gap (unless... it embraces Rust).

Now, after installing Kotlin Toolchain, you only need a single kotlin command that covers creating projects, building, running, testing, packaging, and publishing. Features like code formatting and documentation generation will be added later. Developers no longer need to choose a build tool at the beginning of a project, nor configure complex plugins just to run the first line of code.

Of course, the Kotlin team is doing this to pave the way for AI. AI needs CLI tools the most; even Android has released the android cli.

All existing functionality from Amper has been migrated to Kotlin Toolchain, so the project starts directly at the Alpha stage. The Alpha stage means JetBrains has committed to long-term maintenance, and you can try it out and provide feedback.

If you are already using Amper, note the following two points:

Considering that not many people use it, just install the latest Kotlin Toolchain directly.

Global Installation

The wrapper scripts in a project are suitable for clone-and-build scenarios without extra installation, but they don't fit all cases.

Starting from 0.11, the kotlin command line supports global installation, allowing direct use in any directory without the ./kotlin prefix. Install via SDKMAN!:

sdk install kotlintoolchain

Note: There are other installation methods besides SDKMAN!; see the documentation for details.

Improvements brought by global installation:

The global kotlin command automatically locates the wrapper script in a project and runs the corresponding version of the toolchain, so different projects can use different versions.

Publishing

This version adds library publishing functionality, currently in preview, supporting publishing JVM libraries to Maven repositories, including Maven Central.

Note: Publishing for Kotlin Multiplatform libraries is not yet supported and is under development.

Regular Maven Repositories

To publish to a repository other than Maven Central, configure in module.yaml:

product: jvm/lib

repositories:
  - id: myMavenRepoId
    url: https://maven.pkg.github.com/my-org/my-maven-repo 
    publish: true
    credentials:
      file: creds.properties # Properties file storing credentials
      usernameKey: maven.username # Property name for username
      passwordKey: maven.password # Property name for password

settings:
 publishing:
   enabled: true
   group: com.example
   artifactId: greeter # Optional, defaults to module name
   version: 1.0.0

Example credentials file (creds.properties):

maven.username=john.doe
maven.password=MyVerySecurePassword123

Execute publishing via the repository ID:

kotlin publish myMavenRepoId

All modules with publishing enabled and the corresponding repository declared will be published.

Maven Central

Publishing to Maven Central typically involves multiple steps: sources JAR, javadoc JAR, PGP signing, POM metadata, checksums, etc. Kotlin Toolchain now handles these steps automatically; developers only need to declare what to publish.

Prerequisites: Have an account, namespace, user token, and PGP signing key ready on the Maven Central Publisher Portal.

Publishing to Maven Central does not require manually declaring a repository. Set mavenCentral: enabled in the publishing configuration and fill in the necessary information. Minimal configuration:

product: jvm/lib

description: A meaningful description of the module

settings:
  publishing:
    enabled: true
    group: com.example # group must match the Maven Central namespace
    version: 1.0.0
    # artifactId is optional, defaults to module name
    mavenCentral: enabled
    signArtifacts: true # Auto-sign, no external GPG tool needed
    publishSources: true
    pom:
      url: https://example.com
      scm: https://github.com/my-org/example.git # SCM connection and developer connection are auto-derived
      developers:
        - name: John Doe
      licenses:
        - name: MIT
          url: https://opensource.org/license/mit

After configuration, publish with a single command:

kotlin publish mavenCentral

This command builds and signs all artifacts, packages them into a Maven Central deployment bundle, and uploads them for validation. Afterwards, check the deployment status and complete the release via the Central portal UI.

You can also enable fully automatic publishing via publishingMode: auto to skip manual validation.

Cinterop Support

Kotlin Toolchain now generates custom bindings for C libraries based on definition files in the module's cinterop folder.

1.png

The IDE also assists in generating bindings during project synchronization.

2.png

Terminal UI Improvements

The output of the kotlin command has the following improvements:

Completed tasks have better progress indicators, and the main progress bar integrates native terminal progress display:

3.png

Rendering of Kotlin JVM compiler diagnostics has also been improved (requires Kotlin 2.4.0+):

4.png

IDE Improvements

Library Source Download

Library sources are now automatically downloaded after synchronization completes.

5.png

Synchronization completes first, allowing developers to start working immediately, while sources download in the background.

Module-Level Dependency Resolution

Previously, the IDE plugin's dependency resolution was performed at the project level, which was inconsistent with CLI behavior and could lead to incorrect dependency versions in modules or erroneous error warnings in the editor. It is now aligned with the CLI, with each module resolving independently and diagnostic results remaining consistent.

Plugin Development Improvements

New checks and commands declarations, a new task input API, and diagnostic-related improvements have been added for local plugin authors.

New References

When connecting task inputs in plugin.yaml, built-in references can be used to access project information. Two new references have been added:

Custom Checks

The kotlin check command is used to ensure the project passes all quality checks. It runs regular unit tests by default, and plugins can register additional checks.

Add custom checks in the plugin via the checks top-level list:

# my-lint-plugin/plugin.yaml
tasks:
  runLinter:
    action: !kotlinJavaLint
      sources: ${module.kotlinJavaSources}

checks:
  - name: lint
    performedBy: runLinter

The lint check can also be run individually via kotlin check lint. List checks in the project using kotlin show checks. See the plugin documentation for details.

Custom Commands

Plugins sometimes need to expose public entry points, such as generating a changelog, printing information on demand, or publishing packages in custom formats. Since plugin tasks are considered private by default, custom commands have been introduced as public entry points.

Custom commands are implemented based on regular tasks and can access build data (source files, compiled JARs, runtime classpath, etc.) and depend on other tasks. Register them in plugin.yaml using the commands top-level node:

# my-lint-plugin/plugin.yaml
tasks:
  updateBaseline:
    action: !runDetektForBaseline
      sources: ${module.kotlinJavaSources}
      outputFile: ${module.rootDir}/detekt/baseline.xml

commands:
  # Shorthand when command name matches task name
  - updateBaseline

Execute via kotlin do command:

kotlin do updateBaseline

This command runs the associated task and its dependencies. List all custom commands using kotlin show commands.

New Way to Register Generated Files

A new generated top-level node has been added to plugin.yaml for registering generated source code, resources, and class files. Starting from 0.11.0, cinterop definitions can also be registered when tasks dynamically provide native libraries:

tasks:
  generateStuff:
    action: !myGenerateStuffAction
      outputSources: ${taskOutputDir}/src
      outputResources: ${taskOutputDir}/res
      outputDefFiles: ${taskOutputDir}/cinterop

generated:
  sources:
    - directory: ${tasks.generateStuff.action.outputSources}
      language: kotlin
  resources:
    - directory: ${tasks.generateStuff.action.outputResources}
  cinteropDefinitions:
    - directory: ${tasks.generateStuff.action.outputDefFiles}

This replaces the deprecated markOutputAs property in tasks (which will be removed in a future version). All outputs fed back to the build are registered in a unified way, clearly identifiable under their respective nodes, making them easy for humans, AI agents, and other tools to recognize.

Other Improvements

lib Renamed to kmp/lib

The lib product type has been renamed to kmp/lib to more accurately reflect its meaning (distinguishing it from jvm/lib). The old lib value is deprecated and will be removed in a future version.

Template Nesting

Templates can now apply other templates, building a hierarchical settings structure. The syntax is unchanged; use the apply node in the template file:

# spring.module-template.yaml
apply:
  - ./jvm.module-template.yaml

settings:
  springBoot: enabled

Maven Classifier Support

Maven dependency declarations now support classifiers, allowing you to specify a specific artifact of a dependency library:

dependencies:
      - io.netty:netty-transport-native-epoll:4.2.13.Final:linux-x86_64

run Command Improvements

The run command no longer requires explicitly specifying a module or platform when only one option is applicable to the current host.

When a project has multiple modules but only one can run on the current host, specifying the module is unnecessary. For example, with this project structure:

.
├── linux-cli/
├── macos-cli/
├── windows-cli/
├── shared/
├── kotlin
├── kotlin.bat
└── project.yaml

Executing kotlin run on Windows will automatically start the windows-cli module.

When a module has multiple target platforms but only one can run on the current host, specifying the platform is also unnecessary. For example:

# linux-app/module.yaml
product: linux/app

# Both linuxArm64 and linuxX64 platforms exist by default

On an ARM machine, kotlin run -m linux-app will start the ARM64 version; on an x86 machine, it will start the x86-64 version.

Default Version Updates

Default versions for the toolchain and frameworks have been updated:

Note

Amper users cannot migrate to Kotlin Toolchain through the regular automatic update path. You need to manually replace the amper and amper.bat in your project with the Kotlin wrapper scripts. First, install the toolchain globally, then generate new wrapper scripts via the Kotlin CLI:

kotlin update --create

After replacement, subsequent updates can be done using kotlin update.

Some Thoughts

Amper was just released not long ago and has already been renamed to Kotlin Toolchain; the pace is really fast.

But it's not surprising now. Plans can never keep up with changes; in the AI era, everyone has to follow the pace of AI.

Rather than reinventing a build tool, moving towards a CLI tool is actually a more practical idea. AI agents are much more comfortable calling a CLI than fiddling with a bunch of GUIs and plugins, and the barrier to entry for developers' daily use is lower. It should be more popular than Amper as a standalone build tool.

Original: Kotlin Toolchain 0.11: The Next Step for Amper