invariant-guard
Helps your agent think through all details before writing code. Ensures code is correct and handles edge cases.
What it does
This tool helps you write more reliable code. It makes you describe the rules (invariants), how the code will finish, and special cases before you write the actual code.
When to use it
- ✓When writing algorithms that might have subtle bugs.
- ✓When dealing with repetitions (loops) or recursive calls.
- ✓When reviewing code to ensure it works in all situations.
Example of what to ask your AI
“Write a function to find the largest element in a list, but first define the loop invariant, termination argument, and edge cases.”
Want more? Open the sections below.
How to use
The easiest way: copy the message below and paste it into Claude, ChatGPT, Cursor or any AI. It reads the skill and follows the instructions.
Skill link
Ready-to-paste message
How it works
The tool forces you to formally state the conditions that must be true before, during, and after each step of your code (like loops or recursion). This helps prevent common bugs that often go unnoticed.
Installation
Easiest way: copy the skill link and paste it into Claude, ChatGPT or Cursor asking it to follow the instructions.
In the terminal (Claude Code, Codex, Cursor), in your project folder:
npx skills add sickn33/agentic-awesome-skills --skill invariant-guardOr download just the file:
curl -L https://raw.githubusercontent.com/sickn33/agentic-awesome-skills/main/plugins/agentic-awesome-skills-claude/skills/invariant-guard/SKILL.md -o SKILL.mdTechnical content (original SKILL.md)
Original text by the author, straight from GitHub.
invariant-guard — Correctness-First Coding
The model knows what a loop invariant is. It knows recursion needs a base case. It knows about empty lists, integer overflow, and the difference between < and ≤. It just does not write these down before producing code, so it ships subtle correctness bugs that tests do not catch.
invariant-guard fixes the behavior. State the invariants. State the base case. State the termination argument. State the edge cases. Then write the code — and verify that the code maintains what you stated.
Violating the letter of these rules is violating the spirit of the skill. "I know this algorithm" is the exact rationalization that ships off-by-one and missing-postcondition bugs.
When to Use This Skill
Use invariant-guard when writing or reviewing algorithms where the obvious implementation is subtly wrong:
- Postcondition stronger than the loop's natural invariant: Boyer–Moore majority, Floyd's cycle detection, leftmost vs any binary search, QuickSelect partition.
- In-place mutation with read+write pointers: dedup-in-place, partition, rotate.
- Recursion with multiple parameters or accumulator state.
- Off-by-one suspects with duplicates, empty inputs, boundary values.
- Iterative refinements that must terminate: fixed-point, Newton, EM.
- Any function where you catch yourself thinking "I know this algorithm" — the trap is usually in the contract, not the loop body.
Pairs with lemmaly (picks the algorithm) and mathguard (picks the math). Load invariant-guard after the algorithm has been chosen and before the loop body is written.
The Iron Law
NO LOOP OR RECURSION WITHOUT A WRITTEN INVARIANT AND TERMINATION ARGUMENT
If you cannot write the invariant in one sentence, you have not designed the loop. Write code anyway and you are coding by guess — and the bug will be in the case you did not enumerate.
Non-negotiable rules
Every loop gets a one-line invariant. Before writing any loop, state in one sentence what is true at the top of every iteration. Examples:
- "At loop top:
resultcontains the sum ofa[0..i)." - "At loop top:
lo ≤ target_position ≤ hi." - "At loop top:
seencontains every element processed so far;dupscontains every element that appeared at least twice."
If you cannot write the invariant in one sentence, you have not designed the loop yet.
- "At loop top:
Every loop gets a one-line termination argument. Name the quantity that strictly decreases (or strictly increases toward a bound) on every iteration. Examples:
- "
hi − lostrictly decreases each iteration." - "
iincreases by 1 and is bounded above byn." - "
stack.lengthstrictly decreases each pop; nothing pushes inside this branch."
No termination argument, no loop.
- "
Every recursion gets an explicit base case and a measure. Before writing a recursive function, state:
- The base case(s) — the smallest inputs that return without recursing.
- The measure — a non-negative integer that strictly decreases on every recursive call (e.g.
len(xs),hi − lo,depth,n). - The combination — how the recursive results combine into the answer.
No base case + measure, no recursion. (Mutual recursion: state the measure across the cycle.)
List edge cases before writing, not after. For every function operating on a collection or number, list which of these apply and how they behave:
- Empty input (
[],"",null,undefined,None). - Singleton (
[x]). - All-equal elements.
- Already-sorted / reverse-sorted input.
- Duplicates (when uniqueness is assumed).
- Negative numbers, zero, exactly the boundary value.
- Integer overflow / underflow at the type max/min.
- NaN, ±Infinity,
-0, denormals (for floats). - Off-by-one boundaries: index 0, index n−1, index n, length 0, length 1.
- Concurrent modification while iterating.
The cases that apply must each have a one-phrase expected behavior written down.
- Empty input (
Make illegal states unreachable, not just unhandled. Prefer encoding constraints in types and structure so the wrong state cannot be constructed:
- Sum type over boolean flag soup (
Loading | Loaded(data) | Error(msg)not{loading, data, error}). - Newtype for IDs that must not be swapped (
UserIdvsOrderId). - Non-empty list type when the function requires at least one element.
- Sum type over boolean flag soup (
…
FAQ
What is a 'loop invariant'?
It's a statement that is always true at the beginning of each repetition of a loop. For example, 'the variable X always holds the sum of elements processed so far'.
What is a 'termination argument'?
It's the explanation of how a loop or a recursive function will end. It usually shows that a specific quantity is always decreasing or increasing towards a bound with each step.
Why list 'edge cases' first?
Because many bugs happen in unusual situations, like empty lists, single-item lists, or duplicate values. Thinking about these beforehand prevents errors.
Details
Original description by the author
Correctness-first: forces writing the function contract, loop invariant, termination argument, and edge cases BEFORE code. Catches Boyer-Moore, leftmost binary search, QuickSelect traps.
Popularity
- GitHub stars
- 48k
- Ranking position
- #3351
- License
- MIT
- Updated
- 10/15/2026
Comments
- …
More skills from this repository
00-andruia-consultant
Helps your agent start or improve AI projects. It analyzes code, suggests tools, and creates action plans in Spanish.
sickn33/agentic-awesome-skills
007
Lets your agent perform security audits and threat modeling. It's useful for protecting projects against attacks and vulnerabilities.
sickn33/agentic-awesome-skills
10-andruia-skill-smith
Helps your agent create or improve AI tools. It defines how tools work, writes documentation, and validates the structure.
sickn33/agentic-awesome-skills
20-andruia-niche-intelligence
Lets your agent create a summary about a specific industry. It's useful for understanding the context, rules, usage patterns, and risks of a project, using reliable sources.
sickn33/agentic-awesome-skills
Similar skills
benchmark-optimization-loop
Has your agent improve something's speed in a measured way. It tests multiple versions and chooses the fastest one that still works correctly.
affaan-m/ECC
change-impact
Helps your agent analyze the impact of code changes before making them. It compares the planned vs. actual results afterward, covering paths, data, tests, and documentation. Useful for risky or system-wide changes.
affaan-m/ECC
click-path-audit
Lets your agent trace all user buttons and interactions to find bugs. It finds issues where functions seem to work alone but fail together. Useful when bugs persist even after debugging.
affaan-m/ECC