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

# Configuration

> The config file, its sections, and how shared presets lock what they set.

smartcloud reads `.github/smartcloud.yml` (`.github/smartcloud.yaml` also works). The file is YAML; JSON is valid YAML, so a JSON file works too.

```yaml .github/smartcloud.yml theme={null}
# yaml-language-server: $schema=https://raw.githubusercontent.com/Resnovas/smartcloud/main/schema/smartcloud.schema.json
version: 2
extends:
  - Resnovas/.github/smartcloud/house.yml@main

roles:
  maintainers: [octocat, hubot]
  trustedBots: ["dependabot[bot]", "renovate[bot]"]

links:
  policyBase: https://github.com/my-org/.github/blob/main
```

`version: 2` is required. A file without it is treated as a v1 config and migrated on the fly, with a warning for everything the migration drops; see [Migrating from v1](/migration).

The [configuration reference](/reference/configuration) lists every key.

### Unknown keys and invalid values

A run never fails because a key is unknown or a value is invalid, in your config or in any preset it extends. smartcloud drops it, warns, and runs with the rest, so a preset written for a newer smartcloud, such as one with a `settings` section this version does not know yet, keeps working with an older action. Each warning names the file and the key, for example:

```text theme={null}
Resnovas/.github/smartcloud/house.yml@main: ignored settings.codespaces, because settings.codespaces is unexpected, expected: "merging" | "features" | …
```

What is dropped:

