How to Start Your First Vidocq App

From zero to a booted runtime in under ten minutes with the new Vidocq CLI — doctor, create, build, start, and your first extension.

Vidocq banner

Vidocq is a zero-dependency Jakarta EE / MicroProfile runtime for Java 25: JPMS-native, virtual-threads-first, and built on compile-time code generation instead of runtime reflection. The runtime now ships a command-line interface, and this post walks through it end to end: scaffold a new application, boot it, and wire in your first extension — in under ten minutes.

Note
Update 2026-07: the always-current version of this walkthrough lives in the official documentation — Getting started — and the CLI now installs with a one-liner (below). Thanks to our first external users for the feedback!

Prerequisites

  • Java 25 (Temurin recommended)

  • Maven 3.9.16

Every Vidocq repository pins both via .sdkmanrc, so sdk env inside a checkout puts you on the right versions.

Install the CLI (from Maven Central)

Every brick of the ecosystem — CLI included — is published to Maven Central, and the CLI ships as a self-contained distribution (a JPMS module path plus launchers). One line installs it:

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

On Windows (PowerShell):

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

The script resolves the latest release from Central, unpacks it into ~/.vidocq/cli and puts a vidocq launcher on your PATH. No Maven involved. Prefer doing it by hand? Grab vidocq-runtime-cli-<version>-cli.zip from Central, unzip, and add its bin/ to your PATH.

Tab completion is one line away: source <(vidocq completion bash).

Check your environment

vidocq doctor
Vidocq doctor — environment & project checks

  ✔ Java version     Java 25
  ✔ JAVA_HOME        /Users/you/.sdkman/candidates/java/25-tem
  ⚠ Maven wrapper    no mvnw on this path
  ⚠ Vidocq project   no pom.xml in the current directory
  ✔ Config           no vidocq.properties (built-in defaults apply)
  ⚠ Extensions       no extensions on the classpath

✔ No blocking issues found.
  6 checks — 3 ok, 3 warning(s), 0 failed

Warnings are expected outside a project. doctor only exits non-zero on a blocking ✘, which makes it a handy CI pre-flight gate: vidocq doctor && vidocq build.

Scaffold the project

vidocq create --name hello-world --group-id com.example
ℹ Scaffolding project 'hello-world'…
✔ Project 'hello-world' created.

  Navigate:  cd hello-world
  Build:     ./mvnw package
  Run:       vidocq start

Four files, nothing hidden:

hello-world/
├── pom.xml                          # inherits vidocq-runtime-parent, depends on core
└── src/main/
    ├── java/
    │   ├── module-info.java
    │   └── com/example/hello/world/
    │       └── HelloWorldApp.java
    └── resources/
        └── vidocq.properties        # vidocq.http.port=8080

The module descriptor is a single requires — no opens, no classpath:

module com.example.hello.world {
    requires io.vidocq.runtime.core;
}

and the entry point is a complete, runnable Vidocq application:

package com.example.hello.world;

import io.vidocq.runtime.core.VidocqBootstrap;

public final class HelloWorldApp {

    public static void main(String[] args) {
        VidocqBootstrap.create()
                .configure()
                .start()
                .awaitShutdown();
    }
}

One heads-up: the scaffold does not ship a Maven wrapper yet, so vidocq build falls back to the mvn on your PATH — make sure it is 3.9.16.

Build and boot it

cd hello-world
vidocq build --skip-tests
vidocq start
ℹ Starting Vidocq on port 8080…
INFO: Vidocq - Configuration phase
WARNING: No Vidocq extensions discovered
INFO: Vidocq - Starting
INFO: Vidocq - Started in 39.755 ms (process running for 82 ms)

Under 40 milliseconds to a running runtime — no reflection scan, no proxy generation at boot. The warning is honest, though: a bare core application boots the lifecycle but serves nothing, because in Vidocq everything is an extension.

For iterating, prefer dev mode: vidocq dev watches your sources and resources and re-applies configuration in-process on every change, and --debug prints the JDWP line a debugger can attach to.

Add your first extension

Extensions are how a Vidocq application grows capabilities — each one wraps an independent brick of the ecosystem. The CLI knows the catalog:

vidocq extension list --available
Available extensions:
  • chappe-webserver       Chappe HTTP web server
  • ravel-config           MicroProfile Config
  • cassini-rest           Jakarta REST (JAX-RS) endpoints
  • cyrano-rest-client     MicroProfile REST Client
  • cervantes-jwt          MicroProfile JWT authentication
  • humboldt-telemetry     MicroProfile Telemetry (tracing)
  • knock-health           MicroProfile Health checks
  • dirac-metrics          MicroProfile Metrics
  • mansart-data           Jakarta Persistence (JPA)
  • mansart-pool           JDBC connection pooling
  • mansart-transactions   Jakarta Transactions (JTA)

Adding one edits your pom.xml in place — text-based, format-preserving, idempotent:

vidocq extension add cassini-rest
✔ Wired vidocq-runtime-cassini-rest-extension-codegen  (annotationProcessorPaths)
✔ Added cassini-rest  (io.vidocq.runtime.extensions.jakartaee.core:vidocq-runtime-cassini-rest-extension)

✔ pom.xml updated.

Since CLI 0.2.2, extension add also wires the extension’s annotation-processor bundle on the compiler path — the compile-time codegen works immediately on the next build.

From there, a @Path resource class is all Cassini needs: its annotation processor generates the dispatch adapters at compile time and wires them through JPMS provides clauses — zero runtime reflection, zero opens, GraalVM-friendly. The complete walkthrough (REST resource, CDI, H2 persistence, curl calls) lives in the reference documentation's getting-started guide, and we won’t duplicate it here.

Package it

When you are ready to ship, the CLI wraps the packaging goals of the Vidocq Maven plugin:

vidocq build            # standalone distribution
vidocq build jlink      # self-contained runtime image, no java needed on the target
vidocq build docker     # Dockerfile around the jlink image

Where to go next