# Adopt an existing project

> Migrate a Java, Kotlin or Spring Boot project from Maven or Gradle to Elide with `elide adopt`: what it runs, its flags and exit codes, which projects it fits, and a worked example.

`elide adopt` starts an AI coding harness (Codex, Claude Code or OMP) in the current directory with a built-in
migration prompt. The harness reads the build, edits files and runs Elide; Elide edits nothing itself. The prompt
targets Java and Kotlin projects built with Maven or Gradle, especially Spring Boot, and tells the harness to keep any
other languages working.

```shell
elide adopt
```

`elide adopt` migrates the build to `elide.pkl`. To keep Maven, Gradle or Bazel and use Elide's compilers inside them,
see [Build tool integration](https://elide.help/docs/build-tools).

## Which projects it fits

| Project | Fit | Why |
| --- | --- | --- |
| Single-module Java or Kotlin app on Maven or Gradle | Good | Dependencies, source layout, tests and JAR map onto `elide.pkl`. Tested. |
| Spring Boot application or service | Good | The prompt checks the main class, Spring dependencies and plugins, resources, tests and packaging. Tested. |
| A JVM build you want to keep, using Elide only to run and compile | Good | Choose **Existing build**: no `elide.pkl` is required. |
| Multi-module builds | Untested | Elide [workspaces](https://elide.help/docs/elide-pkl-reference#workspaces) exist, but the prompt is not evaluated on them. |
| Heavy custom plugins, generated sources, unusual annotation processing | Poor | The harness keeps Maven or Gradle for steps Elide does not replace; expect a partial migration. |
| Android | Untested | The prompt is not evaluated on Android builds. |
| JavaScript, TypeScript or Python only | Not needed | Elide runs `package.json` scripts, `pyproject.toml` entry points and `node:test` files without a migration; see [Project Setup](https://elide.help/docs/projects). |

### Tested projects

These shapes pass `elide install`, `elide build`, `elide test`, startup and the original build, starting from a fresh
checkout, with the Codex harness:

| Project shape | Existing build | Tested on |
| --- | --- | --- |
| Java, Spring Boot application | Maven | Spring Petclinic: dependencies, resources, tests, runnable app, JAR |
| Java, Spring Boot service | Gradle | Spring REST service: dependencies, resources, tests, HTTP readiness |
| Kotlin/JVM command-line app | Gradle Kotlin DSL | Single module with Kotlin serialization and coroutines |

The Claude Code harness is shown on the Kotlin app in the [worked example](#worked-example).

## Before you start

1. Install and sign in to a harness. Elide runs it from `PATH`:

   | Choice | Executable | Harness |
   | --- | --- | --- |
   | `codex` | `codex` | OpenAI Codex CLI |
   | `claude` | `claude` | Claude Code |
   | `omp` | `omp` | OMP |

2. Commit the project, so the migration is one reviewable diff.
3. Build it once with Maven or Gradle, so there is a known-good baseline.
4. `cd` into the project, or pass `-p DIR`.

## Run interactively

`elide adopt` asks three questions, then starts the harness. Flags answer a question in advance.

| Question | Answers | Flag |
| --- | --- | --- |
| Use elide build with an elide.pkl project manifest? | Yes (default): **Elide build**. No: **Existing build** | `--build elide`, `--build existing` |
| Which AI coding harness should perform the migration? | `codex`, `claude`, `omp` | `--harness` |
| How should the harness approve tool calls? | `auto-approve`, `manual-approve`, `yolo` | `--approval` |

```shell
elide adopt --build elide --harness claude
```

Esc on a question exits `0` without starting the harness. Ctrl+C stops the harness and exits `130`.

### Build strategy

| Strategy | The prompt tells the harness to |
| --- | --- |
| **Elide build** | Write `elide.pkl`: keep `src/main`/`src/test` without declaring source sets, keep dependency versions and scopes, set the Java target and release, define the JAR with its main class. Keep Maven or Gradle until a final `elide install`, `elide build`, `elide test`, `elide run` and the original build all pass. |
| **Existing build** | Keep Maven or Gradle as the build; use Elide's runtime and tools only where they help; not create `elide.pkl` just for `elide build`. |

Both end with a summary of changed files, the validation run, and anything left to do.

### Approval mode

| Mode | Codex | Claude Code | OMP | Use for |
| --- | --- | --- | --- | --- |
| `auto-approve` | `--approve-for-me` | `--permission-mode auto` | `--auto-approve` | A committed worktree you will review. |
| `manual-approve` | (no flag) | `--permission-mode manual` | `--approval-mode=always-ask` | Unfamiliar or sensitive repositories. |
| `yolo` | `--dangerously-bypass-approvals-and-sandbox` | `--permission-mode bypassPermissions` | `--approval-mode=yolo` | Disposable environments without secrets. |

With `auto-approve` or `yolo`, Elide runs the harness in batch mode (`codex exec --skip-git-repo-check`,
`claude --print`, `omp --print`) and shows a progress line; `--log` also streams the harness output. With
`manual-approve`, the harness runs interactively and its output is always shown.

## Run without questions

```shell
elide adopt \
  --build elide \
  --harness codex \
  --approval auto-approve \
  --non-interactive
```

`--non-interactive` requires `--build`, `--harness` and `--approval`; a missing one exits `2`. It refuses
`manual-approve`. Without a terminal, `elide adopt` exits `1` unless `--non-interactive` and all three are given.

## Add guidance

`--prompt-append FILE` adds a UTF-8 file to the end of the prompt under `Additional adoption guidance:`. Repeat it to
add several, in order:

```shell
elide adopt --prompt-append ./adoption-guidance.md --prompt-append ./team-rules.md
```

Use it for facts the harness cannot infer: internal repositories, which build to keep, commands that must keep
working.

## Output and exit codes

The harness's edits are the only output in the project. On the [worked example](#worked-example) that was a new
`elide.pkl` and `.gitignore` entries for `.dev/`. Elide prints `Adoption log: PATH` before starting; the log is kept at
`.dev/logs/adopt-<timestamp>-<pid>.log` in the project.

| Exit code | Meaning |
| --- | --- |
| `0` | The harness exited `0`, or a question was cancelled. |
| `1` | The harness failed (`Error: claude exited unsuccessfully (exit status: 3)`), could not start (`Error: failed to launch codex: No such file or directory`), a `--prompt-append` file is unreadable, or there is no terminal. |
| `2` | A flag is missing or invalid. |
| `130` | Interrupted with Ctrl+C. |

## Validate the migration

Exit `0` means the harness finished, not that the migration is correct. Review the diff: dependency versions, source
and resource directories, entry point, tests and packaging. Then run:

```shell
elide install
elide build
elide test
elide run
```

Run the original Maven or Gradle build too, while it exists. If the result is wrong, revert, add guidance with
`--prompt-append`, and run again.

## Worked example

A single-module Kotlin command-line app built with Gradle Kotlin DSL: Kotlin 2.3.20, JVM 17,
`kotlinx-coroutines-core` 1.10.2, `kotlinx-serialization-json` 1.9.0 and one `kotlin("test")` test. Committed, then:

```shell
elide adopt --build elide --harness claude --approval auto-approve --non-interactive
```

```terminaloutput
Adoption log: /path/to/project/.dev/logs/adopt-1767225600-973648.log
[3m 56s] ✓ Project adopted in 3m 56s
```

The harness added `elide.pkl` and a `.gitignore`, and changed nothing else. The manifest keeps the Gradle versions and
moves the rest into Elide's terms:

```pkl
amends "elide:project.pkl"

import "elide:Jvm.pkl" as Jvm
import "elide:Kotlin.pkl" as Kotlin

name = "kotlinx-cli"
version = "1.0.0"

dependencies {
  maven {
    packages {
      "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2"
      "org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0"
      // Gradle mediates annotations to 23.0.0 (via coroutines); Elide's nearest-wins picks 13.0.
      "org.jetbrains:annotations:23.0.0"
    }
    testPackages {
      // Gradle's `kotlin("test")` with `useJUnitPlatform()` resolves to the JUnit 5 variant.
      "org.jetbrains.kotlin:kotlin-test-junit5:2.3.20"
      // The JUnit launcher; with `testing = false`, Elide does not bundle one.
      "org.junit.platform:junit-platform-console:1.10.1"
    }
  }
}

jvm {
  main = "dev.elide.samples.MainKt"
  target = 17
  features {
    // JUnit comes from testPackages above, as with Gradle's `kotlin("test")`; Elide's bundled JUnit is off.
    testing = false
  }
  java {
    source = 17
    release = 17
  }
}

kotlin {
  // Matches the Kotlin Gradle plugin version in build.gradle.kts.
  toolchain = new Kotlin.ManagedKotlinToolchain {
    version = "2.3.20"
  }
  compilerOptions {
    jvmTarget = 17
  }
  features {
    // KotlinX libraries are declared explicitly above, at the versions Gradle uses; only the
    // serialization compiler plugin (Gradle's `plugin.serialization`) is enabled.
    kotlinx = false
    serialization = true
    coroutines = false
    atomicfu = false
    powerAssert = false
    metro = false
    reflection = false
  }
}

artifacts {
  ["jar"] = new Jvm.Jar {
    name = "kotlinx-cli"
    main = "dev.elide.samples.MainKt"
  }
}
```

Validation from a clean `.dev/`:

```terminaloutput
$ elide install
[504ms] ✓ Resolved 25 Maven dependencies (476ms)
[505ms] ✓ Dependencies installed in 484ms
$ elide test
 1 pass
 0 skip
 0 fail
Ran one test across one file. (0.57s)
$ elide run
[ 16ms] ⇥ Dependencies ready (Up to date)
[ 16ms] ⇥ Kotlin main compilation skipped (Up to date)
[ 16ms] ⇥ Java main compilation skipped (Up to date)
[ 17ms] ⇥ Packaging jar 'jar' skipped (Up to date)
{"completed":["PARSE","EMIT"]}
[138ms] ✓ JVM jar application completed successfully (121ms)
[139ms] ✓ Build successful in 126ms
```

`elide build` produced `.dev/artifacts/jar/kotlinx-cli/kotlinx-cli.jar`, and `gradle build` still passed.

## See also

- [Project Setup](https://elide.help/docs/projects) and the [elide.pkl reference](https://elide.help/docs/elide-pkl-reference)
- [Elide for Java users](https://elide.help/docs/elide-for-java), [Elide for Kotlin users](https://elide.help/docs/elide-for-kotlin)
- [`elide adopt` flags](https://elide.help/docs/cli-references#adopt)
