agentleFS
VyrnexisVyrnexis/nim-agent-template/skills/nim-debugging/SKILL.md

nim-debugging

Skill4 starsChanged 3 months agoMITView on GitHub

Debug Nim compile failures, crashes, wrong results, macro expansion, ownership behavior, and unsafe-memory defects using focused reproduction, stack traces, inspection, compiler expansion, and sanitizers. Use when diagnosing runtime failures, release-only behavior, generic or macro issues, unexpected copies, pointer bugs, or memory leaks.

1 other project uses a version of this, 1 of them edited.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

15 rules. About 0 are common, 5 are distinctive, and 10 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 10

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Add --lineTrace:on to the failing release or danger command to restore the call chain and line numbers.

    line 46
  2. Very specific:

    Use --excessiveStackTrace:off when filenames are sufficient.

    line 48
  3. Very specific:

    Call writeStackTrace() when the current path matters before an exception exists.

    line 50
  4. Distinctive:

    Read the trace from the failure backward, then inspect values along that path until the first invalid state is found.

    line 52
  5. Very specific:

    Use echo for ordinary values and repr when a type lacks useful $ formatting.

    line 57
  6. Very specific:

    Use debugEcho inside {.noSideEffect.} code.

    line 59
  7. Very specific:

    Run nim c --expandMacro:<name> file.nim to inspect a macro's expanded AST.

    line 71
  8. Very specific:

    Run nim c --expandArc:<proc> file.nim to inspect injected copy, sink, move, and destroy operations.

    line 73
  9. Very specific:

    Keep an --expandArc target reachable from the entry point and use the target project's --mm: mode.

    line 75
  10. Very specific:

    Treat expansion output as evidence about generated operations, not as a reason to optimize by itself.

    line 79
  11. Very specific:

    Use ASan for ptr, addr, cstring, cstringArray, manual allocation, and C-FFI memory faults.

    line 87
  12. Distinctive:

    Read both the invalid-access stack and the allocation/free stack before editing code.

    line 108
  13. Distinctive:

    Use Valgrind as an independent native-memory check:

    line 116
  14. Distinctive:

    Follow the failing path backward and locate the first invalid state.

    line 139
  15. Distinctive:

    Add a regression test, then remove temporary prints and scratch artifacts.

    line 142

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Nim Debugging

Debug by reducing uncertainty: preserve the failure, state one hypothesis, and collect the smallest piece of evidence that can reject it. Find the first violated invariant rather than stopping at the final crash.

Rules

Preserve the failure

  • Record the exact input, command, working directory, backend, memory manager, thread setting, build mode, and relevant environment.
  • Make the failure deterministic before changing code. If it is intermittent, preserve a seed, event order, or failing fixture.
  • Change one diagnostic dimension at a time. A debug build that no longer fails is a comparison point, not a reproduction.
  • Turn each confirmed defect into a regression test before removing instrumentation.

Choose evidence by failure class

FailureFirst evidence
Compile-time type or generic questionNormal compiler diagnostic; use compiles only for a yes/no probe
Unhandled exception or defectDefault stack trace, or --lineTrace:on in the failing optimized mode
Wrong runtime valueecho, debugEcho, or repr at invariant boundaries
Buffered output lost at a crashstdout.write followed by stdout.flushFile()
Macro-generated code--expandMacro:<name>
Unexpected copy, move, or destruction--expandArc:<proc> under the project memory manager
Pointer, manual allocation, or FFI memory errorAddressSanitizer with the complete required recipe
Independent leak or invalid-access checkValgrind

Stack traces and build modes

Default build behavior:

ModeUnhandled exception tracewriteStackTrace()
default or -d:debugfull paths and line numbersfull trace
-d:releaseraising frame onlyno traceback available
-d:dangerraising frame onlyno traceback available
  • Add --lineTrace:on to the failing release or danger command to restore the call chain and line numbers. It implies --stackTrace:on.
  • Use --excessiveStackTrace:off when filenames are sufficient; the default on form includes full paths.
  • Call writeStackTrace() when the current path matters before an exception exists.
  • Read the trace from the failure backward, then inspect values along that path until the first invalid state is found.

