How to Debug Pipeline Issues Using cliLogWriter Output in no-mistakes

The cliLogWriter function in no-mistakes captures all pipeline diagnostics to $NM_HOME/.no-mistakes/logs/cli.log, enabling you to debug failures by inspecting appended log entries with step-specific markers.

The no-mistakes CLI tool provides a robust logging mechanism through its cliLogWriter implementation, which serves as the single source of truth for pipeline execution diagnostics. Understanding how to access and interpret this log output is essential for troubleshooting complex Git-centric workflows when the terminal UI truncates messages or when processes fail silently in CI environments.

Understanding cliLogWriter and Log File Location

The logging infrastructure is initialized early in the application lifecycle to ensure no diagnostic messages are lost. According to the source code in kunchenguid/no-mistakes, the CLI entrypoint installs a structured logger that directs all output through a dedicated file writer.

How the Logger is Initialized

In cmd/no-mistakes/main.go, the application bootstrap code configures the default slog logger to use the custom writer:

// cmd/no-mistakes/main.go
slog.SetDefault(slog.New(slog.NewTextHandler(cliLogWriter(), nil)))

This setup ensures that every component—including pipeline steps, subprocess executors, and the TUI renderer—writes to the same diagnostic stream.

Safe Path Resolution and Fallback Behavior

The cliLogWriter() function (lines 93-105) implements defensive programming to prevent log-related crashes from aborting pipeline execution:

// cmd/no-mistakes/main.go – lines 93-105
func cliLogWriter() io.Writer {
    p, err := paths.New()
    if err != nil {
        return io.Discard
    }
    f, err := os.OpenFile(p.CLILog(), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644)
    if err != nil {
        return io.Discard
    }
    return f
}

Key implementation details:

  • Graceful degradation: If the paths cannot be resolved or the log file cannot be opened (for example, before running no-mistakes init), the function returns io.Discard rather than panicking
  • Atomic appends: The file is opened with O_APPEND flag, ensuring concurrent pipeline runs cannot corrupt the log with interleaved lines
  • Automatic creation: The O_CREATE flag ensures the log file and directory structure are created on first write

Locating and Reading Pipeline Logs

The paths.New() call constructs a Paths value that computes runtime file locations based on the $NM_HOME environment variable.

Default Log File Path

The CLILog() method resolves the concrete file location to:


$NM_HOME/.no-mistakes/logs/cli.log

When $NM_HOME is unset, this defaults to ~/.no-mistakes/logs/cli.log. The file is opened with write-only and append permissions (0o644), preserving a complete chronological history of all CLI invocations.

Real-time Log Inspection with tail

To debug an active pipeline failure, monitor the log file while the command executes:


# Run the pipeline

NM_HOME=$HOME/.no-mistakes no-mistakes run &

# Follow log output in real-time

tail -n +0 -f $NM_HOME/.no-mistakes/logs/cli.log

This approach captures progress information, errors, and detailed step diagnostics that may scroll past too quickly in the terminal interface.

Filtering and Debugging Pipeline Steps

Pipeline implementations in internal/pipeline/steps/*.go emit structured messages via the shared slog logger, making the CLI log file searchable by execution phase.

Step-Specific Markers

The pipeline code prefixes messages with step identifiers, allowing you to isolate specific failure points:

  • [rebase] – Git rebase operations and conflict detection
  • [push] – Remote synchronization and ref updates
  • [ci] – Continuous integration monitoring and agent coordination

Filter for specific pipeline stages using grep:


# Isolate rebase-related errors

grep '\[rebase\]' $NM_HOME/.no-mistakes/logs/cli.log

# Monitor CI agent status

grep '\[ci\]' $NM_HOME/.no-mistakes/logs/cli.log

Correlating with TUI Status

When the terminal UI (internal/tui/axi_render.go) shows a run as "parked" or "awaiting-agent", the log file contains the underlying awaiting_agent messages. This correlation helps distinguish between:

  • Stuck subprocesses (visible in internal/shellenv/shellenv.go execution logs)
  • Missing remote configurations
  • Authentication or permission failures

Why cliLogWriter is Reliable for Debugging

The cliLogWriter implementation provides three critical reliability guarantees for production debugging:

  1. Graceful fallback – If the log directory cannot be created, the writer returns io.Discard, ensuring log-related errors never abort the pipeline
  2. Atomic appends – The O_APPEND flag guarantees line-level atomicity, preventing log corruption during concurrent runs
  3. Centralized configuration – The paths package computes the location once, ensuring all components (CLI, daemon, agents) agree on the same file path

Programmatic Access Examples

For automated monitoring or custom debugging scripts, access the log file programmatically:

// Example: Read last 500 bytes of the log
logPath, _ := paths.New()
data, _ := os.ReadFile(logPath.CLILog())
fmt.Printf("Recent log entries:\n%s", string(data[len(data)-500:]))

For CI environments where you need to archive logs after failure:


# Copy logs after a failed run

cp $NM_HOME/.no-mistakes/logs/cli.log ./debug-artifacts/no-mistakes-$(date +%s).log

Summary

  • The cliLogWriter() function in cmd/no-mistakes/main.go creates an io.Writer that persists all slog output to $NM_HOME/.no-mistakes/logs/cli.log
  • Defensive design ensures the tool falls back to io.Discard if the log file is unavailable, preventing crashes during early initialization
  • Step-specific markers ([rebase], [push], [ci]) in the log file allow targeted filtering of pipeline stages
  • Atomic append operations preserve log integrity when multiple no-mistakes processes run concurrently
  • TUI correlation is possible because internal/tui/axi_render.go renders the same underlying log messages shown in the CLI log file

Frequently Asked Questions

Where does no-mistakes store its CLI log files?

The tool stores logs at $NM_HOME/.no-mistakes/logs/cli.log, defaulting to ~/.no-mistakes/logs/cli.log when the environment variable is unset. The paths.New() function in internal/paths/paths.go resolves this location consistently across all components.

Why is my no-mistakes command not writing to the log file?

If you run no-mistakes before executing no-mistakes init, the cliLogWriter() function may return io.Discard because the log directory does not exist. The tool intentionally fails silently to io.Discard rather than crashing, so ensure you have initialized the environment or manually created the .no-mistakes/logs directory structure.

How do I view logs while a pipeline is still running?

Use the tail -f command to follow the log file in real-time. Because the file is opened with O_APPEND, you can safely read it while the process writes new entries, making this ideal for debugging long-running rebase or CI monitoring operations.

What do the bracketed tags in the log file mean?

Tags like [rebase], [push], and [ci] indicate which pipeline step emitted the message. These markers are generated by the step implementations in internal/pipeline/steps/*.go and allow you to filter the log for specific workflow stages using tools like grep.

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 →