How to Configure no-mistakes for a Specific Repository: A Complete Guide

Configure no-mistakes for a specific repository by creating a .no-mistakes.yaml file in the repository root, which defines pipeline steps, trusted commands, and gate policies that the daemon merges with global defaults before execution.

The kunchenguid/no-mistakes tool relies on a per-repository configuration file to customize its continuous integration pipeline and security gates. To configure no-mistakes for a specific repository, you must create a .no-mistakes.yaml file at the repository root, which controls everything from test commands to auto-fix policies while maintaining strict security boundaries between trusted and untrusted configuration sources.

Where Configuration Lives

The configuration system spans three layers: global defaults hardcoded in the binary, repository-specific overrides in your local file, and trusted configuration fetched from the default branch.

The Repository Configuration File

Every repository protected by no-mistakes requires a .no-mistakes.yaml file in the Git root. This file is read by both the CLI when starting a run (internal/cli/daemon_cmd.go) and by the daemon process (internal/daemon/manager.go). The file uses YAML format and supports two distinct security zones: trusted keys (executable commands) and untrusted keys (informational settings).

Global Defaults

The internal/config/config.go file defines the DefaultConfig struct, which provides fallback values for all repositories. These defaults include settings like ci_timeout and auto_fix policies, stored in config.autoFixDefaults. When you configure no-mistakes for a specific repository, your .no-mistakes.yaml values override these globals.

Trusted vs Untrusted Configuration

Understanding the security model is critical when you configure no-mistakes for a specific repository. The system splits configuration into two trust zones to prevent malicious pull requests from executing arbitrary code.

Trusted fields—including commands.{test,lint,format}, agent, commands.post_push, and document.instructions—are read only from the default branch at a pinned SHA. The daemon implements this protection in loadTrustedRepoConfig and validates it via assertGateTrustedConfigReadable.

Untrusted fields—such as ignore_patterns, auto_fix settings, and intent—can be set by any branch and are read from the current checkout. This split ensures that only repository maintainers can define executable commands, while contributors can adjust informational settings.

Creating Your Repository Configuration

To initialize no-mistakes in a new repository, run no-mistakes init, which invokes the wizard in internal/wizard/wizard.go to generate a starter .no-mistakes.yaml file.

Minimal Configuration Example

A functional .no-mistakes.yaml file separates trusted executable commands from untrusted behavioral settings:


# .no-mistakes.yaml – repository-specific configuration

# Trusted-only keys (read from default branch)

commands:
  test: go test ./...
  lint: golint ./...
  format: gofmt -w .
document:
  instructions: |
    # Documentation policy

    * One owner per fact
    * Stale docs become pointers
    * No AGENTS.md post-mortems

# Untrusted (can be set by branch)

auto_fix:
  review: 1          # enable auto-fix for review findings

  lint: 0            # keep lint findings manual

steps:
  test:
    enabled: true
  lint:
    enabled: true
  document:
    enabled: true

The commands and document.instructions keys are trusted-only and must exist in the default branch to take effect. The steps and auto_fix maps can be adjusted per branch.

Common Customization Scenarios

When you configure no-mistakes for a specific repository, you typically need to customize pipeline steps, command hooks, or auto-fix behavior. The following patterns cover the most common use cases:

Goal Configuration snippet Explanation
Use a different test command commands.test: "gotestsum --format testname" Trusted field—must exist in default branch to be accepted.
Skip lint on PRs steps.lint.enabled: false Disables the lint gate entirely.
Enable auto-fix for review findings auto_fix.review: 1 Untrusted field—can be set per branch.
Add a custom post-push hook commands.post_push: "./scripts/check.sh" Trusted hook that runs after a successful push.
Restrict repository-wide commands allow_repo_commands: false Must be set in the trusted default branch; prevents contributors from enabling arbitrary commands.

Each gate in the pipeline follows the model described in docs/concepts/gate-model.md, and you can enable or disable individual gates via steps.<name>.enabled.

Configuration Loading and Validation

The no-mistakes daemon follows a strict merge process when loading configuration to maintain security guarantees.

  1. Local Load: config.LoadRepoConfig reads .no-mistakes.yaml from the current checkout to obtain untrusted fields and local preferences.
  2. Trusted Fetch: loadTrustedRepoConfig in internal/daemon/manager.go fetches the same file from the remote default branch at a fresh SHA, extracting only trusted fields like commands.* and allow_repo_commands.
  3. Merge: The executor (internal/pipeline/executor.go) combines the trusted configuration with the local configuration, with trusted values taking precedence.
  4. Validation: If loadTrustedRepoConfig fails to fetch or parse the trusted configuration, the run aborts immediately (TestLoadTrustedRepoConfig_FailClosedOnFetchFailure), following a fail-closed security policy.

This process ensures that when you configure no-mistakes for a specific repository, the system never executes commands defined in unmerged feature branches.

Summary

  • Create a .no-mistakes.yaml file in the repository root to configure no-mistakes for a specific repository.
  • Place executable commands under the commands key and documentation policies under document.instructions—these are trusted-only and must be committed to the default branch.
  • Adjust behavioral settings like auto_fix and steps in any branch, as these are untrusted and informational only.
  • Use no-mistakes init to generate a starter configuration via the wizard in internal/wizard/wizard.go.
  • The daemon validates configuration in internal/daemon/manager.go before execution, ensuring trusted fields originate from the default branch.

Frequently Asked Questions

What is the difference between trusted and untrusted configuration keys?

Trusted keys include any configuration that results in code execution, such as commands.test, commands.lint, and agent. These are read exclusively from the default branch to prevent malicious PRs from injecting arbitrary shell commands. Untrusted keys, like auto_fix.review or steps.lint.enabled, control informational or behavioral settings and can be modified in any branch. This separation is enforced by the loadTrustedRepoConfig function in internal/daemon/manager.go.

Can I use environment variables in my .no-mistakes.yaml file?

The configuration parser in internal/config/config.go processes the YAML file directly. While the source code does not explicitly mention environment variable expansion in the default configuration struct, you should verify the specific implementation in your version. For dynamic values, use the commands hooks to export variables before running tests or linting.

How do I disable specific pipeline steps for my repository?

Set steps.<name>.enabled: false in your .no-mistakes.yaml file. For example, to disable the lint gate, add steps.lint.enabled: false. This is an untrusted field, meaning you can toggle it per branch without requiring default branch approval. The executor in internal/pipeline/executor.go consults this setting when scheduling pipeline steps.

What happens if the trusted configuration fails to load?

The daemon implements a fail-closed policy. If loadTrustedRepoConfig cannot fetch the .no-mistakes.yaml from the default branch, or if the file contains malformed trusted keys, the run aborts immediately with a clear error. This behavior is tested in TestLoadTrustedRepoConfig_FailClosedOnFetchFailure and ensures that the system never runs with incomplete or potentially compromised security settings.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →