This page installs the Vidocq CLI, scaffolds a REST application, builds it with plain Maven, and serves a first endpoint — every command below is tested end-to-end against the released 0.2.x artifacts on Maven Central. If you prefer not to use the CLI, jump to the manual annex.

Prerequisites

  • Java 25 (Temurin recommended) — check with java -version

  • Maven 3.9+ — check with mvn -version

With SDKMAN!: sdk install java 25-tem && sdk install maven.

Step 1 — Install the CLI

curl -fsSL https://vidocq.dev/install.sh | sh

On Windows (PowerShell):

irm https://vidocq.dev/install.ps1 | iex

The script downloads the latest released CLI from Maven Central into ~/.vidocq/cli and puts a vidocq launcher on your PATH. Verify:

$ vidocq version
Vidocq CLI 0.3.0
To try what is on main before it is released, install the latest SNAPSHOT CLI instead: curl -fsSL https://vidocq.dev/install.sh | VIDOCQ_VERSION=snapshot sh (PowerShell: $env:VIDOCQ_VERSION='snapshot'; irm https://vidocq.dev/install.ps1 | iex). The projects it scaffolds resolve Vidocq from the Central snapshot repository; see Trying a SNAPSHOT.
No installer needed? Download vidocq-runtime-cli-<version>-cli.zip from Maven Central, unzip it anywhere, and add its bin/ directory to your PATH.

Step 2 — Scaffold a project

vidocq create --name todo --group-id com.acme --extension cassini-rest
cd todo

--extension cassini-rest (short: -x) enables Jakarta REST — it transitively brings the Chappe HTTP server, CDI (Vauban) and JSON-B (Champollion). The generated project is a standard JPMS Maven project:

todo/
  pom.xml                      (1)
  src/main/java/
    module-info.java           (2)
    com/acme/todo/TodoApp.java (3)
  src/main/resources/
    vidocq.properties          (4)
1 Inherits io.vidocq.runtime:vidocq-runtime-parent:0.3.0 and wires the vidocq-runtime-maven-plugin so mvn package produces a runnable distribution.
2 Module descriptor, pre-filled with the requires/opens a REST app needs.
3 The entry point — boots the runtime with VidocqBootstrap.
4 MicroProfile-style configuration (vidocq.http.port=8080, …).
Run vidocq extension list --available to see all first-party extensions, and vidocq help create for the options (--package, --parent-version, …).

Step 3 — Write your first resource

Create src/main/java/com/acme/todo/HelloResource.java:

package com.acme.todo;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/hello")
@ApplicationScoped
public class HelloResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "Hello from Vidocq!";
    }
}

No further wiring: the Cassini annotation processor generates the dispatch adapter at compile time — no runtime reflection.

Step 4 — Build and run

mvn package
sh target/todo-0.3.0/bin/todo.sh

mvn package compiles, runs the code generators, and assembles a standalone distribution under target/todo-0.3.0/ (launchers in bin/, module path in lib/). In another terminal:

$ curl http://localhost:8080/hello
Hello from Vidocq!

The runtime boots in well under a second — the log line to look for:

INFOS: Vidocq - Started in 90.940 ms (process running for 135 ms)

Step 5 — Dev mode

mvn vidocq:dev

Dev mode launches the application on its module path and watches your sources. It uses the vidocq.mainModule / vidocq.mainClass properties already set in the generated pom.

Nothing to add: since todo already has the Chappe HTTP server (through cassini-rest), mvn vidocq:dev also serves the dev console on its own NEW: Vidocq dev console: http://127.0.0.1:8888/ opens the startup report of the running application and the live values of its extensions.

To run the application once, without the watcher, use mvn vidocq:run NEW: it compiles, completes the bean index and forks the same JVM, and its exit code is the build’s. See the vidocq:run goal.

