What are Gradle's console output modes (--console=plain/rich/auto), and what does each one do?
answer
- plain / rich / auto / verbose
- auto = TTY detection
- rich forces ANSI even when redirected
- verbose adds UP-TO-DATE/SKIPPED lines
- org.gradle.console property
basics
~20 sGradle has three console modes. plain gives flat text with no colors or progress bar. rich forces colors and the animated progress bar. auto (the default) picks rich when attached to a terminal, plain otherwise.
solid answer
~40 sGradle's `--console` flag controls how build output is rendered. There are three values: - **`plain`** — no ANSI color, no animated progress bar, no in-place line rewriting. Output is a flat append-only stream, ideal for CI logs and log files. - **`rich`** — always emits ANSI colors and the live, redrawing progress/work-in-progress area, even when stdout is not a TTY. - **`auto`** (default) — Gradle detects whether stdout is attached to an interactive terminal; if so it behaves like `rich`, otherwise like `plain`. There is also a `verbose` mode, which is like `rich` but additionally prints lifecycle output for every task (including up-to-date/skipped ones). You can set the mode persistently with the `org.gradle.console` Gradle property instead of passing the flag each time. For CI you typically force `plain` so logs don't contain control characters.
code
bash · 8 lines# Flat, CI-friendly output
./gradlew build --console=plain
# Force colors + progress bar even into a pipe
./gradlew build --console=rich | tee build.log
# Show a line for every task, including UP-TO-DATE
./gradlew build --console=verbosego deeper
Name the three core modes and that auto is the default which detects a terminal.
Explain the TTY detection in auto, that rich forces ANSI even into a pipe, and the verbose extra-lines behavior.
Tie modes to ANSI handling and the transient status area; recommend plain for CI and the org.gradle.console property for persistence.
Frame console mode as part of a reproducible, log-hygiene build policy standardized across all CI pipelines and the gradle.properties baseline.
## What "console output mode" means When Gradle runs, it writes two kinds of things to your terminal: **persistent log lines** (task headers, warnings, your `println`/logger output) and a **transient status area** at the bottom — the animated progress bar plus the "work in progress" lines showing which tasks are executing right now. To draw that transient area, Gradle uses **ANSI escape codes**: special byte sequences (e.g. `\u001b[2K` to clear a line, `\u001b[31m` to color text red) that a real terminal interprets but a plain log file does not. The `--console` command-line flag (and its persistent twin, the `org.gradle.console` property) selects the rendering strategy. ## The four values - **`auto`** — the default. Gradle inspects whether its standard output is connected to a terminal (a TTY). Interactive shell → render like `rich`. Redirected to a file or a CI pipe → render like `plain`. This "do the right thing" behavior is why most local runs look colorful and most CI runs look flat without any configuration. - **`plain`** — disables ANSI entirely: no colors, no bold, no progress bar, no cursor movement. Every line is written once and never rewritten. This is the safe choice for log files, CI systems that don't emulate a terminal, and anything that greps or diffs build output. - **`rich`** — forces the full interactive experience: colors, the bottom progress bar, and in-place redrawing of the work-in-progress area — *even when output is redirected*. Use it when your CI does emulate a terminal and you want the colored output preserved. - **`verbose`** — same visuals as `rich`, but also prints a lifecycle line for **every** task, including ones that are `UP-TO-DATE`, `SKIPPED`, `NO-SOURCE`, or `FROM-CACHE`. By default Gradle hides those to reduce noise; `verbose` shows the full task graph as it executes. ## Setting it ``` # one-off ./gradlew build --console=plain # persistent, in gradle.properties org.gradle.console=plain ``` The property is read from `gradle.properties` (project or `~/.gradle/`) and from the `ORG_GRADLE_PROJECT_`/`-D` mechanisms. A command-line `--console` always wins over the property for that invocation. ## Why it matters The progress bar and colors rely on the terminal honoring ANSI control characters and cursor movement. A log aggregator that just stores bytes will capture the raw escape sequences as garbage like `^[[2K^[[1A`, making logs unreadable. Forcing `plain` (or letting `auto` detect the non-TTY) keeps CI logs clean and diffable.
- What does `verbose` add over `rich`?Identical visuals, but it also prints a lifecycle line for every task — including UP-TO-DATE, SKIPPED, NO-SOURCE and FROM-CACHE tasks that rich/auto normally suppress.
- If you pass `--console=rich` but redirect to a file, what gets written?Raw ANSI escape codes — colors and cursor-movement sequences — because rich forces the interactive renderer regardless of whether the destination is a real terminal.
saying these in an interview costs you the question
- Claiming `auto` always means rich — it falls back to plain when stdout is not a TTY.
- Thinking `plain` changes the log *level* — it only changes rendering; the same messages appear, just without ANSI.