Skip to content

Quickstart

By the end of this page you'll have started a readable CLI session, then asked the daemon two compiler-backed questions: "what symbol is this?" and "who uses it?" The lifecycle commands render readable summaries by default; raw analysis requests still return JSON-RPC payloads.

The walkthrough uses the headless backend because it works on Linux terminals, CI runners, and agent loops after the Linux headless tarball is installed. If IDEA or Android Studio is already open on the project with the plugin installed, swap --backend=headless for --backend=idea and skip the start/stop steps. The plugin reuses the IDE's analysis session — no second daemon to babysit.

Before you begin

You need:

  • Kast installed through the Linux headless bundle, or through Homebrew plus the IDEA plugin on macOS (see Install)
  • A Kotlin workspace on your machine — Gradle or plain
  • The absolute path to that workspace root
About Gradle discovery

With settings.gradle(.kts) or build.gradle(.kts) at the root, headless discovery uses Gradle's project model. Without those files, kast falls back to conventional source roots and a source-file scan. The Gradle path matters most for multi-module builds.

Step 1: Start the headless backend

Run commands from your project root or any subdirectory below it. Kast walks up to the nearest Gradle or .kast marker when --workspace-root is omitted. The first call is the slow one — the daemon discovers your project and indexes Kotlin files. After that, you're hitting a warm session.

First-time local setup
./scripts/install-ubuntu-debian.sh install
Start the daemon
kast up --backend=headless
sequenceDiagram
    participant You
    participant CLI as "kast CLI"
    participant Daemon as "Analysis daemon"
    participant K2 as "K2 engine"

    You->>CLI: up
    CLI->>Daemon: Start process
    Daemon->>K2: Bootstrap session
    K2-->>Daemon: Indexing complete
    Daemon-->>CLI: READY
    CLI-->>You: Rendered status summary

The first start indexes every Kotlin file. Later commands reuse the warm state — the cost you pay here buys you fast lookups for the rest of the session.

The default output is meant to be read. In an interactive terminal, headings and inline code are styled; in logs and captured output, the same summary is rendered as plain text:

Example output
  Kast up
  =======

  - Workspace: /workspace
  - Started new daemon: yes

  Selected runtime
  ----------------
  - Backend: headless
  - Runtime state: READY

Use --output json on lifecycle and install commands when a script needs the original structured payload.

Step 2: Resolve a symbol

Pick a Kotlin file and a byte offset that lands on a symbol name. kast returns the fully qualified name, kind, signature, and source location of the declaration at that offset.

How to get an offset

The fast way: grep -bo 'functionName' src/main/kotlin/App.kt prints the byte offset of every match.

Resolve a symbol
1
2
3
4
APP_FILE="$PWD/src/main/kotlin/App.kt"

kast rpc \
  "{\"jsonrpc\":\"2.0\",\"method\":\"raw/resolve\",\"params\":{\"position\":{\"filePath\":\"$APP_FILE\",\"offset\":42}},\"id\":1}"
Example response
{
  "result": {
    "fqName": "com.example.App.processOrder",
    "kind": "FUNCTION",
    "returnType": "OrderResult",
    "parameters": [
      { "name": "orderId", "type": "String" }
    ],
    "location": {
      "filePath": "/workspace/src/main/kotlin/App.kt",
      "startLine": 12, "startColumn": 5
    }
  }
}

fqName and kind are compiler identity, not text matches. Every later command can stay anchored to this declaration without ambiguity.

Step 3: Find references

Same file, same offset. Ask for every reference across the workspace.

Find references
1
2
3
4
APP_FILE="$PWD/src/main/kotlin/App.kt"

kast rpc \
  "{\"jsonrpc\":\"2.0\",\"method\":\"raw/references\",\"params\":{\"position\":{\"filePath\":\"$APP_FILE\",\"offset\":42}},\"id\":1}"
Example response
{
  "result": {
    "declaration": {
      "fqName": "com.example.App.processOrder",
      "kind": "FUNCTION"
    },
    "references": [
      {
        "filePath": "/workspace/src/.../CheckoutController.kt",
        "startLine": 45,
        "preview": "app.processOrder(orderId)"
      }
    ],
    "searchScope": {
      "exhaustive": true,
      "candidateFileCount": 12,
      "searchedFileCount": 12
    }
  }
}

searchScope.exhaustive: true is the part that matters. kast walked every candidate file. The reference list is complete for this workspace — not a sample, not a best effort.

Step 4 (optional): stop the daemon

Free the resources when you're done.

Stop the daemon
kast stop --backend=headless

What just happened

Four commands. You:

  1. Started a daemon that indexed your Kotlin codebase into a live K2 session.
  2. Resolved a cursor position to a real declaration with type info — no string match.
  3. Got every reference back as JSON-RPC, with proof the search was exhaustive.
  4. Shut the daemon down cleanly.

The CLI defaults to readable summaries for lifecycle work and keeps JSON where JSON is the contract: kast rpc and explicit --output json calls. No regex, no guessing, no "we might have missed some."

Next steps