---
title: Lint Rules Reference
description: Complete reference for Bivvy's configuration validation rules
---

# Lint Rules Reference

Bivvy includes built-in lint rules to validate your configuration.
Run `bivvy lint` to check your configuration for issues.

## Severity Levels

| Level | Description |
|-------|-------------|
| Error | Prevents execution, must be fixed |
| Warning | Should be addressed, but won't block |
| Hint | Informational suggestion |

## Output Formats

The lint command supports multiple output formats:

Human-readable (default):

```bash
bivvy lint
```

JSON output:

```bash
bivvy lint --format=json
```

SARIF output (for IDE/CI integration):

```bash
bivvy lint --format=sarif
```

## Auto-Fix

Some rules support automatic fixes:

```bash
bivvy lint --fix
```

## Strict Mode

Treat warnings as errors:

```bash
bivvy lint --strict
```

## Built-in Rules

### app-name-format

**Severity:** Warning (Error if empty)
**Auto-fix:** Yes

Validates the `app_name` field follows naming conventions.

**Checks:**
- `app_name` is not empty (Error)
- `app_name` does not contain spaces (Warning)

**Example - Invalid:**
```yaml
app_name: "My App Name"  # Warning: contains spaces
```

**Example - Valid:**
```yaml
app_name: my-app-name
```

**Suggestion:** When spaces are detected, suggests kebab-case alternative.

---

### required-fields

**Severity:** Error
**Auto-fix:** No

Ensures required configuration fields are present.

**Checks:**
- `app_name` field must be present (Error)
- At least one workflow should be defined (Warning)

**Example - Invalid:**
```yaml
# Missing app_name
steps:
  hello:
    command: echo hello
```

**Example - Valid:**
```yaml
app_name: my-app
steps:
  hello:
    command: echo hello
workflows:
  default:
    steps: [hello]
```

---

### circular-dependency

**Severity:** Error
**Auto-fix:** No

Detects circular dependencies between steps in the `depends_on` field.

**Checks:**
- No step can be part of a dependency cycle

**Example - Invalid:**
```yaml
steps:
  a:
    command: echo a
    depends_on: [b]
  b:
    command: echo b
    depends_on: [c]
  c:
    command: echo c
    depends_on: [a]  # Creates cycle: a -> b -> c -> a
```

**Example - Valid:**
```yaml
steps:
  a:
    command: echo a
    depends_on: [b]
  b:
    command: echo b
    depends_on: [c]
  c:
    command: echo c
```

**Diagnostic:** Reports the full cycle path (e.g., "a -> b -> c -> a").

---

### self-dependency

**Severity:** Error
**Auto-fix:** No

Detects steps that depend on themselves.

**Checks:**
- A step cannot list itself in `depends_on`

**Example - Invalid:**
```yaml
steps:
  build:
    command: make build
    depends_on: [build]  # Error: self-dependency
```

**Example - Valid:**
```yaml
steps:
  build:
    command: make build
    depends_on: [setup]
```

---

### undefined-dependency

**Severity:** Error
**Auto-fix:** No

Ensures all `depends_on` references point to existing steps.

**Checks:**
- Every step name in `depends_on` must exist in `steps`

**Example - Invalid:**
```yaml
steps:
  build:
    command: make build
    depends_on: [nonexistent]  # Error: step doesn't exist
```

**Example - Valid:**
```yaml
steps:
  setup:
    command: npm install
  build:
    command: npm run build
    depends_on: [setup]
```

---

### undefined-workflow-force

**Severity:** Error
**Auto-fix:** No

Ensures every step name in a workflow's `force:` list refers to a defined step.

**Checks:**
- Each entry in `workflows.<name>.force` must exist in `steps`

**Example - Invalid:**
```yaml
steps:
  build:
    command: cargo build
workflows:
  release:
    steps: [build]
    force: [nonexistent]  # Error: step doesn't exist
```

**Example - Valid:**
```yaml
steps:
  build:
    command: cargo build
workflows:
  release:
    steps: [build]
    force: [build]
```

**Diagnostic:** Reports the workflow name and the undefined step (e.g., "Workflow 'release' force list references undefined step 'nonexistent'").

---

### undefined-template

**Severity:** Error
**Auto-fix:** No

Validates that template references resolve to actual templates.

**Checks:**
- Template names in `template` field must exist in the registry

**Example - Invalid:**
```yaml
steps:
  deps:
    template: nonexistent-template  # Error: template not found
```

**Example - Valid:**
```yaml
steps:
  deps:
    template: brew  # Built-in template
    inputs:
      packages: [git, node]
```

---

### template-inputs

**Severity:** Error/Warning
**Auto-fix:** No

Validates that template inputs match their contracts.

**Checks:**
- Required inputs without defaults must be provided (Error)
- Input types must match the template contract (Error)
- Unknown inputs produce a warning (Warning)

**Example - Invalid (missing required):**
```yaml
steps:
  deps:
    template: my-template
    # Missing required input 'packages'
```

**Example - Invalid (wrong type):**
```yaml
steps:
  deps:
    template: my-template
    inputs:
      enabled: "not a boolean"  # Error: expected boolean
```

**Example - Valid:**
```yaml
steps:
  deps:
    template: my-template
    inputs:
      packages: [git, node]
      enabled: true
```

---

### check-fields-exclusive

**Severity:** Error
**Auto-fix:** No

Ensures a step does not set both `check` (singular) and `checks` (list) at the
same time. Pick one form per step.

**Checks:**
- A step with `check` set must not also have a non-empty `checks` list

