Description
I find myself replacing bash and automation scripts with kotlin scripts everywhere and thats how much I like kotlin.
But the file naming convention is such a hacky, careless, low quality, lazy implementation that requires entire WORDS within kotlin script file names as a prerequisite that its a terrifying experience, just to get tooling support or executability, resolving etc.... Why ?? And can we propose an ultimate solution ? Let's dive in & discover the architectural paths forward.
History
-
Kotlin’s scripting support has evolved over time. Initially, .kts scripts could be executed via the compiler’s -script mode, but this support was limited (requiring a special script template and no direct dependency handling). In Kotlin 1.3 (2018), JetBrains introduced a new scripting artifact called kotlin-main-kts
-
By Kotlin 1.3.70 (2020), support for kotlin-main-kts was integrated by default into the Kotlin compiler and IntelliJ IDEA. This meant that the Kotlin compiler and IDE would automatically recognize and handle *.main.kts files without any extra setup
The Problem
So every language have their own ways to indicate entry points, in python it can detect via AST parsing an if __main__
block, or in most languages default fallback detection relies on main
function name defined within the file. In others build configuration overrides the path for source code, but scripts usually, even 50 years ago in UNIX were always flexible, they can even be run without an extension right now.
Can you imagine a scripting language requiring entire words within filenames to be shoved to be recognized as a script, to provide tooling capabilities in our IDEs ? I thought I wouldn't see the day but here we are.
Kotlin’s requirement of a specific file suffix for runnable scripts is unusual when compared to common scripting languages. Most languages rely on either a shebang, explicit interpreter invocation, or special functions to mark entry points, rather than the file’s name. There are examples of file extensions signaling a certain mode (e.g. Node’s module types, or Gradle using .gradle.kts to distinguish Kotlin DSL scripts), but having to include the word “main” in the file name for a standalone script is a Kotlin-specific quirk
Other ecosystems generally treat file naming as a matter of developer preference or tooling convenience, not a prerequisite for execution. This suggests Kotlin could potentially follow suit by using internal markers or context instead of the filename, to decide how to run a script.
Impacts on Usability and Developer Experience.
There are countless effects on dev experience here
- Discoverability: New users are going to spend days trying to work out why their ridiculous scripts are not even recognized by the IDE. I lost a day on it.
- Surprise in Tools/Automation: Many tools and environments generate or use scripts in a way that didn’t account for Kotlin’s naming rule. A notable example is GitHub Actions. If one tries to use Kotlin as a scripting shell in Actions, the Action runner creates a temporary file for the script without an extension (as it does for other shells). Kotlin’s CLI then refuses to run that file as a script because it doesn’t end in .main.kts lol
In GitHub Actions Issue #813, a developer reported that Kotlin couldn’t be used in a custom action script because “kotlin expects a file name ending in .main.kts, but the runner creates a file without extension”. This meant Kotlin was essentially incompatible with that workflow until a workaround or change was made. It’s an example of how an unconventional requirement can break integration with external systems that assume a more typical interpreter behavior.
Solution
- new extension:
.ktx
- or just make all kts executable ?
- content detection ?
anything is a better idea than enforcing words in file names, almost half a century ago shell scripts were defined to be able to even run without an extension. They still do. We should be able to do much better.
Context & Relevant:
- https://youtrack.jetbrains.com/issue/KT-44242/Allow-running-main.kts-script-that-does-not-end-in-a-main.kts-filename-with-information-from-inside-the-script
- Scripting #77
- https://slack-chats.kotlinlang.org/t/16765016/at-what-point-and-why-did-kts-files-start-needing-to-be-name
- https://github.com/JetBrains/kotlin/blob/dc26f31f3cdfdcee5f77019eb371ff6b2835394a/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/scriptDef.kt