# .no-mistakes.yaml Configuration Options vs Global Config: Complete Reference

> Understand .no-mistakes.yaml vs global config settings. Learn how to customize repository-specific rules and user-wide defaults for optimal control.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: api-reference
- Published: 2026-06-25

---

**The [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml) file controls repository-specific settings like custom commands and ignore patterns, while `~/.no-mistakes/config.yaml` stores user-wide defaults for agents, binary paths, and CI timeouts, with the two configs merged via `config.Merge()` in [`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go).**

The `no-mistakes` daemon uses a two-tier configuration system to balance flexibility with security. Understanding the difference between repository-specific [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml) files and the global `~/.no-mistakes/config.yaml` is essential for setting up automated code review pipelines securely.

## Global Configuration (`~/.no-mistakes/config.yaml`)

The global configuration is defined by the `GlobalConfig` struct in [`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go) (lines 40-53). These settings act as user-wide defaults that affect every repository unless overridden locally.

### Core Global Options

The global config stores **environment-wide defaults** that rarely change between projects:

- **agent**: Default agent selection (`auto`, `claude`, `codex`, `open_code`, `pi`, or `acp:<target>`)
- **acpx_path**: Path to the `acpx` binary when using ACP agents
- **acp_registry_overrides**: Map of per-target command overrides for custom ACP agents
- **agent_path_override**: Map overriding binary paths for native agents like `claude` or `codex`
- **agent_args_override**: Map of extra CLI arguments for native agents (validated via `validateAgentArgsOverride`)
- **ci_timeout** / **babysit_timeout**: Duration string for maximum idle time during CI monitoring. Supports keywords `unlimited`, `none`, `off`, or `never` mapped via `parseCITimeout` (lines 22-39)
- **log_level**: Logging verbosity (`debug`, `info`, `warn`, `error`)
- **auto_fix**: Per-step auto-fix attempt limits (lint, test, review, document, CI, rebase)
- **intent**: Settings for automatic user-intent extraction (enabled, threshold, slack days, disabled readers)
- **test**: Test-step evidence configuration (`store_in_repo`, `dir`)

The default template written by `EnsureDefaultGlobalConfig` lives in `defaultConfigYAML` (lines 75-124).

## Repository Configuration ([`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml))

Repository-specific settings are defined by the `RepoConfig` struct in [`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go) (lines 69-84). These options only make sense on a per-repo basis and include security-sensitive execution fields.

### Execution-Related Fields and Security

The repo config contains **code-executing fields** that require special security handling:

- **commands**: Custom command strings for `lint`, `test`, and `format` that replace built-in defaults. These are sourced from the **trusted default-branch copy** unless `allow_repo_commands` is `true` (see `EffectiveRepoConfig`, lines 78-92)
- **allow_repo_commands**: Boolean flag determining whether the daemon honors `commands` and `agent` from pushed branches. Defaults to `false` to prevent supply-chain injection
- **agent**: Overrides the global agent for this specific repository
- **ignore_patterns**: File-path globs that the pipeline should ignore (e.g., `["*.md", "docs/**"]`)

### Per-Repository Overrides

Beyond execution fields, repos can override behavior-specific settings:

- **auto_fix**: Repo-specific auto-fix limits that override global settings
- **intent**: Repo-specific intent extraction settings
- **test**: Repo-specific test evidence configuration

## How Configurations Are Merged

The `Merge()` function (lines 441-475) produces the final `Config` used by the daemon through a specific precedence algorithm.

### The Merge Algorithm

The merge process follows this priority:

1. Starts with **global** defaults for `Agent`, `ACPXPath`, `AgentPathOverride`, `AgentArgsOverride`, `CITimeout`, `LogLevel`, `AutoFix`, `Intent`, and `Test`
2. Overwrites with **repository** values where specified:
   - `Agent` (if non-empty) → repo-specific agent
   - `Commands` and `IgnorePatterns` come **only** from repo config
   - `AutoFix`, `Intent`, `Test` are deep-merged with repo overrides taking precedence

### Trusted vs. Pushed Copies

Security-critical fields (`commands`, `agent`) behave differently based on `allow_repo_commands`:

- When `false` (default): The daemon reads these fields only from the trusted default-branch SHA via `loadTrustedRepoConfig` in [`internal/daemon/manager.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/manager.go)
- When `true`: The daemon honors values from the pushed branch copy

