---
title: "evlog CLI"
description: "Use the evlog CLI to check logging patterns in supported source files, diagnose your setup, and control telemetry. Includes flags and exit codes."
canonical_url: "https://www.evlog.dev/cli/overview"
---
# evlog CLI

> Use the evlog CLI to check logging patterns in supported source files, diagnose your setup, and control telemetry. Includes flags and exit codes.

The `evlog` executable ships with the `evlog` package. It runs separately from your application: use it locally or in CI to inspect your source, configure evlog, and work with telemetry.

Start with [`evlog map`](https://www.evlog.dev/cli/map) to check supported entry points for evlog logging patterns and get a static observability score with suggested fixes. It writes `evlog.map.json` unless you pass `--no-write`. The score describes recognized source patterns, not the logs your handlers produce in production.

[`evlog init`](https://www.evlog.dev/cli/init) adds evlog configuration to the app. [`evlog logs`](https://www.evlog.dev/cli/logs) reads the events the fs drain wrote: the latest requests, the failures, the slowest, or one request in full. [`evlog agents`](https://www.evlog.dev/cli/agents) writes logging conventions for the AI agents working in the repository. [`evlog.config.ts`](https://www.evlog.dev/cli/config) holds the settings `evlog map` and `evlog logs` apply, next to the sampling and redaction the app imports.

<warning icon="i-lucide-flask-conical">

**Early days.** `evlog map` has adapters for Nuxt, Nitro, Next.js App Router, TanStack Start, Hono, Express, and Fastify. Each adapter recognizes specific entry-point shapes. Check the detected framework and entry-point count before interpreting the score. Rules can change between releases, so [pin the version](https://www.evlog.dev/cli/ci#pin-the-version) when you gate CI on the number.

</warning>

<code-group>

```bash [pnpm]
pnpm evlog map
```

```bash [bun]
bunx evlog map
```

```bash [npm]
npx evlog map
```

</code-group>

The executable runs [`@evlog/cli`](https://npmjs.com/package/@evlog/cli) when it is installed and otherwise fetches it with the package manager that launched it, so `evlog` adds no dependency to your project and `npx evlog init` works on a project that has nothing yet. A global `@evlog/cli` hands off to the copy the project installs, so a project always runs the version it pins. Install the CLI for a pinned, instant run, which is what CI wants:

<code-group>

```bash [pnpm]
pnpm add -D @evlog/cli
```

```bash [bun]
bun add -d @evlog/cli
```

```bash [npm]
npm install --save-dev @evlog/cli
```

</code-group>

<callout color="neutral" icon="i-lucide-info">

The CLI requires Node 22 or later.

</callout>

## Commands

<card-group>
<card color="neutral" icon="i-lucide-wand-sparkles" title="init" to="https://www.evlog.dev/cli/init">

Install evlog, register the framework integration, and write a local drain.

</card>

<card color="neutral" icon="i-lucide-bot" title="agents" to="https://www.evlog.dev/cli/agents">

Write the evlog conventions into AGENTS.md and install the agent skills.

</card>

<card color="neutral" icon="i-lucide-radar" title="map" to="https://www.evlog.dev/cli/map">

Score wide-event coverage across every entry point, and name the ones to fix first.

</card>

<card color="neutral" icon="i-lucide-stethoscope" title="doctor" to="https://www.evlog.dev/cli/doctor">

Check that evlog is installed, resolvable, and writing logs where you expect.

</card>

<card color="neutral" icon="i-lucide-settings-2" title="config" to="https://www.evlog.dev/cli/config">

Show the evlog.config that applies here and where each setting comes from.

</card>

<card color="neutral" icon="i-lucide-bar-chart-3" title="telemetry" to="https://www.evlog.dev/cli/telemetry">

Show, enable, or disable the CLI's own anonymous usage telemetry.

</card>
</card-group>

## Global flags

Every command accepts these:

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      What it does
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --json
      </code>
    </td>
    
    <td>
      Machine-readable JSON on stdout instead of the report
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --debug
      </code>
    </td>
    
    <td>
      Print a debug summary of the run, and emit it as a wide event
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --noHeader
      </code>
    </td>
    
    <td>
      Skip the branded header
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --cwd <dir>
      </code>
    </td>
    
    <td>
      Run against another directory instead of the current one
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --help
      </code>
    </td>
    
    <td>
      Usage for the command
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --version
      </code>
    </td>
    
    <td>
      Print the CLI version and exit
    </td>
  </tr>
</tbody>
</table>

## Human output goes to stderr

The report you read is written to **stderr**. Stdout is reserved for `--json`, so a run can be piped into `jq` without the report getting in the way:

```bash [Terminal]
evlog map --json | jq '.map.score'
```

Without `--json`, nothing is written to stdout at all. Colour is dropped when stdout is not a TTY or when `NO_COLOR` is set, and the report lays itself out for the width it is given, so set `COLUMNS` to render at a fixed width.

## Exit codes

<table>
<thead>
  <tr>
    <th>
      Code
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      The command ran and nothing failed
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      A check failed, or <code>
        --min-score
      </code>
      
       was not met
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        2
      </code>
    </td>
    
    <td>
      Usage error — an unknown flag or an invalid value
    </td>
  </tr>
</tbody>
</table>

<warning>

A pipe replaces `$?` with the exit code of the *last* command in it, so `evlog map --min-score 90 \| head` always looks successful. Use `set -o pipefail` when you pipe a gated run.

</warning>

## When a check is wrong

Every verdict can be turned off from the code it is about, so a false positive never becomes a reason to stop running the tool:

```ts [server/api/health.get.ts]
// evlog-map-disable-next-line wide-event, context -- liveness probe, deliberately silent
export default defineEventHandler(() => ({ ok: true }))
```

The check becomes `n/a` with your reason attached, at no score cost and with no failed gate, and the report counts how many checks the project disabled, so the number stays honest. [Full syntax](https://www.evlog.dev/cli/rules#disabling-a-check).

## Monorepos

`init`, `map` and `doctor` all resolve the nearest `package.json` above the working directory, then treat that package as the project. In a pnpm or npm workspace, running from `apps/web` scans `apps/web`, not the repo root.

`evlog map` scans one app at a time. Running it from a bare workspace root, where there is no framework to detect, is an error rather than an empty report:

```bash [Terminal]
cd apps/web && evlog map
# or
evlog map --cwd apps/web
```

## Debugging a run

`--debug` prints what the command did: the steps it went through, the directory it resolved, and any findings, and emits the same information as an evlog wide event:

```bash [Terminal]
evlog map --debug
```

```text [Output]
── debug ────────────────────────────────
command  map
env      development
cwd      /Users/you/apps/web
steps    resolveProject → detectFramework → resolveEvlog → scan → writeMapFile → done
──────────────────────────────────────────
full event → --json --debug  (stderr)
```

Add `--json` to get the whole event instead of the summary. `EVLOG_CLI_DEBUG=1` does the same as the flag, which is useful in a CI job you cannot easily edit.

## Next

- [`evlog init`](https://www.evlog.dev/cli/init): wire evlog into an app that does not have it yet
- [`evlog map`](https://www.evlog.dev/cli/map): what it scans and how to read the report
- [Rules](https://www.evlog.dev/cli/rules): every check, what satisfies it, and how to fix it
- [Scoring](https://www.evlog.dev/cli/scoring): how the number is calculated
- [CI](https://www.evlog.dev/cli/ci): gate a pull request on the score

---

- [evlog map](https://www.evlog.dev/cli/map)
- [Rules](https://www.evlog.dev/cli/rules)


## Sitemap

See the full [sitemap](https://www.evlog.dev/sitemap.md) for all pages.