* An unknown key, or a value of the wrong type or outside its allowed values, is dropped on its own; the rest of its section still applies.
* A problem anywhere in a rule's `when` drops the whole `when`, so a rule never runs with some of its conditions missing. A rule that cannot work without its `when`, such as a labelling rule or an automatic approval, is then dropped too; a convention that also names a `preset` keeps the preset. A problem inside any other list drops the whole list, never one item.
* A section or rule still incomplete once every file is merged, such as `sync` without `source`, a label without `color`, or a convention with neither `preset` nor `when`, is dropped. A repository can still complete a rule its preset starts, or restate one to add a field, as [Add, never change](#add-never-change) describes.

Dropping a setting that only tightens policy would loosen it. For example, a `roles.maintainers` list with one bad entry would leave fewer than two maintainers, and that opens the review gate. So an invalid value dropped from one of these settings is an error in the `smartcloud / config` check, not a warning. Every feature still runs, but the check fails and blocks merging until the config is fixed:

* `roles.maintainers`
* `reviews.gate`
* `commits`
* `disclosure.requireDraft`
* `settings.security`
* `settings.ruleset`
* `settings.actions`
* `settings.collaborators`
* `settings.teams`
* `sync.check`

This applies to an invalid value at, inside or around one of these, such as a whole `sync` section dropped for lacking its `source`. An unknown key there is still only a warning, because this version would not have applied it anyway.

A value a preset sets that this version cannot read is dropped from the preset but stays locked: your config cannot set that key either, and a value it sets there is ignored with a warning. A preset that asks for a stricter setting than this version knows can never be turned into a weaker one.

Some problems still fail the run, because they are not about one key: a file that is not YAML or JSON, is not a mapping, or has a malformed `extends` entry; a preset that cannot be read (outside a [restricted run](/reporting#restricted-runs)); presets that extend each other in a loop or more than five deep; and a config that changes a value its preset set, which [Add, never change](#add-never-change) describes.

The warnings appear in a `smartcloud / config` check run and the job summary; see [Reporting](/reporting#config-warnings). To catch mistakes before they reach a run, check the config with [`smartcloud validate`](/cli#validate) or the MCP server's `validate_config`, which are strict and report every unknown key and invalid value as an error, or let your editor check it against the JSON Schema named in the first line of the example above, which is strict too.

## Sections

| Section                                          | Feature                              |
| ------------------------------------------------ | ------------------------------------ |
| `labels`, `labelSync`, `labelling`, `sizeLabels` | [Labels](/features/labels)           |
| `conventions`                                    | [Conventions](/features/conventions) |
| `commits`                                        | [Commits](/features/commits)         |
| `disclosure`                                     | [Disclosure](/features/disclosure)   |
| `reviews`                                        | [Reviews](/features/reviews)         |
| `required`                                       | [Required](/features/required)       |
| `stale`                                          | [Stale](/features/stale)             |
| `settings`                                       | [Settings](/features/settings)       |
| `sync`                                           | [Sync](/features/sync)               |
| `roles`, `links`                                 | Shared by several features, below.   |

Every rule is a keyed map, never a list. Keys are how presets and repositories merge, and how an error names the rule it is about.

### Roles

`roles.maintainers` and `roles.trustedBots` are lists of GitHub logins. Logins compare ignoring case, and a leading `@` is optional.

* Trusted bots skip the commits and disclosure checks and the review gate.
* On a maintainer's own pull request, the commits and disclosure features report errors at their `maintainerLevel` (`warning` by default). The repository owner counts as a maintainer for this.
* The review gate and the ruleset's required checks only apply once two or more maintainers are listed.

### Links

`links.policyBase` is the base URL of your governance documents. Findings link to pages under it, for example `AI_POLICY.md#ai-02`, `CONTRIBUTING.md#dco` and `GOVERNANCE.md#review`. The default is `https://github.com/Resnovas/.github/blob/main`.

## Presets and `extends`

`extends` lists preset files to build on, each written as `owner/repo/path@ref`. The ref (a branch, tag or commit) is optional; without it the repository's default branch is read.

```yaml theme={null}
extends:
  - Resnovas/.github/smartcloud/house.yml@main
  - my-org/.github/smartcloud/typescript.yml@v1.2.0
```

A preset is an ordinary config file with `version: 2`, and may extend presets of its own. Presets are merged first, in the order listed, each preset's own presets before it, and the repository's config last. Presets extending each other in a loop are an error, as is nesting more than five deep.

### Add, never change

Everything a preset sets is locked. A repository may add to what it inherits, but never change or remove it:

* **Adding is allowed.** A new label, a new rule, or a new field on an inherited rule that the preset left unset.
* **Identical restatements are allowed.** Repeating an inherited value exactly as it already is changes nothing, so a repository can keep a full copy of a rule without error.
* **Changing is an error.** Any other value for something already set, whether a scalar, a list or a different shape, fails the whole run.

Lists are values, not collections to append to: if a preset sets `roles.maintainers`, a repository cannot add a name to it.

Given this preset:

```yaml Resnovas/.github/smartcloud/house.yml theme={null}
version: 2
labels:
  bug:
    name: bug
    color: D73A4A
```

This repository config is valid: it restates `bug` identically, adds a description the preset left unset, and adds a new label.

```yaml .github/smartcloud.yml theme={null}
version: 2
extends:
  - Resnovas/.github/smartcloud/house.yml@main
labels:
  bug:
    name: bug
    color: D73A4A
    description: Something is not working
  docs:
    name: documentation
    color: 0075CA
```

Changing the colour instead fails with an error naming the path and the preset that set it:

```text theme={null}
.github/smartcloud.yml cannot change "labels.bug.color": it is set by Resnovas/.github/smartcloud/house.yml@main. Add a new rule instead.
```

The same rule applies between presets: a later preset cannot change what an earlier one set.

`version`, `extends` and `$schema` describe a file rather than rules, so they are never merged.

### Reading presets

The action reads presets through the GitHub API with its own token, so a preset in a private repository needs a token that can read that repository. A [restricted run](/reporting#restricted-runs), such as a pull request from a fork, leaves out a preset from another repository that its token cannot read, and warns that the preset's rules were not checked, rather than failing. The CLI resolves a token only when a config extends something; see [CLI](/cli#tokens).
