Skip to content
skotch
...

CLI Reference

Compile a single .kt file to a target format. This is the lowest-level entry point — it runs the full lex/parse/typeck/MIR/backend pipeline on one source file and writes the output directly.

Terminal window
skotch emit --target <TARGET> <input.kt> -o <output>
TargetOutputDescription
jvm.classJava 17 class file (v61)
dex.dexDalvik executable (v035)
klib.klibKotlin library (zip with serialized IR)
llvm.llTextual LLVM IR (19+)
nativeexecutableHost binary (via LLVM IR + clang link)
FlagDescription
--target <TARGET>Required. One of jvm, dex, klib, llvm, native.
-o <FILE> / --output <FILE>Required. Output file path.
--norm-out <FILE>Write a normalized text representation alongside the binary output. Used for fixture testing.
Terminal window
# Compile to JVM bytecode and run
skotch emit --target jvm hello.kt -o HelloKt.class
java -cp . HelloKt
# Compile to DEX (for Android)
skotch emit --target dex hello.kt -o classes.dex
# Compile to LLVM IR (text)
skotch emit --target llvm hello.kt -o hello.ll
cat hello.ll
# Compile to native binary
skotch emit --target native hello.kt -o hello
./hello
# Emit a klib archive
skotch emit --target klib hello.kt -o hello.klib
unzip -l hello.klib

Build a project from its build.gradle.kts. Discovers source files under src/main/kotlin/, compiles them, and packages the result.

Terminal window
skotch build [-C <dir>] [--target <TARGET>]
FlagDescription
-C <DIR> / --project-dir <DIR>Project directory. Defaults to the current directory.
--target <TARGET>Override the build target: jvm, android, or native. By default, inferred from build.gradle.kts plugins.
TargetOutput pathFormat
JVMbuild/<name>.jarExecutable JAR with Main-Class manifest
Androidbuild/app-unsigned.apkUnsigned APK with classes.dex and binary AndroidManifest.xml

Skotch parses a subset of the Gradle Kotlin DSL. It recognizes:

plugins {
kotlin("jvm") // → JVM target
id("com.android.application") // → Android target
application // marker plugin
}
group = "com.example"
version = "1.0.0"
application {
mainClass.set("com.example.MainKt") // JVM main class
}
android {
namespace = "com.example.app"
compileSdk = 34
defaultConfig {
applicationId = "com.example.app"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
}
}

Skotch reads settings.gradle.kts to discover modules:

rootProject.name = "myapp"
include(":app", ":lib")

Inter-module project(":lib") dependencies in the dependencies block are recognized. Modules are compiled in dependency order and their class files are merged into the final JAR.

Terminal window
# Build a JVM project (infers target from build.gradle.kts)
skotch build
# Build from a specific directory
skotch build -C /path/to/project
# Override target to Android
skotch build --target android
# Build a multi-module project
cd myapp/
skotch build # reads settings.gradle.kts, compiles :lib then :app

Interactive Kotlin REPL with line editing, backed by an in-process JVM via JNI.

Terminal window
skotch repl [--exec <CODE>] [--file <PATH>] [--exit-after]
FlagDescription
-e <CODE> / --exec <CODE>Execute a snippet before entering interactive mode. Separate statements with ;.
-f <PATH> / --file <PATH>Execute a script file before entering interactive mode.
--exit-afterExit after running --exec / --file instead of entering the interactive prompt.
CommandDescription
:quit / :exitLeave the REPL.
:helpShow available commands.
:historyShow accumulated declarations.

The REPL accumulates top-level declarations (val, var, fun) across turns. Each expression you type is wrapped in a synthetic fun main() { } along with all prior declarations, compiled to a .class file, and executed in the embedded JVM.

skotch> val x = 10
skotch> val y = 20
skotch> println(x + y)
30

The interactive REPL uses reedline for line editing:

  • Arrow keys for cursor movement
  • Up/Down for history browsing
  • Ctrl-R for reverse history search
  • Ctrl-C to abort the current line
  • Ctrl-D to exit
Terminal window
# Interactive REPL
skotch repl
# Run a one-liner and exit
skotch repl --exec 'println("hello")' --exit-after
# Load a setup script, then go interactive
skotch repl --file setup.kts
# Pipe input (non-interactive mode)
echo 'println(1 + 2)' | skotch repl

Execute a .kts Kotlin script file.

Terminal window
skotch run <script.kts>

The script’s contents are wrapped in a synthetic fun main() { }, compiled, and executed. Top-level val and var declarations become locals inside main.

Terminal window
# example.kts
val name = "Kotlin"
println("Hello from $name script!")
Terminal window
skotch run example.kts
Hello from Kotlin script!

Start the Language Server Protocol server on stdin/stdout for use by editors (VS Code, Neovim, Helix, Zed, etc.).

Terminal window
skotch lsp

The LSP server provides:

FeatureDescription
Real-time diagnosticsSyntax and type errors highlighted as you type
Semantic tokensSyntax highlighting with semantic awareness (keywords, functions, types, variables, parameters)
HoverType information and signatures on hover (val x: Int, fun greet(n: String): String)
Go-to-definitionNavigate to function, parameter, and top-level val declarations
CompletionsKeywords, scope identifiers, function signatures, Java class names

VS Code — add to settings.json:

{
"kotlin.languageServer.path": "skotch",
"kotlin.languageServer.arguments": ["lsp"]
}

Neovim (nvim-lspconfig):

require('lspconfig.configs').skotch = {
default_config = {
cmd = { 'skotch', 'lsp' },
filetypes = { 'kotlin' },
root_dir = function(fname)
return vim.fs.dirname(fname)
end,
},
}
require('lspconfig').skotch.setup({})

Discover and run tests.