mvn vidocq:idea NEW writes IntelliJ IDEA run configurations for what an IDE should run: by default, three files per application — a Maven run of vidocq:dev (the one above, console included), one of vidocq:run suffixed ` (packaged), and a Remote JVM Debug one suffixed ` (debug) that attaches to vidocq:dev’s own debug agent. See the `vidocq:idea goal.

vidocq dev and vidocq start (the CLI commands, as opposed to the Maven goal) boot the runtime from the CLI’s own module path and therefore do not see the extensions declared in your pom. Prefer mvn vidocq:dev and the packaged launcher for extension-based apps.

Step 6 — Add extensions as you grow

vidocq extension list --available
vidocq extension add knock-health
mvn package

extension add edits your pom.xml with the correct coordinates. See Usage for the per-extension configuration keys, and the examples tour for a full REST + persistence application (Mansart Data + H2).

Step 7 — Package for production

vidocq build jlink    # self-contained runtime image (no local java needed)
vidocq build docker   # container image

See Usage for jlink/jpackage/Docker options and AOT notes.

Annex — Without the CLI

The CLI is a convenience, not a requirement. The project above is plain Maven — here is the complete, copy-pasteable equivalent.

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>io.vidocq.runtime</groupId>
        <artifactId>vidocq-runtime-parent</artifactId>
        <version>0.3.0</version>
        <relativePath/>
    </parent>

    <groupId>com.acme</groupId>
    <artifactId>todo</artifactId>
    <name>todo</name>

    <properties>
        <vidocq.mainModule>com.acme.todo</vidocq.mainModule>
        <vidocq.mainClass>com.acme.todo.TodoApp</vidocq.mainClass>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.vidocq.runtime</groupId>
            <artifactId>vidocq-runtime-core</artifactId>
            <version>0.3.0</version>
        </dependency>
        <dependency>
            <groupId>io.vidocq.runtime.extensions.jakartaee.core</groupId>
            <artifactId>vidocq-runtime-cassini-rest-extension</artifactId>
            <version>0.3.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>io.vidocq.runtime</groupId>
                <artifactId>vidocq-runtime-maven-plugin</artifactId>
                <configuration>
                    <jvmArgs>-Dfile.encoding=UTF-8</jvmArgs>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>package</goal>
                        </goals>
                        <configuration>
                            <mainClass>${vidocq.mainModule}/${vidocq.mainClass}</mainClass>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <annotationProcessorPaths combine.children="append">
                        <path>
                            <groupId>io.vidocq.runtime.extensions.jakartaee.core</groupId>
                            <artifactId>vidocq-runtime-cassini-rest-extension-codegen</artifactId>
                            <version>0.3.0</version>
                            <type>pom</type>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
Dependency versions are pinned on purpose: the released parent’s dependencyManagement uses ${project.version}, so an app relying on it must inherit the parent’s version. The two vidocq-runtime-maven-plugin configuration blocks work around known 0.2.0 issues (fixed in 0.3.0).

src/main/java/module-info.java:

module com.acme.todo {
    // APT-generated $$CassiniAdapter classes import @Generated (SOURCE retention).
    requires static java.compiler;

    requires jakarta.cdi;
    requires jakarta.inject;
    requires jakarta.ws.rs;
    requires jakarta.json.bind;

    requires io.vidocq.runtime.core;
    requires io.vidocq.runtime.extensions.jakartaee.core.cassini;
    requires io.vidocq.cassini.api;

    // JAX-RS and JSON-B reflect on resource classes and payload types.
    opens com.acme.todo;
}

This opens works because the resources live in the same module as the main class. In a multi-module application (e.g. hexagonal, resources in their own Java module), the module system only lets a module open packages it owns: the opens must move into the module that contains the classes, and the runtime module scans it with <scanDependencies>. See Usage — Multi-module applications.

src/main/java/com/acme/todo/TodoApp.java:

package com.acme.todo;

import io.vidocq.runtime.core.Vidocq;
import io.vidocq.runtime.spi.VidocqMain;

/**
 * Entry point. {@code main} is a trampoline: {@code Vidocq.run} resolves the application
 * into the Vauban layer and boots it there, from the IDE, {@code vidocq start} or a jlink
 * image alike. Put no code before it: it would run outside that layer.
 */
@VidocqMain
public final class TodoApp {

    public static void main(String[] args) {
        Vidocq.run(args);
    }
}

src/main/resources/vidocq.properties:

# Vidocq application configuration
vidocq.http.port=8080

Then add the HelloResource from Step 3 and continue from Step 4 (mvn package) — the flow is identical.

Next steps