> ## Documentation Index
> Fetch the complete documentation index at: https://bakefile.wisl.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Logging and Console Output

> console is your task's output and always prints. Logs are diagnostics gated by verbosity, from -v to -vvv, with per-module levels and a JSON format.

bakefile has two output channels, and they don't affect each other:

* **`console`** is your task's user-facing output (results, status). It always prints, regardless of verbosity.
* **Logs** are bakefile's own diagnostics, plus any `logging` calls you make in tasks. These are gated by verbosity.

## Console output

`console` (imported from `bake`) is a thin wrapper over [Rich](https://rich.readthedocs.io/). Print task output through it rather than `print`:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from bake import Bakebook, command, console


class MyBakebook(Bakebook):
    @command()
    def status(self) -> None:
        console.echo("Building...")  # plain output, stdout
        console.success("Build done")  # ✅ SUCCESS   (stderr)
        console.warning("Low disk")  # ⚠️ WARNING   (stderr)
        console.error("Build failed")  # ❌ ERROR     (stderr)
```

Helpers:

* `console.echo(msg)` prints to stdout (your task's normal output).
* `console.success`, `info`, `warning`, `error(msg)` print a labeled line to stderr. In GitHub Actions, `warning` and `error` become `::warning::` / `::error::` annotations.
* `console.prefix(msg, label=..., emoji_code=..., label_style=...)` prints a custom labeled line when the built-in labels don't fit. `label` is required - use `info` for the default `INFO` label.
* `console.cmd(cmd_str)` prints a command as `❯ <cmd>`, which is what `ctx.run` uses to show the command it runs. The arrow accepts `arrow_style=` (default green, e.g. `arrow_style="bold red"` for failed commands). The command text always stays plain.
* `console.script_block(title, script)` pretty-prints a multi-line script, used by `run_script`.

Every helper accepts rich print kwargs (`style`, `emoji`, `markup`, `highlight`, ...) and they apply to the message only - the label chrome is rendered as a `Text` object and is never affected. Chrome styling has its own param names (`label_style` on `prefix`, `arrow_style` on `cmd`) so rich kwargs are never shadowed. So `console.success("tests[unit] passed", markup=False)` keeps the green label but prints the message literally. Note that with markup on (the default), rich parses the message: `[unit]`-style tags are consumed.

Stream model: `echo` is for machine-readable data (stdout, safe to pipe). Everything else is human progress output (stderr). Any helper also accepts `no_color=True` to emit zero ANSI codes - use it when the output is parsed by another tool:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
console.echo(value, no_color=True)  # clean stdout, no ANSI codes
```

For anything else, the raw Rich consoles are also exposed: `console.out` / `console.err` (stdout / stderr, color) and `console.plain_out` / `console.plain_err` (no color).

`console` output, plain `print()`, and command output are all separate from logs. They always print, regardless of verbosity.

## Logging

bakefile logs through [loguru](https://github.com/Delgan/loguru), and all logs go to stderr. Standard-library `logging` is bridged into it, so any `logging.getLogger(__name__).info(...)` in your tasks honors the same settings:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import logging

logger = logging.getLogger(__name__)


@bakebook.command()
def task(self):
    logger.info("starting")  # visible at -vv and above
```

Three settings control logs. The first two decide what shows, and the third picks the format.

### Verbosity

Verbosity sets the global floor. Anything below it is dropped. The default is `0` (silent).

| Flag   | Env                    | Level            |
| ------ | ---------------------- | ---------------- |
| (none) | `BAKE_LOG_VERBOSITY=0` | silent (no logs) |
| `-v`   | `BAKE_LOG_VERBOSITY=1` | warning          |
| `-vv`  | `BAKE_LOG_VERBOSITY=2` | info             |
| `-vvv` | `BAKE_LOG_VERBOSITY=3` | debug            |

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
bake build              # silent
bake -v build           # warning + error
bake -vv build          # adds info
bake -vvv build         # adds debug (everything)
```

### Per-module levels

`--bake-log` (env `BAKE_LOG`) is a comma-separated list of `level` or `module=level` entries. It raises or lowers specific modules independent of verbosity. The default is `warning,bake=debug,bakelib=debug,bakefile=debug` (the tool's internals and your `bakefile.py` at debug, everything else at warning):

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Set one level for everything (the root level, always required)
bake --bake-log debug build                        # all modules at debug
bake --bake-log warning build                      # all modules at warning

# Raise one module above the root
bake --bake-log warning,bake=debug build           # bake internals at debug, rest warning

# Target your own bakefile.py (it loads as module "bakefile")
bake --bake-log warning,bakefile=debug build       # your bakefile.py at debug

# Env var form: quiet bakefile.py, keep bake internals (restate them)
BAKE_LOG="warning,bake=debug,bakelib=debug,bakefile=warning" bake build
```

`--bake-log` replaces the default instead of merging with it, so restate any module you want to keep. In the last line, `bake` and `bakelib` stay at debug while `bakefile.py` is silenced to warning.

A log line shows only if it clears **both** the verbosity floor and its module's level. So with the default `BAKE_LOG`, `-v` surfaces bakefile's warnings and errors, and `-vvv` surfaces its debug logs too.

### Format

`--log-pretty` / `--no-log-pretty` (env `BAKE_LOG_PRETTY`, default pretty) chooses between pretty colored text and JSON (one object per line, for CI and log shipping):

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
bake --no-log-pretty build     # JSON logs
```

### Advanced

For advanced needs, override `setup_logging()` (e.g. a custom JSON sink like `GCPJsonSink` for GCP Cloud Logging) or `get_bake_log_thread_local_context()` (inject trace IDs into each log line) on your Bakebook.
