pino-pretty: Formatting Pino Logs in Development
🌲Basic prettifier for Pino log lines
At a glance
- What is it?
- pino-pretty converts newline-delimited Pino output into readable terminal text through a CLI, Pino transport, or JavaScript stream. It is intended mainly for development, with configurable levels, timestamps, objects, errors, colors, and filtering.
- Who is it for?
- Developers who want readable Pino output during local work should adopt pino-pretty, while teams that need stable machine-readable production logs should avoid adding it to the production path. Before adoption, verify that your application uses compatible Pino output, that each expected field is present under its configured key, and that your chosen level, timestamp, and filtering rules match the logging schema.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 19 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why pino-pretty Exists for Local Pino Output
Pino emits compact JSON records, which is effective for machines but tiring to scan in a terminal. pino-pretty is a formatter for ndjson input whose records resemble Pino log entries. The README describes it as a basic prettifier intended for development, rather than as a complete production logging platform. Its purpose is narrow: read incoming log lines, recognize fields such as the level and timestamp, and turn them into compact text.
The README gives this transformation:
{"level":30,"time":1522431328992,"msg":"hello world","pid":42,"hostname":"foo","v":1}becomes:
[17:35:28.992] INFO (42): hello worldThis makes the project appropriate for application developers inspecting Pino output on a local machine or in a development terminal. It can add color, omit selected properties, choose a custom level scheme, and change the displayed message layout. Those controls improve readability, but the core format remains line-oriented ndjson processing. pino-pretty does not replace the logger, create a logging backend, retain records, or solve storage and querying. Those concerns belong elsewhere in a logging setup.
The documentation specifically recommends against using pino-pretty in production and recommends installing it as a development dependency. That boundary should shape adoption decisions. JSON is easier for downstream systems to parse without formatter-specific interpretation, while human-oriented formatting adds interpretation and color or layout processing. Local adoption can still be valuable when engineers regularly read application events, request details, and error objects by eye.
How pino-pretty Processes ndjson Records
The formatter receives one log line at a time, identifies fields commonly emitted by Pino, and renders a human-readable representation. By default, `level` contains the numeric severity, `time` contains the timestamp, and `msg` contains the main message. `hostname` is ignored by default. Other properties can be displayed as part of the resulting record.
Field selection is configurable rather than tied permanently to those defaults. `--levelKey` and `--timestampKey` select alternate property names, including dot-delimited nested paths. `--messageKey` changes the property treated as the main message. `--ignore` and `--include` control which keys appear, but the README states that `--ignore` is ignored when both `--ignore` and `--include` are passed. This makes configuration validation or clear command construction important when combining options.
Formatting is also configurable. `--translateTime` converts the epoch value using patterns from the `dateformat` package. A `UTC:` prefix selects UTC, while `SYS:` uses the local system time zone. The default time presentation is `HH:MM:ss.l` in the local time zone. `--messageFormat` changes the arrangement of the visible line, and `--singleLine` keeps each message on one line, except that errors may remain multiline.
The programmatic API exposes the same formatter as a stream or Pino transport. That matters because the integration point determines the data flow: a CLI receives piped stdout, while a transport is configured inside the Pino logger.
Installing pino-pretty and Reading the First Log
For a terminal pipeline, the README gives a global installation command:
npm install -g pino-prettyAfter installing it, pipe an application's Pino output into the `pino-pretty` executable:
node app.js | pino-prettyThe first command places the CLI command on the system path. The second starts `app.js` and sends each emitted log line through the formatter. Instead of a raw JSON object, the terminal should show readable output such as `[17:35:28.992] INFO (42): hello world`, assuming the sample record's fields are present.
For a project-specific application, the README recommends saving it as a development dependency:
npm install --save-dev pino-prettyThat installation form is consistent with the documented boundary around production use. It keeps the formatter declared in the development environment instead of making it an ordinary runtime dependency.
The CLI can also receive options documented in the README. For example, `--colorize` adds terminal color escape sequences, while `--minimumLevel` hides records below a chosen severity. The exact output depends on the numeric level values and the data produced by `app.js`; the README does not claim a universal terminal color scheme.
Connecting pino-pretty to Pino Transport
For applications that create the logger themselves, the README recommends configuring `pino-pretty` as the Pino transport target. The logger still emits structured records, but its transport sends them through the formatter.
const pino = require('pino')
const logger = pino({
transport: {
target: 'pino-pretty'
},
})
logger.info('hi')Options can be passed through the transport's `options` object:
const pino = require('pino')
const logger = pino({
transport: {
target: 'pino-pretty',
options: {
colorize: true
}
}
})
logger.info('hi')This form is useful when the application already centralizes Pino configuration. The README also shows a callable stream:
const pino = require('pino')
const pretty = require('pino-pretty')
const logger = pino(pretty())
logger.info('hi')Here, `pretty()` returns the stream passed to Pino. An options object can be supplied directly:
const pino = require('pino')
const pretty = require('pino-pretty')
const stream = pretty({
colorize: true
})
const logger = pino(stream)
logger.info('hi')The README points users who arrived after the deprecation of Pino's `prettyPrint` option to programmatic integration. That distinction matters because transport configuration and direct stream usage are documented migration paths, not an assertion that Pino itself should always format production output.
Custom Levels, Error Fields, and Configuration Files
pino-pretty supports more than the default `trace`, `debug`, `info`, `warn`, `error`, and `fatal` labels. `--customLevels` replaces or augments the default mapping. The README gives the compact form `-x err:99,info:1`. Matching values can then be assigned through `--customColors`, for example `-X err:red,info:blue`.
That mechanism is useful when an application emits nonstandard numeric levels. It also creates a schema dependency: if the logger emits different values, the selected labels and colors will not match. `--useOnlyCustomProps` controls whether pino-pretty falls back to its defaults when custom levels or colors are absent. The README states that the option defaults to `true` and shows `-U false` when fallback is wanted.
Error presentation has two related controls. `--errorLikeObjectKeys` defines keys treated as error-like objects, with `err,error` as the default. `--errorProps` selects individual properties for display. The README warns that `--errorProps` should not be used when logging from Pino 7 and says support will be removed from future versions. That warning narrows its usefulness for new integrations and makes the default error-like key behavior the safer choice when compatible with the application schema.
A `.pino-prettyrc` file can hold options for the CLI. According to the README, pino-pretty looks for that file in `process.cwd` when `--config` is not supplied, or it can read a path passed through `--config`. This separates formatter settings from shell commands, but it also ties behavior to the directory from which the process starts.
Limits of Formatting and Filtering
The clearest limitation is documented scope. pino-pretty is described as basic and recommended for development, with an explicit warning against production use. Formatting changes the representation of records, so operators who need to parse the terminal output later would be consuming a human-oriented format rather than Pino's original JSON.
It also does not attempt to be a general query and filtering system. `--minimumLevel` accepts one threshold, which is enough to hide lower-severity messages. For more complex filtering, the README specifically points to `jq`.
Several defaults can also change the appearance unexpectedly. `hostname` is omitted unless included. `--hideObject` hides object values other than error objects. `--singleLine` does not guarantee single-line errors. Setting both `--ignore` and `--include` makes the former ineffective according to the documentation. Applications with nonstandard `level`, `time`, or `msg` fields must configure the corresponding keys or the expected formatting will not occur.
The README does not document retry behavior, backpressure policy, persistent buffering, rollback, or a compatibility matrix for every Pino major version. Those details should not be inferred from the formatter's presence in an application. They are reasons to keep the integration narrow unless the surrounding system independently establishes the required behavior.
Maintenance, License, and the Alternative Path
The repository is not archived. Its last push was on 2026-10-04, and release `v13.2.0` carries the same date in the repository metadata. The listed package version is `13.2.0`, while `package.json` declares `pino` as a development dependency at `^10.1.0`. These details provide a current release trail, but they do not establish compatibility with every Pino deployment.
The project uses the MIT license. That permits use, modification, distribution, and sublicensing under the license's conditions, including preservation of its copyright and permission notice. This is a statement about the declared license, not legal advice. The package also depends on components for formatting, parsing, streams, timestamps, colors, configuration discovery, and argument handling, so installation brings those declared dependencies into the application environment.
`jq` is the documented alternative when the requirement goes beyond pino-pretty's minimum-level filter. The approaches differ: pino-pretty understands Pino fields and produces human-readable terminal text, whereas `jq` works on JSON with explicit selection and transformation expressions. A team that only needs human formatting can use pino-pretty. A team that needs arbitrary JSON queries should start with structured output and use `jq`, rather than first converting records into display text.
Editorial conclusion
Developers who want readable Pino output during local work should adopt pino-pretty, while teams that need stable machine-readable production logs should avoid adding it to the production path. Before adoption, verify that your application uses compatible Pino output, that each expected field is present under its configured key, and that your chosen level, timestamp, and filtering rules match the logging schema.
Frequently asked questions
How do I install and use pino-pretty?
Install it with `npm install -g pino-pretty`, then pipe application output through it with `node app.js | pino-pretty`. The README recommends `npm install --save-dev pino-pretty` for programmatic use.
How do I configure pino-pretty as a Pino transport?
Set the Pino transport `target` to `pino-pretty`. Formatter options can be placed in the transport's `options` object, such as `colorize: true`.
Should pino-pretty be used in production?
The README explicitly recommends against production use and recommends installing it as a development dependency. It describes pino-pretty as a development formatter for ndjson output resembling Pino logs.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pinojs-pino-pretty)Was this useful?