npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@isr4el-silv4/loop-guard

v0.1.3

Published

Pi extension that detects and prevents LLM loops in tool calls and reasoning

Readme

loop-guard

loop-guard

Pi extension that detects and prevents LLM looping behavior in real-time across tool calls, thinking blocks, and streaming output.

Why

LLMs can get stuck in repetitive loops: calling the same tool with the same arguments, repeating identical reasoning, or producing stagnant output. This wastes tokens, time, and can cause agents to run indefinitely without making progress.

loop-guard watches for these patterns and escalates progressively:

  1. Hint — Inject a system prompt nudge to steer the model off its current path
  2. Block — Reject the tool call or abort streaming with a strong corrective message
  3. Terminate — Stop the agent entirely after persistent looping

Detection Modes

Tool Call Loops

Detects three patterns in tool calls:

| Pattern | Description | |---------|-------------| | Exact repeat | Same tool + identical arguments called consecutively | | Fuzzy repeat | Same tool with similar arguments (Jaccard similarity) | | Cycle | Repeating sequence of different tools (e.g. read → edit → read → edit) |

Thinking Loops (Streaming)

Detects repetitive reasoning in real-time during streaming:

| Pattern | Description | |---------|-------------| | Consecutive | N consecutive similar lines (exact match or n-gram similarity) | | Density | High repetition density in a sliding window (mode-based) |

Uses a two-stage escalation within a single prompt: warn on first detection, abort on second. This avoids false positives from legitimate repetitive output (e.g. listing items).

Thinking Loops (Post-Hoc)

At message_end, analyzes complete thinking blocks for repetitive patterns using n-gram similarity across a sliding window.

Result Stagnation

Detects when the same tool returns identical results repeatedly, indicating the agent is stuck in a non-productive cycle.

Installation

Drop this directory into your Pi extensions folder:

~/.pi/agent/extensions/loop-guard/

Pi loads it automatically on startup. You'll see loop-guard: active in the notification log.

Usage

Commands

| Command | Description | |---------|-------------| | /loop-guard reset | Clear all detection counters and allow the agent to continue | | /loop-guard config | Open interactive config menu to adjust thresholds | | /loop-guard | Same as config (opens menu) |

Configuration

Run /loop-guard config to pick a setting and edit it. Key fields:

Tool Call Detection

| Field | Default | Description | |-------|---------|-------------| | toolCallWindow | 5 | Recent tool calls to scan | | exactRepeatThreshold | 2 | Consecutive identical calls before flagging | | fuzzySimilarityThreshold | 0.85 | Jaccard similarity threshold (0.0–1.0) | | cycleLength | 2 | Tools in a repeating cycle pattern | | cycleRepetitions | 2 | Times a cycle must repeat | | cycleSimilarityThreshold | 0.7 | Argument similarity for cycle confirmation |

Thinking Loop Detection

| Field | Default | Description | |-------|---------|-------------| | thinkingWindow | 3 | Recent thinking blocks to compare (post-hoc) | | thinkingSimilarityThreshold | 0.8 | N-gram similarity threshold (post-hoc) | | thinkingMinLength | 100 | Min chars to analyze (shorter blocks skipped) |

Streaming Detection

| Field | Default | Description | |-------|---------|-------------| | consecutiveThreshold | 4 | Consecutive similar lines to trigger | | densityThreshold | 0.75 | Repetition density to trigger | | densityWindow | 100 | Sliding window size for density | | lineSimilarityThreshold | 0.85 | N-gram threshold for near-identical lines | | maxBufferSize | 10240 | Chunk buffer cap in bytes | | escalationTurns | 2 | Loop detections per prompt before abort |

Result Stagnation

| Field | Default | Description | |-------|---------|-------------| | resultStagnationThreshold | 3 | Consecutive identical results before flagging |

Escalation

| Field | Default | Description | |-------|---------|-------------| | hintAfter | 1 | Detections before system prompt hint | | blockAfter | 2 | Detections before blocking | | blockBeforeTerminate | 3 | Blocked calls before termination | | maxTurns | null | Hard turn limit (null = unlimited) |

Architecture

index.ts              Extension entry point, wires Pi events to trackers
├── tool-tracker.ts   Detects exact, fuzzy, and cycle patterns in tool calls
├── thinking-tracker.ts  Streaming + post-hoc thinking loop detection
├── result-tracker.ts   Detects identical results from the same tool
├── escalation.ts     Multi-level escalation (hint → block → terminate)
├── similarity.ts     Jaccard + n-gram similarity utilities
└── config.ts         Config schema, defaults, /loop-guard command

Event Flow

session_start  →  reset all trackers
agent_start    →  reset thinking tracker (full)
message_start  →  reset thinking tracker (per-message)
message_update →  onChunk() / onThinkingEnd() (streaming detection)
tool_call      →  toolTracker.check() → escalate if loop found
tool_result    →  resultTracker.check() → escalate if stagnant
message_end    →  thinkingTracker.check() (post-hoc detection)
turn_end       →  max turns safety net

Testing

npm test

88 tests covering all detection modes, escalation paths, similarity algorithms, and edge cases.