# How to Configure Custom Lint, Test, and Format Commands in RepoConfig

> Customize lint test and format commands in RepoConfig by defining shell commands in the no-mistakes yaml file. Override default auto-detection and streamline your workflow.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: how-to-guide
- Published: 2026-07-03

---

**You can configure custom lint, test, and format commands in no-mistakes by defining shell commands in the `commands` section of [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml), which overrides the agent's default auto-detection behavior.**

The `no-mistakes` repository automation tool allows you to configure custom lint test format commands in RepoConfig to override default pipeline behaviors. When defined in [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml), these commands execute via the platform shell instead of relying on the agent's auto-detection logic. This configuration resides in the `Commands` struct defined in [`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go) (lines 86-91), giving you precise control over code quality checks.

## Understanding the Commands Structure

The configuration schema centers on the `Commands` struct in [[`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go)](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go#L86-L91). This structure exposes three optional string fields:

- `commands.lint` – Shell command for the lint step
- `commands.test` – Shell command for the test step  
- `commands.format` – Shell command for the format step

When populated, the pipeline executes your command via `sh -c` on POSIX systems or `cmd.exe /c` on Windows. The step monitors the exit code: zero indicates success, while any non-zero exit aborts the step and reports a failure. If left empty, the step falls back to the agent-driven auto-detect logic.

## Configuring Commands in .no-mistakes.yaml

Place your configuration at the repository root in [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml). The `commands` map accepts shell commands for each pipeline stage.

### Basic Configuration

```yaml

# .no-mistakes.yaml

agent: auto

commands:
  lint:   "golangci-lint run ./..."
  test:   "go test -race ./..."
  format: "gofmt -w ."

ignore_patterns:
  - "*.generated.go"
  - "vendor/**"

```

In this example:
- **Lint**: Runs `golangci-lint`; non-zero exit codes fail the lint step immediately
- **Test**: Runs `go test -race`; success allows the agent to continue with additional evidence collection  
- **Format**: Runs `gofmt -w .` after lint fixes and before the push step commits changes

### Enabling Per-Branch Commands

By default, `commands.*` fields are read only from the trusted default-branch copy. To enable commands from any branch (for personal repositories only), set `allow_repo_commands: true`:

```yaml
allow_repo_commands: true

commands:
  lint:   "npm run lint"
  test:   "npm test"
  format: "prettier --write ."

```

### Environment Variables

Since commands execute through the shell, you can embed environment variables directly:

```yaml
commands:
  test: "COVERAGE=1 go test -cover ./..."

```

## Security and Default Branch Protection

Because `commands.*` fields execute arbitrary code, `no-mistakes` implements strict security controls documented in [[`docs/src/content/docs/reference/repo-config.md`](https://github.com/kunchenguid/no-mistakes/blob/main/docs/src/content/docs/reference/repo-config.md)](https://github.com/kunchenguid/no-mistakes/blob/main/docs/src/content/docs/reference/repo-config.md#L88-L98). The daemon reads these fields **only from the default branch** copy (e.g., `origin/main`) unless you explicitly set `allow_repo_commands: true` in the default branch configuration.

This prevents supply-chain attacks where malicious contributors inject harmful commands via feature branches. Even if a pull request modifies [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml) with dangerous commands, the daemon ignores those changes until they merge into the default branch.

## Step Execution Flow

### Lint Step

The lint step implementation in [[`internal/pipeline/steps/lint.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/lint.go)](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/lint.go) executes `sctx.Config.Commands.Lint` when configured. The command runs before any auto-fixes, and failure aborts the entire lint step.

### Test Step  

According to [[`internal/pipeline/steps/test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/test.go)](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/test.go), the pipeline executes `sctx.Config.Commands.Test` first. If the custom test command succeeds, the agent may still run additional evidence collection checks.

### Format Step

The format command executes in the push step logic after lint fixes have been committed. As documented in the reference guide, this runs `sctx.Config.Commands.Format` right before committing auto-fixed changes; failure aborts the push operation.

All three commands are scoped to their respective steps and terminate together with any child processes when the step finishes or is cancelled.

## Summary

- Define custom commands in [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml) under the `commands` key with `lint`, `test`, and `format` subkeys
- Commands execute via shell (`sh -c` or `cmd.exe /c`) with exit code zero indicating success  
- Security defaults require commands to be defined in the default branch; set `allow_repo_commands: true` to enable per-branch configuration
- The `Commands` struct in [`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go) (lines 86-91) defines the configuration schema
- Step implementations in [`internal/pipeline/steps/lint.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/lint.go), [`test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/test.go), and the push step handle command execution

## Frequently Asked Questions

### How do I enable custom commands for feature branches?

Set `allow_repo_commands: true` in your [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml) file on the default branch. This tells the daemon to honor commands from whatever branch the user pushes. Only enable this for personal repositories where you trust every branch, as it allows arbitrary code execution from any branch.

### What happens if a custom command returns a non-zero exit code?

The step immediately aborts and reports a failure. For lint and test steps, this stops the pipeline. For the format step, a non-zero exit prevents the push from completing. The agent treats any non-zero exit status as a failure condition regardless of the actual command output.

### Can I use environment variables in custom commands?

Yes. Because commands execute through the platform shell, you can embed environment variables directly in the command string. For example: `test: "COVERAGE=1 go test -cover ./..."`. The step evaluates the exit status after the shell processes the environment variable assignments.

### Where does the format command execute in the pipeline?

The format command runs after lint fixes have been committed but before the push step finalizes changes. According to the reference documentation in [`docs/src/content/docs/reference/repo-config.md`](https://github.com/kunchenguid/no-mistakes/blob/main/docs/src/content/docs/reference/repo-config.md), this occurs in the push step logic where `sctx.Config.Commands.Format` executes, allowing formatting tools to modify files before the final commit.