**Example - Invalid:**
```yaml
steps:
  build:
    command: cargo build
    check:
      type: presence
      target: target/debug/myapp
    checks:
      - type: execution
        command: cargo build --offline
```

**Example - Valid:**
```yaml
steps:
  build:
    command: cargo build
    checks:
      - type: presence
        target: target/debug/myapp
      - type: execution
        command: cargo build --offline
```

**Diagnostic:** "Step '<name>' has both 'check' and 'checks' fields. Use only one."

---

### deprecated-fields

**Severity:** Warning
**Auto-fix:** No

Detects deprecated YAML field names and `type:` values. Because old field
names have been removed from the typed schema, serde would silently ignore
them — this rule scans the raw YAML text so renamed fields do not become
silent no-ops.

**Detected fields:**

| Deprecated | Replacement |
|------------|-------------|
| `completed_check:` | `check:` or `checks:` |
| `type: marker` | Use a specific check type, or remove the check |
| `type: file_exists` | `type: presence` |
| `type: command_succeeds` | `type: execution` |
| `watches:` | `check: { type: change, target: ... }` |
| `prompt_if_complete:` | `prompt_on_rerun:` |
| `log_path:` (in output settings) | Removed — JSONL logs are written to `~/.bivvy/logs/` automatically |

**Example - Invalid:**
```yaml
steps:
  setup:
    command: bundle install
    completed_check:        # Warning: deprecated, use 'check' or 'checks'
      type: file_exists     # Warning: use 'type: presence' instead
      path: Gemfile.lock
    prompt_if_complete: true  # Warning: use 'prompt_on_rerun' instead
```

**Example - Valid:**
```yaml
steps:
  setup:
    command: bundle install
    check:
      type: presence
      target: Gemfile.lock
    prompt_on_rerun: true
```

**Diagnostic:** Each deprecated field is reported with its file, line number, and the suggested replacement.

---

### unknown-requirement

**Severity:** Warning
**Auto-fix:** No

Requirement name in a step's `requires` list is not in the built-in registry
or the config's `requirements` map.

**Checks:**
- Every name in `requires` must be a known requirement

**Example - Invalid:**
```yaml
steps:
  build:
    command: make build
    requires: [nonexistent-tool]  # Warning: unknown requirement
```

**Example - Valid:**
```yaml
steps:
  build:
    command: make build
    requires: [ruby, node]
```

---

### circular-requirement-dep

**Severity:** Error
**Auto-fix:** No

Circular dependency chain detected in requirement install dependencies.

**Example - Invalid:**
A requirement whose install template depends on itself through a chain.

---

### unknown-environment-in-step

**Severity:** Warning
**Auto-fix:** No

A step's `environments` override block references an environment name that
is not a built-in environment and not defined in `settings.environments`.

**Example - Invalid:**
```yaml
steps:
  build:
    command: make build
    environments:
      nonexistent:  # Warning: unknown environment
        command: make build-fast
```

---

### unknown-environment-in-only

**Severity:** Warning
**Auto-fix:** No

A step's `only_environments` list includes an environment name that is not
a built-in environment and not defined in `settings.environments`.

**Example - Invalid:**
```yaml
steps:
  build:
    command: make build
    only_environments: [nonexistent]  # Warning: unknown environment
```

---

### environment-default-workflow-missing

**Severity:** Error
**Auto-fix:** No

An environment's `default_workflow` references a workflow that doesn't exist
in the config.

---

### unreachable-environment-override

**Severity:** Warning
**Auto-fix:** No

A step has an environment override for an environment that is excluded by
its own `only_environments` list. The override can never take effect.

---

### custom-environment-shadows-builtin

**Severity:** Warning
**Auto-fix:** No

A custom environment name in `settings.environments` matches a built-in
environment name (`ci`, `docker`, `codespace`, `development`).

---

### redundant-environment-override

**Severity:** Hint
**Auto-fix:** No

An environment override specifies field values identical to the base step.

---

### redundant-env-null

**Severity:** Hint
**Auto-fix:** No

An environment override sets an env var to `null` (remove), but that var
is not present in the base step's `env` map.

---

### environment-circular-dependency

**Severity:** Error
**Auto-fix:** No

Circular dependency detected in per-environment `depends_on` overrides.

---

### install-template-missing

**Severity:** Hint
**Auto-fix:** No

A requirement has no install template, so Bivvy cannot offer automatic
installation.

---

### service-requirement-without-hint

**Severity:** Warning
**Auto-fix:** No

A service requirement (e.g., `postgres-server`) lacks an `install_hint`,
making it hard for users to fix the gap manually.

---

## IDE Integration

### VS Code

Use the SARIF Viewer extension to see lint results inline:

```bash
bivvy lint --format=sarif > bivvy.sarif
```

### GitHub Actions

Upload SARIF results to GitHub Code Scanning:

```yaml
- name: Lint Bivvy config
  run: bivvy lint --format=sarif > bivvy.sarif
- uses: github/codeql-action/upload-sarif@v2
  with:
    sarif_file: bivvy.sarif
```

## JSON Output Schema

The JSON output format includes:

```json
{
  "diagnostics": [
    {
      "rule_id": "circular-dependency",
      "severity": "error",
      "message": "Circular dependency detected: a -> b -> a",
      "file": ".bivvy/config.yml",
      "line": 5,
      "column": 3,
      "suggestion": null
    }
  ],
  "summary": {
    "total": 1,
    "errors": 1,
    "warnings": 0,
    "hints": 0
  }
}
```