Runtime inspection

  • Use echo for ordinary values and repr when a type lacks useful $ formatting.
  • Use debugEcho inside {.noSideEffect.} code; ordinary echo is rejected there.
  • echo flushes automatically. Flush stdout.write explicitly when a crash could occur before the buffer drains.
  • Label diagnostic values with the phase and invariant being checked. Avoid dumping large structures when one length, index, tag, or identity answers the hypothesis.
  • compiles(expr) is a compile-time boolean probe. If it returns false, compile the candidate normally to obtain the actual diagnostic.

Compiler-generated code

  • Run nim c --expandMacro:<name> file.nim to inspect a macro's expanded AST. The compiler emits an [ExpandMacro] hint.
  • Run nim c --expandArc:<proc> file.nim to inspect injected copy, sink, move, and destroy operations.
  • Keep an --expandArc target reachable from the entry point and use the target project's --mm: mode.
  • Measure copy behavior inside a named proc; last-use analysis does not fire at module top level.
  • Treat expansion output as evidence about generated operations, not as a reason to optimize by itself. move is destructive and requires deliberate last use plus behavior tests.
  • Nim defaults to ORC. Read the compiler build hint because project configuration may select ARC or atomic ARC.

AddressSanitizer

Use ASan for ptr, addr, cstring, cstringArray, manual allocation, and C-FFI memory faults. The required Linux/GCC recipe is:

nim c \
  --passC:"-fsanitize=address -fno-omit-frame-pointer" \
  --passL:"-fsanitize=address -fno-omit-frame-pointer" \
  -g \
  -d:useMalloc \
  -d:noSignalHandler \
  file.nim
  • Pass sanitizer flags to both compilation and linking.
  • -d:useMalloc is required so ASan observes memory obtained through Nim's allocator.
  • -d:noSignalHandler is required so ASan, rather than Nim's signal handler, reports signal faults.
  • -g gives symbolized Nim locations with GCC. Add --cc:clang for Clang and ensure llvm-symbolizer is in PATH.
  • Preserve the project's memory manager and failing input.
  • Read both the invalid-access stack and the allocation/free stack before editing code.

See references/memory_sanitizers.md for a complete runnable example. Platform recipes not verified in this repository are intentionally omitted.

Valgrind

Use Valgrind as an independent native-memory check:

nim c -g -o:program file.nim
valgrind --leak-check=full --error-exitcode=1 ./program

It requires no sanitizer instrumentation and is slower than ASan. A non-zero exit distinguishes detected errors in automated checks.

Debug symbols and native debuggers

  • -g and --debugger:native enable native debug information and line directives.
  • This project does not use GDB: Nim name mangling and generated C make variable inspection slower and less reliable than stack traces, focused inspection, ASan, Valgrind, and compiler expansion.

Workflow

  1. Reproduce the failure with an exact command and fixed input.
  2. Minimize unrelated setup while keeping the same failure and configuration.
  3. State one falsifiable hypothesis and the invariant it predicts.
  4. Select the narrowest evidence source from the failure-class table.
  5. Follow the failing path backward and locate the first invalid state.
  6. Fix the invariant at its owner instead of suppressing the final symptom.
  7. Re-run the original reproduction and relevant sanitizer or expansion check.
  8. Add a regression test, then remove temporary prints and scratch artifacts.

Common Mistakes

MistakeWhy it is wrong
Changing input, build mode, and code togetherThe result cannot identify which change affected the failure
Reading only the final crashing lineCorruption or invalid state commonly begins earlier
Expecting full traces from release or danger defaultsAdd --lineTrace:on to the failing optimized command
Using compiles as a replacement for compiler diagnosticsIt answers only yes or no and suppresses the candidate diagnostic
Printing with stdout.write immediately before a crash without flushingBuffered evidence can be lost
Running ASan without -d:useMallocNim allocator overflows can remain invisible to ASan
Running ASan without -d:noSignalHandlerNim can intercept signal faults before ASan reports them
Passing ASan flags only to C compilationThe sanitizer runtime must also be linked
Using Clang ASan without llvm-symbolizerReports can contain raw addresses instead of Nim locations
Adding move merely because --expandArc shows a copymove changes ownership semantics and must be safe at last use
Using GDB for routine Nim debuggingThe project uses faster Nim-aware evidence sources instead

References

  • references/stack_trace_diagnosis.md — Boundary instrumentation for finding the first bad value behind a crash.
  • references/memory_sanitizers.md — ASan and Valgrind commands for unsafe access and leaks.
  • references/arc_optimization.md — expandArc comparison for unexpected ownership copies.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.