# Where apigenie.yaml is found and how settings merge

Source: https://apigenie.pl/docs/concepts/where-the-configuration-is-found

One file, `apigenie.yaml`, configures the four binaries: the rules of the linter and the differ,
the layout of the formatter, the specifications of the catalog, the options of each code
generator and the settings of the server. This page explains how a command finds the file and how
a setting ends up with its value; the [Configuration](/docs/reference/cli/configuration) page of
the reference lists the settings.

## Which file is read

Without `--config`, a command looks for the first of `apigenie.yaml`, `apigenie.yml`,
`apigenie.json`, `.apigenie.yaml`, `.apigenie.yml` and `.apigenie.json` in the current directory,
then in each parent, and stops at the root of the Git repository, the directory with `.git`. One
file at the root of the repository is found from every directory of it:

```text
shop/
  .git/
  apigenie.yaml                <- read from shop/ and from shop/services/orders/
  services/
    orders/
      openapi.yaml
```

```sh
cd services/orders
apigenie lint openapi.yaml     # reads shop/apigenie.yaml
```

Two options change the lookup:

- `--config FILE` reads FILE and nothing else. The file of the repository is left alone, and the
  two are never merged.
- `--no-config` reads no file: the command runs with its defaults, as it does when no file is
  found.

`apigenie-server` has a file of its own, `apigenie-server.yaml` (or `apigenie-mock.yaml`, its
former name), looked for in the current directory before the shared file. In it the settings are
at the top level; in `apigenie.yaml` they are under `commands.mock`
([server configuration](/docs/reference/server/configuration)).

## What is checked before a setting is read

Every file is checked against the JSON Schema of the configuration before any command reads it. A
key the schema doesn't know, a value of the wrong type or one outside its allowed values stops the
command with exit status 2, the position and the JSON pointer of the value, and a suggestion for
a misspelled name:

```text
$ apigenie lint openapi.yaml
/home/me/shop/apigenie.yaml:4:12: /commands/lint/rulez: unknown property 'rulez'; did you mean 'rules'?
```

A broken file found in a parent directory stops every command run below it, not only the one
whose section is wrong. [`apigenie config check FILE`](/docs/reference/cli/config) checks a file
without running anything, and the `$schema` comment on the first line of the reference's example
lets an editor check it while you type. `version` has to be the string `'1.0'`: in YAML,
`version: 1.0` is a number, and refused.

## How settings merge

Each command reads only its own section of `commands`, and every section is optional: without
one, the command runs with its defaults, which for `lint`, `format` and `diff` is the
`recommended` ruleset. Within a section, the rules combine in this order:

1. **The rulesets of `extends`**, in the order they are listed: when two set the same rule, the
   later one wins.
2. **The `rules` of the section**, over the rulesets: a severity, `off`, or `[severity, options]`.

```yaml
version: '1.0'
commands:
  lint:
    extends: [recommended, strict]   # strict's settings win over recommended's
    rules:
      tags-unique: error             # and these win over both
      info-defined: off
```

The `asyncapi`, `swagger`, `protobuf` and `graphql` sections of `lint`, `format` and `diff`
configure the other linters, formatters and differs, each with rulesets and rules of its own: the
settings for OpenAPI documents don't apply to them, and a linter whose section is missing runs
with `recommended`.

`apigenie config` prints the settings a command ends up with, and `--origin` says where each one
comes from:

```text
$ apigenie config --for lint --origin
extends: # /home/me/shop/apigenie.yaml (repository file)
- recommended
rules:
  tags-unique: error # /home/me/shop/apigenie.yaml (repository file)
```

### The server

`apigenie-server` takes its settings from three places, and the first that sets a value wins: the
command line, then the `APIGENIE_SERVER_*` environment variables (`APIGENIE_SERVER_PORT`,
`APIGENIE_SERVER_PROXY_TO`, ...), then the file.

```text
$ APIGENIE_SERVER_PORT=5000 apigenie config --for mock --origin
server:
  host: 127.0.0.1 # default
  port: 5000 # environment APIGENIE_SERVER_PORT
```

### The generators

Each target of `apigenie-generator` has a section under `commands.generate`, named like
`client_fetch` or `server_spring`, with the settings its reference page lists. The section's
`overlay` list names the [overlays](/docs/reference/generator#overlays) applied to the document
before generating, with paths relative to the file; the `--overlay` arguments of the command line
apply after them.

### The catalog

`catalog.specs` adds to what `apigenie-catalog` finds, it doesn't replace it: a specification
the file doesn't list is still in the catalog, with a derived name, and `catalog.exclude` leaves
files out ([What the catalog counts as a specification](/docs/concepts/what-the-catalog-counts-as-a-specification)).

## See also

- [Configuration](/docs/reference/cli/configuration): every setting, by section.
- [config](/docs/reference/cli/config): prints the effective settings, checks a file, prints the
  schema.
- [lint](/docs/reference/cli/lint#configuration): `extends`, `rules`, custom rules and functions.
- [Server configuration](/docs/reference/server/configuration): every setting of
  `apigenie-server`.
