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

# verify.yml

> Configure how Otto verifies the code it writes before opening a pull request.

When Otto implements a ticket, it verifies the code (lint, build, and test commands) before opening a pull request. Customize this with a `.otto/verify.yml` file in your repository.

<Note>
  `verify.yml` applies to code Otto writes during [ticket
  automation](/automation/lifecycle). It doesn't affect pull request reviews;
  those are configured with [`otto.yml`](/configuration/otto-yml).
</Note>

## Quick start

Most repositories don't need a `verify.yml`. Otto detects your project type and runs the usual commands. Add one only to change the defaults:

```yaml .otto/verify.yml theme={null}
max_retries: 3
runtime:
  node: '20'
verify:
  - pnpm run lint
  - pnpm run build
```

## Reference

| Field | Type | Default | Description |
| - | - | - | - |
| `enabled` | boolean | `true` | `false` skips verification entirely |
| `max_retries` | number | `2` | How many times the fix agent retries on failure (0–5) |
| `runtime` | map | *(auto-detected)* | Runtime versions to install, for example `node: "20"` |
| `install` | string\[] | *(auto-detected)* | Dependency install commands |
| `verify` | string\[] | *(auto-detected)* | Verification commands (lint, build, test, …) |
| `timeout.install_seconds` | number | `300` | Timeout per install command, in seconds |
| `timeout.verify_seconds` | number | `180` | Timeout per verify command, in seconds |

## Full example

```yaml .otto/verify.yml theme={null}
# Number of times the fix agent retries on failure (0–5)
max_retries: 3

# Runtime versions (installed with mise)
runtime:
  node: '20'
  python: '3.12'

# Run in order; stops at the first failure
install:
  - pnpm install --frozen-lockfile
  - pip install -e .

# Run in order; every result is collected
verify:
  - pnpm run lint
  - pnpm run build
  - pnpm run test
  - pytest

timeout:
  install_seconds: 600
  verify_seconds: 300
```

## Auto-detection

When `install` and `verify` are omitted, Otto detects your project type:

| Project type | Detected by | Install command | Verify commands |
| - | - | - | - |
| Node.js (pnpm) | `pnpm-lock.yaml` | `pnpm install --frozen-lockfile` | `pnpm run lint`, `pnpm run build`, `pnpm run test` |
| Node.js (yarn) | `yarn.lock` | `yarn install --frozen-lockfile` | `yarn run lint`, `yarn run build`, `yarn run test` |
| Node.js (npm) | `package-lock.json` | `npm ci` | `npm run lint`, `npm run build`, `npm run test` |
| .NET | `*.csproj` or `*.sln` | `dotnet restore` | `dotnet build --no-restore`, `dotnet test --no-build` |
| Go | `go.mod` | `go mod download` | `go vet ./...`, `go build ./...` |
| Python | `pyproject.toml` | `pip install -e .` | `ruff check .`, `pytest` |
| Rust | `Cargo.toml` | *(none)* | `cargo check`, `cargo clippy` |
| Makefile | `Makefile` | *(none)* | `make lint`, `make build`, `make test` |

For Node.js, only scripts that exist in `package.json` are run. For Makefiles, only targets that exist are run.

### Runtime versions

When `runtime` is omitted, Otto detects versions:

* **Node.js**, checked in order: `.node-version`, `.nvmrc`, the `nodejs` entry in `.tool-versions`, then the major version in `package.json` `engines.node`.
* **.NET**: `sdk.version` in `global.json`.
* **Go, Python, Rust**: `latest`.

Runtimes are installed with [mise](https://mise.jdx.dev/), so any tool mise supports works in `runtime`, for example `java: "21"` or `ruby: "3.3"`.

## Partial configuration

Set only what you need; Otto auto-detects the rest:

<CodeGroup>
  ```yaml Override retries theme={null}
  max_retries: 4
  ```

  ```yaml Pin a runtime theme={null}
  runtime:
    node: '22'
  ```

  ```yaml Longer timeout theme={null}
  timeout:
    verify_seconds: 600
  ```
</CodeGroup>

## How verification works

<Steps>
  <Step title="Install runtimes">
    Each version in `runtime` is installed with mise.
  </Step>

  <Step title="Install dependencies">
    `install` commands run in order and stop at the first failure.
  </Step>

  <Step title="Verify">
    `verify` commands run in order. Every result is collected; a failure doesn't
    stop the rest.
  </Step>

  <Step title="Fix and retry">
    If any command fails, a fix agent gets the errors, corrects the code, and
    verification runs again, up to `max_retries` times.
  </Step>

  <Step title="Report">
    The results are included in the pull request description.
  </Step>
</Steps>

## Best practices

* **Start with auto-detection.** Add a `verify.yml` only when the defaults don't fit.
* **Keep verify commands fast.** Run lint, build, and unit tests; leave slow integration suites to CI.
* **Use `enabled: false` sparingly.** Otto's code won't be checked before the PR opens.
* **Raise timeouts for large monorepos** and `max_retries` for strict lint or build setups.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.