Manage the app lifecycle
apps: in axx.yaml describes the system under test: your service and anything it needs, such as databases, brokers and mocks. axx run starts them, waits until they are ready, runs the scenarios, stops them and runs their cleanup.
Declare an app
Section titled “Declare an app”apps: infra: dir: ./infra # relative to axx.yaml command: docker compose up --wait postgres kafka ready: tcp: localhost:5432 cleanup: docker compose down -v --remove-orphans
api: dependsOn: [infra] command: ./gradlew bootRun # or npm start, go run ./cmd/api, ... env: SPRING_PROFILES_ACTIVE: acceptance ready: http: url: http://localhost:8080/actuator/health timeout: 120s interval: 1s stop: signal: SIGTERM grace: 20sEach key is described in the configuration reference. A command that exits 0 before the app is ready is fine, which is what docker compose up -d or --wait does: Axx keeps polling the ready checks.
App output goes to .axx/logs/apps.log. When an app fails to start, the error shows the last lines of its output and a stable code from AXX-E0400 to AXX-E0414.
Keep apps running between runs
Section titled “Keep apps running between runs”axx up # start every enabled app (or: axx up api) and wait until readyaxx run # reuses the running apps: no start, no stopaxx run --tags @smokeaxx down # stop the apps and run their cleanupThis is the fastest local loop, and the one agents should use. axx down also stops apps left behind by an interrupted run.
Run an app yourself
Section titled “Run an app yourself”To run the service from your IDE (with breakpoints, hot reload, a profiler), tell Axx not to start it. Axx still starts everything else and waits for your app’s readiness checks:
axx run --attach api--no-start skips starting, stopping and cleaning up every app; use it when the whole system is already running somewhere.
Debug an app
Section titled “Debug an app”Give the app a debug command and a debugger to wait for:
apps: api: command: ./gradlew bootRun debug: command: ./gradlew bootRun -PappJvmArgs=-agentlib:jdwp=transport=dt_socket,server=n,address=localhost:5005,suspend=n debugger: type: java # java, go, nodejs or python port: 5005 mode: ide-listens # the IDE listens, the app connects (default for java) onUnavailable: retry # retry (default), fail, or fallback to the normal command retry: {attempts: 10, delay: 3s}axx run --debug # every app with a debug blockaxx run --debug=api # only apiaxx up --debug=apiWith mode: ide-listens, start a listening debugger in your IDE first (in IntelliJ IDEA: a Remote JVM Debug configuration in Listen to remote JVM mode on port 5005), then run Axx. With mode: app-listens (delve, --inspect, debugpy), the app opens the port and you attach; the parcels example runs its Go service under Delve this way. If no debugger is listening, onUnavailable decides whether to wait, fail with AXX-E0409, or run without debugging.
Start only what a run needs
Section titled “Start only what a run needs”In a repository with several services, start only the apps the selected scenarios need:
active: enabled: true onNoTags: fallback # scenarios without tags: start every enabled app (or: error)
apps: orders: command: ./gradlew :orders:bootRun active: {tags: ["@orders"]} billing: command: ./gradlew :billing:bootRun active: {tags: ["@billing", "@payments"]} wiremock: command: docker compose up wiremock # no active.tags: always startsAn app with active.tags starts when any selected scenario carries one of its tags. Apps without active.tags always start. axx run --tags @billing starts billing and wiremock, not orders.