Skip to content

L1: Agnostic Environment and Hello World

If you have ever tried running a Windows .exe executable on a Mac, or an iOS application on an Android smartphone, you know that they simply do not work.

Historically, programming languages (like C or C++) compile directly down to machine code. That means they are translated into the physical, specific instruction set of that exact computer processor and operating system. If you compile for Windows x86, a macOS ARM machine will not understand a single byte.

Imagine having to rewrite and recompile your AI Chat application separately so your friends on Mac, Linux, and Windows could run it. This is where the engineering brilliance of the Java and Kotlin ecosystem comes in.


Imagine you are an acclaimed playwright and you just completed a masterpiece (your Kotlin source code). You want your play performed in theaters all over the world: in Tokyo, Paris, and Mexico City (Windows, Mac, and Linux).

You have two paths:

  1. The traditional path (C++): You manually translate and localize the script into every native language and cultural context before shipping it. (A titanic effort).
  2. The JVM path: You translate your script into an invented, universal language—one that no country speaks natively, but which is syntactically pristine. Then, in every theater worldwide, you employ an orchestra conductor who understands this universal language fluently and directs the local actors in real time.

In software engineering:

  • The “universal language” is called Bytecode.
  • The “orchestra conductor” installed on each machine is called the Java Virtual Machine (JVM).

Under the Hood: Why is Kotlin “Platform-Agnostic”?

Section titled “Under the Hood: Why is Kotlin “Platform-Agnostic”?”

Kotlin (when targeting the JVM) does not directly generate machine binaries (.exe or .app). When you write Kotlin code and trigger “Compile”, the Kotlin compiler (kotlinc) parses your source code and generates .class files packed with JVM Bytecode.

For this agnostic bytecode to execute, the destination computer needs a JVM installed. The JVM ingests the bytecode, interprets or Just-In-Time (JIT) compiles it on the fly, and feeds native CPU instructions to the processor. This is why the foundational ethos of this ecosystem is: “Write once, run anywhere”.


Anatomy of a Kotlin Project: Demystifying Gradle

Section titled “Anatomy of a Kotlin Project: Demystifying Gradle”

When developers open a Kotlin project for the first time, they typically encounter files like build.gradle.kts, settings.gradle.kts, or directories named gradle/wrapper/. For many, this looks like an intimidating, magical “black box”. Let’s demystify it step-by-step.

In professional software development, we do not compile projects by manually issuing terminal commands file-by-file. We use a Build Tool and automation system. Across the Kotlin and Android ecosystems, the industry standard is Gradle.

  • settings.gradle.kts: The very first file Gradle evaluates. It defines your root project name (rootProject.name = "ai-chat-cli") and registers repository endpoints required to fetch build plugins.
  • build.gradle.kts: The primary build manifest. Here you declare applied plugins (e.g., kotlin("jvm")), the target Java toolchain (JavaVersion.VERSION_17), and external libraries required by your application.
  • gradle/libs.versions.toml: Known as the Version Catalog. A centralized dependency table where plugin and library versions are declared in a single place, eliminating duplicate or drifting version numbers across modules.
  • Kotlin DSL (.kts) vs Groovy (.gradle): Historically, Gradle relied on Groovy (a dynamically typed language). Modern projects use Kotlin DSL (files ending in .kts). The key advantage is that your build configuration is authored in the exact same Kotlin language you are learning: complete with IDE autocomplete, compile-time syntax validation, and robust static typing.

🧠 Conceptual Bridge: How does Gradle compare to your ecosystem?

Section titled “🧠 Conceptual Bridge: How does Gradle compare to your ecosystem?”

Coming from Node.js, npm, or the modern web:

  • build.gradle.kts is the direct equivalent to your package.json, declaring dependencies and executable tasks.
  • gradle/libs.versions.toml functions like centralized workspace dependency catalogs in monorepos using pnpm-workspace.yaml.
  • The task ./gradlew run is equivalent to running npm run dev or pnpm start.
  • Gradle plugins (kotlin("jvm")) correspond to bundlers and compiler toolchains like esbuild, tsc, or vite.

Where are dependencies stored? (Global Immutable Cache vs node_modules)

Section titled “Where are dependencies stored? (Global Immutable Cache vs node_modules)”

One of the biggest surprises for developers coming from JavaScript or Python is opening a Kotlin project directory and wondering: “Where are the libraries Gradle downloaded? There is no node_modules or .venv folder here!”.

The Role of the Gradle Wrapper (./gradlew)

Section titled “The Role of the Gradle Wrapper (./gradlew)”

In the project root, you will find two key executable scripts: ./gradlew (for macOS and Linux) and gradlew.bat (for Windows).

Why do they exist, and why should you never delete them? The Gradle Wrapper is a lightweight, portable bootstrap utility designed to guarantee deterministic build reproducibility:

  1. You do not need to install Gradle globally on your machine using Homebrew, SDKMAN, or Windows installers.
  2. When you run ./gradlew run for the first time, the wrapper inspects gradle/wrapper/gradle-wrapper.properties, automatically downloads the exact Gradle runtime required by the project, caches it, and executes the target task.
  3. This ensures every engineering team member and student compiles against the exact same tooling behavior, eradicating the infamous “works on my machine” problem.

Throughout this course, we will not work on disconnected toy exercises. We will incrementally build an interactive AI Chat CLI in the Terminal. Today, our mission is to prepare the foundation, set up professional engineering tools, and raise our project flag with a “Hello World”.

Clone the official course repository. We use Git Tags so you can time-travel to any lesson state at will:

In professional Kotlin and Java engineering, we choose our tooling depending on development workflows and available hardware resources:

The recommended environment by JetBrains and the primary industry standard:

  1. Download and install IntelliJ IDEA Community Edition (free) or Android Studio.
  2. Select Open and choose the root directory of the cloned repository.
  3. Wait a few moments for the Gradle tool window (on the right sidebar) to synchronize and index dependencies.
  4. Ensure the project is configured with JDK 17 or higher (File -> Project Structure -> Project SDK).

Every program requires an “entry point”—the exact place where the JVM knows execution begins. In Kotlin, this is simply a function named main.

Open src/main/kotlin/Main.kt, clear its contents, and let’s craft our Chat welcome banner:

/**
* Main entry point of our Kotlin application.
*
* The JVM will search for this exact 'main' function across our project
* to initiate execution.
*/
fun main() {
// println is a Kotlin standard library function.
// It outputs text to the standard console and appends
// an invisible newline (Enter) at the end.
println("===============================")
println("🤖 Welcome to AI Chat CLI")
println("===============================")
}

Select your preferred execution workflow depending on your tooling:

Open src/main/kotlin/Main.kt and, directly to the left of the fun main() line, click the green Play (▶️) button in the gutter. Select Run ‘MainKt’. The IDE will trigger the Kotlin compiler, translate the source code into Bytecode, and launch the JVM in the bottom Run tool window.

If you see the welcome banner… congratulations! You have configured an agnostic development environment, understand Gradle’s architecture, and are ready to program interactive application logic in the next lesson.


To deepen your understanding of JVM internals and the Kotlin compilation pipeline:


Did you encounter any hurdles setting up Gradle or your JDK, or have suggestions for this lesson?