Getting started

Enkan is a middleware-chain-based web framework for Java 25. Its core idea is
explicitness over convention: every component, every middleware, and every
dependency is declared in plain Java code — no classpath scanning, no
auto-configuration, no magic.

The fastest path from zero to a running application is the /init command,
which turns a plain-English description of your app into a compilable project
skeleton in minutes.

Prerequisite

  • Java 25 or higher
  • Maven 3.6.3 or higher
  • An API key for an OpenAI-compatible chat completion endpoint (only for /init)

Scaffold a project with /init (recommended)

/init is the entry point to the Enkan ecosystem. It is an AI-powered project
generator built into the standalone REPL client. You describe your application
in natural language, review a generated plan, and init writes a compilable
project skeleton — complete with routing, controllers, domain records, database
migrations, and a development REPL server — then compiles it and optionally
starts it for you.

No Enkan knowledge is required to run /init. It is intentionally designed as
the first thing a new user does.

You describe your app
        ↓
/init collects requirements interactively
        ↓
LLM generates a plan (you can revise it)
        ↓
Project files are written
        ↓
mvn compile runs (with auto-fix loop)
        ↓
App starts + REPL connects
        ↓
You are live inside a running Enkan application

1. Download the REPL client

Grab the standalone client jar from the
latest release:

curl -L -o enkan-repl-client.jar \
  https://github.com/enkan/enkan/releases/latest/download/enkan-repl-client.jar

2. Configure the LLM endpoint

/init uses an OpenAI-compatible chat completion API. It works with OpenAI,
Anthropic’s OpenAI-compatible endpoint,
LM Studio, Ollama, vLLM, and any other server that speaks the same protocol.

Env var System property Default
ENKAN_AI_API_URL enkan.ai.apiUrl https://api.anthropic.com/v1
ENKAN_AI_API_KEY enkan.ai.apiKey (required)
ENKAN_AI_MODEL enkan.ai.model claude-sonnet-4-5

The URL may be either a base (/v1) or the full path (/v1/chat/completions) —
both are accepted.

export ENKAN_AI_API_KEY=sk-...

3. Run /init

java -jar enkan-repl-client.jar
  Enkan Project Generator

── Project Setup ─────────────────────────
? What kind of application do you want to build? REST API for a bookstore
? Project name [rest-api-bookstore]:
? Group ID [com.example]:
? Output directory [./rest-api-bookstore]:

── Plan Draft ────────────────────────────
(the LLM shows a proposed plan — components, routes, file list)
Plan feedback (say 'yes' to proceed, or describe changes, 'cancel' to abort) > yes

── Generating ────────────────────────────
  ✓ src/main/java/.../BookstoreApplicationFactory.java
  ✓ src/main/java/.../BookController.java
  ...

✓ Done! Created 5 file(s)

── Compiling ─────────────────────────────
✓ Compilation succeeded.

? Start and connect to the generated app? [Y]:
⚡ Starting app (mvn compile exec:exec -Pdev)...
Connected to server (port = 3001)
enkan(3001)❯

At the enkan(3001)❯ prompt you are connected to a running REPL server inside
your new project. From here you can run /routes,
/start, /stop, /reset, or evaluate live Java expressions.

What /init generates

/init writes the following files verbatim (without touching the LLM), so the
scaffold is always consistent:

  • pom.xml — including the dev profile that runs DevMain
  • src/dev/java/.../DevMain.java — starts the REPL server
  • src/main/java/.../<Project>SystemFactory.java — minimal EnkanSystem.of(...) skeleton

The LLM then fills in the ApplicationFactory, controllers, and domain classes
based on your approved plan. The default generated stack is:

Layer Technology
HTTP server Jetty (virtual threads)
MVC Kotowari
JSON Jackson
Connection pool HikariCP
SQL jOOQ
Row mapping Raoh
Migrations Flyway
Database H2 (in-memory, dev)

Manual setup

If you prefer to wire everything by hand, add kotowari (MVC framework) and a
server component to your pom.xml:

<dependency>
  <groupId>net.unit8.enkan</groupId>
  <artifactId>kotowari</artifactId>
  <version>0.15.0</version>
</dependency>
<dependency>
  <groupId>net.unit8.enkan</groupId>
  <artifactId>enkan-component-jetty</artifactId>
  <version>0.15.0</version>
</dependency>

If you only need the middleware core without MVC routing, use enkan-web instead of kotowari.

Hello World

1. Define your application factory

An application factory builds the middleware stack and routing table:

import enkan.Application;
import enkan.application.WebApplication;
import enkan.config.ApplicationFactory;
import enkan.middleware.*;
import enkan.system.EnkanSystem;
import kotowari.middleware.*;
import kotowari.routing.Routes;

public class MyAppFactory implements ApplicationFactory {
    @Override
    public Application create(EnkanSystem system) {
        WebApplication app = new WebApplication();

        Routes routes = Routes.define(r -> {
            r.get("/").to(HomeController.class, "index");
        }).compile();

        app.use(new DefaultCharsetMiddleware());
        app.use(new ContentTypeMiddleware());
        app.use(new ParamsMiddleware());
        app.use(new RoutingMiddleware(routes));
        app.use(new ControllerInvokerMiddleware(system));
        return app;
    }
}

2. Write a controller

Controllers are plain Java classes — no annotations, no base class:

import enkan.data.HttpResponse;

public class HomeController {
    public HttpResponse index() {
        return HttpResponse.of("Hello, World!");
    }
}

3. Wire the system

import enkan.system.EnkanSystem;
import enkan.component.ApplicationComponent;
import enkan.component.jetty.JettyComponent;

import static enkan.system.EnkanSystem.component;

public class MySystemFactory {
    public EnkanSystem create() {
        return EnkanSystem.of(
            "app",  new ApplicationComponent(MyAppFactory.class.getName()),
            "http", new JettyComponent()
        ).relationships(
            component("http").using("app")
        );
    }
}

Start the REPL

% mvn -e compile exec:java

Start the system with the /start command:

enkan> /start

Access http://localhost:3000/ in your browser.

What’s next?