This design is tested in [`internal/e2e/repo_config_security_test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/e2e/repo_config_security_test.go), confirming that malicious `commands` in feature branches are ignored unless explicitly allowed.

## Practical Configuration Examples

### Global Config Example

Create `~/.no-mistakes/config.yaml` with user-wide defaults:

```yaml
agent: auto
log_level: info
ci_timeout: "168h"     # 7 days; use "unlimited" for no timeout

auto_fix:
  lint: 3
  test: 3
  review: 0
intent:
  enabled: true
  threshold: 0.2
  slack_days: 3

```

### Repository Config Example

Place [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml) in your repository root:

```yaml
agent: claude
commands:
  lint: "golint ./..."
  test: "go test ./... -race"
ignore_patterns:
  - "*.md"
  - "docs/**"
allow_repo_commands: false   # keep defaults (recommended)

auto_fix:
  lint: 1          # be stricter on this repo

intent:
  enabled: false   # disable intent extraction for this repo

test:
  evidence:
    store_in_repo: true
    dir: ".no-mistakes/evidence"

```

When contributors push branches, the daemon reads the **trusted** default-branch copy. Because `allow_repo_commands` is `false`, the `commands` and `agent` values from pushed branches are ignored, protecting against malicious edits.

### Loading Configuration Programmatically

The configuration loading process follows this pattern:

```go
global, _ := config.LoadGlobal(filepath.Join(home, ".no-mistakes", "config.yaml"))
repo, _   := config.LoadRepo(repoRoot)                     // reads .no-mistakes.yaml
finalCfg := config.Merge(global, repo)                    // final Config used by the daemon

```

Relevant functions: `LoadGlobal` (lines 57-84), `LoadRepo` (lines 41-55), and `Merge` (lines 441-475).

## Summary

- **Global config** (`~/.no-mistakes/config.yaml`) stores user-wide defaults including agent binaries, timeout settings, and default auto-fix behavior via the `GlobalConfig` struct
- **Repository config** ([`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml)) provides per-repo overrides for commands, ignore patterns, and security settings via the `RepoConfig` struct
- **Security model**: The `allow_repo_commands` flag controls whether execution fields (`commands`, `agent`) are read from pushed branches or only from the trusted default-branch copy
- **Merging**: The `Merge()` function combines both configs, with repository values taking precedence for overlapping fields
- **File locations**: Global config lives in the user's home directory; repo config must be at the repository root

## Frequently Asked Questions

### What happens if I define the same option in both config files?

Repository-specific values in [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml) override global settings during the merge process. For example, if `auto_fix.lint` is set to `3` globally but `1` in the repo config, the daemon uses `1`. However, fields like `commands` and `ignore_patterns` only exist in the repository config and have no global equivalent.

### Why does the no-mistakes daemon ignore my commands in pushed branches?

By default, `allow_repo_commands` is `false` in the trusted copy of [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml). The daemon loads execution fields (`commands`, `agent`) exclusively from the default-branch SHA to prevent supply-chain attacks where malicious commands could be injected via pull requests. Set `allow_repo_commands: true` only if you explicitly trust all branches to define custom commands.

### Can I use different agents for different repositories?

Yes. While the global config sets a default `agent` (e.g., `auto`), any repository can override this in [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml) by specifying a different agent like `claude`, `codex`, or `acp:custom-target`. This override is respected as long as the repository config is properly loaded via `config.LoadRepo()`.

### How do I set an unlimited CI timeout?

In `~/.no-mistakes/config.yaml`, set `ci_timeout` or `babysit_timeout` to the string `"unlimited"`, `"none"`, `"off"`, or `"never"`. The `parseCITimeout` function maps these keywords to an unlimited sentinel value, while other values are parsed as duration strings like `"168h"` for 7 days.