How do you make Gradle produce clean, CI-friendly build logs without ANSI control characters or a redrawing progress bar?
answer
- --console=plain for clean CI logs
- org.gradle.console=plain in gradle.properties
- CI may allocate a PTY → auto wrongly picks rich
- --no-color strips color only, not progress bar
- verify with cat -v / no ^[[ sequences
basics
~10 sForce plain mode — pass --console=plain on the command line or set org.gradle.console=plain in gradle.properties. That disables colors, cursor movement and the animated progress bar, leaving an append-only text log.
solid answer
~40 sOn CI you want output that is **append-only and free of ANSI escape codes**, so logs are greppable and don't contain garbage like `^[[2K`. Two ways: 1. **Per-invocation:** `./gradlew build --console=plain`. 2. **Persistent:** add `org.gradle.console=plain` to the project's `gradle.properties` (or `~/.gradle/gradle.properties` on the agent). In practice `--console=auto` (the default) usually already detects that CI stdout is not an interactive TTY and falls back to plain automatically — but **some CI systems allocate a pseudo-TTY** (e.g. to capture colors), which makes auto pick rich and pollute logs. Explicitly forcing `plain` removes that ambiguity. Many teams also pass `--no-color` separately if they only want to strip color but keep the progress bar, though `plain` is the usual all-in-one switch. Forcing plain in `gradle.properties` keeps every pipeline consistent regardless of agent terminal emulation.
code
toml · 3 lines# gradle.properties
# Force flat, append-only output on every machine and CI agent
org.gradle.console=plain
go deeper
Know to pass --console=plain for clean CI output.
Explain why auto can misfire on PTY-allocating agents and the --no-color vs plain distinction; set it via gradle.properties.
Recommend a committed gradle.properties policy and verifying logs are escape-free; understand color suppression vs progress-bar suppression.
Standardize console policy across the org's CI templates and agent gradle.properties so build logs are uniformly clean and aggregator-safe.
## The CI logging problem Gradle's default `--console=auto` tries to detect a terminal. On a developer laptop that gives colors and a live progress bar; on CI, *if* the agent has no TTY, it falls back to `plain` and you get clean logs for free. The trouble is that the detection is not always right: - Some CI runners (e.g. certain GitLab/GitHub/Jenkins configurations) **allocate a pseudo-terminal (PTY)** so tools that want colors can produce them. Gradle then sees a TTY and chooses `rich`, redrawing the progress bar with cursor-movement escapes. When that stream is captured to a plain log file, you get unreadable control-character noise. - Conversely, you may *want* colors preserved in a CI that renders ANSI in its web UI — in which case you'd force `rich`, not fight it. ## The fix: force the mode explicitly Don't rely on detection — declare intent: ``` # gradle.properties (project root or ~/.gradle/) org.gradle.console=plain ``` or per build: ``` ./gradlew build --console=plain ``` `plain` guarantees: no ANSI color, no bold, no progress bar, no in-place line rewriting. Each log line is emitted exactly once, in order — perfect for `grep`, diffing two builds, or feeding a log aggregator. ## --no-color vs --console=plain `--no-color` strips **color codes only**. The animated progress/work-in-progress area can still be drawn (it uses cursor-movement codes, not color). `--console=plain` disables **both** color and the progress bar. For truly flat CI logs, prefer `plain`. Note that in newer Gradle versions color suppression is folded into the console mode, so `plain` is the recommended single switch. ## Where to set it - **Command line** for a one-off override; it beats any property. - **Project `gradle.properties`** so the whole team and all pipelines share the setting (committed to VCS). - **`~/.gradle/gradle.properties` on the agent** for machine-wide CI policy without touching the repo. ## Verifying A quick sanity check is to pipe to `cat -v` (or open the captured log) and confirm there are no `^[[` sequences. If you still see them, something is forcing `rich` — check for `org.gradle.console=rich`, a `--console=rich` flag, or `GRADLE_OPTS`.
- Default is auto, which should already detect non-TTY on CI. Why force plain anyway?Because some CI agents allocate a pseudo-TTY, so auto detects a terminal and picks rich, writing ANSI escape codes into the captured log. Forcing plain removes that dependency on the agent's terminal emulation.
- Difference between `--no-color` and `--console=plain`?`--no-color` removes color codes but can still draw the redrawing progress bar; `--console=plain` removes color and the progress bar, giving fully append-only output.
- Where would you set this so all pipelines are consistent?In the committed project `gradle.properties` (org.gradle.console=plain), or `~/.gradle/gradle.properties` on the CI agent for a machine-wide policy.
saying these in an interview costs you the question
- Saying you must always pass the flag because auto can't handle CI — auto often works; the issue is PTY-allocating agents.
- Claiming `--no-color` fully cleans logs — it leaves the progress bar's cursor-movement codes.