← Back to Plugins
Tools

ClawSqueezer

cldy-com By cldy-com 👁 28 views ▲ 0 votes

๐Ÿ‹ Stale content eviction plugin for OpenClaw โ€” squeeze 86% of wasted context tokens from images, tool results, and exec outputs. Compaction fires 2-3x less often.

GitHub

Install

openclaw plugins install @cldy-com/clawsqueezer

Configuration Example

{
  "plugins": {
    "slots": {
      "contextEngine": "clawsqueezer"
    }
  }
}

README

<p align="center">
  <img src="assets/logo.png" alt="ClawSqueezer" width="200">
</p>

<h1 align="center">๐Ÿ‹ ClawSqueezer</h1>

<p align="center">
  <strong>Stale content eviction for <a href="https://github.com/openclaw/openclaw">OpenClaw</a></strong>
</p>

<p align="center">
  <a href="https://www.npmjs.com/package/@cldy-com/clawsqueezer"><img src="https://img.shields.io/npm/v/@cldy-com/clawsqueezer" alt="npm"></a>
  <a href="https://github.com/cldy-com/ClawSqueezer/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-blue" alt="license"></a>
  <a href="https://github.com/openclaw/openclaw"><img src="https://img.shields.io/badge/OpenClaw-%3E%3D2026.3.7-orange" alt="openclaw"></a>
</p>

<p align="center">
  <a href="./README.md">English</a> | <a href="./README_CN.md">ไธญๆ–‡</a>
</p>

Your messages are 3% of context. Images, tool results, and exec outputs are 86%. After the LLM has processed them, they're dead weight โ€” but they stay in context until compaction fires.

ClawSqueezer evicts stale heavy content before each LLM call. Compaction fires 2-3x less often.

## The Problem

Real OpenClaw session breakdown (analyzed from production data):

```
๐Ÿ“„ Tool results (160)    65,000 tokens   42%  โ† File reads, exec outputs, web fetches
๐Ÿ“ธ Image (1 screenshot)  48,000 tokens   30%  โ† ONE base64 image
๐Ÿ”ง Tool call args (160)  18,000 tokens   12%  โ† SSH commands, file paths, arguments
๐Ÿค– Assistant text (128)  18,000 tokens   11%  โ† LLM responses
๐Ÿ’ฌ User messages (75)     4,000 tokens    3%  โ† Your actual words
๐Ÿ”ฉ Overhead               4,000 tokens    2%  โ† Tool IDs, thinking
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
                        ~157K tokens filling a 200K context window
```

That image was seen 20 turns ago. Those file reads were processed and acted upon. But they're still sitting in context, eating tokens, until compaction triggers an expensive LLM call to summarize everything.

## The Solution

`assemble()` runs before every LLM call and evicts stale content:

```
Image (48K tokens, 5 turns old)
  โ†’ "[image was here โ€” 48,000 tokens, processed 5 turns ago]"
  โ†’ 48K tokens freed

File read (10K tokens, 8 turns old)  
  โ†’ "[tool result squeezed โ€” was 40,000 chars โ€” Preview: import { Router }...]"
  โ†’ 9.5K tokens freed

Exec output (5K tokens, 6 turns old)
  โ†’ "[exec: npm run build 2>&1]"
  โ†’ 5K tokens freed
```

Recent content is never touched. Only stale heavy blocks get squeezed.

## Requirements

- **OpenClaw >= 2026.3.7** (ContextEngine plugin slot)
- **Node.js >= 20**

Make sure your OpenClaw version meets this requirement before enabling the plugin.

## Installation

```bash
# From npm
openclaw plugins install @cldy-com/clawsqueezer

# From GitHub
openclaw plugins install https://github.com/cldy-com/ClawSqueezer

# From local path (for development)
openclaw plugins install /path/to/ClawSqueezer --link
```

Then activate it as the context engine:

```bash
openclaw config set plugins.slots.contextEngine clawsqueezer
```

Or in `openclaw.json`:

```json
{
  "plugins": {
    "slots": {
      "contextEngine": "clawsqueezer"
    }
  }
}
```

### Configuration

```json
{
  "plugins": {
    "config": {
      "clawsqueezer": {
        "staleTurns": 4,
        "minTokensToSqueeze": 200,
        "keepPreviewChars": 200,
        "imageAgeTurns": 2
      }
    }
  }
}
```

| Option | Default | Description |
|--------|---------|-------------|
| `staleTurns` | `4` | Turns before content is eligible for eviction |
| `minTokensToSqueeze` | `200` | Minimum token size to consider evicting |
| `keepPreviewChars` | `200` | Characters of preview to keep from evicted content |
| `imageAgeTurns` | `2` | Turns before images are evicted (lower = more aggressive) |

### Rollback

If anything goes wrong, rollback is instant:

```bash
# Soft โ€” back to default, plugin stays installed
openclaw config unset plugins.slots.contextEngine

# Medium โ€” plugin won't load
openclaw plugins disable clawsqueezer

# Hard โ€” completely gone
openclaw plugins uninstall clawsqueezer
```

No data loss. ClawSqueezer only modifies messages in memory during `assemble()` โ€” it never writes to session files.

## How It Works

```
Message arrives โ†’ OpenClaw processes normally
                         โ”‚
                         โ–ผ
                  assemble() fires before LLM call
                         โ”‚
                         โ–ผ
              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
              โ”‚ Scan messages for:   โ”‚
              โ”‚ โ€ข Images > N turns   โ”‚
              โ”‚ โ€ข Tool results > N   โ”‚
              โ”‚ โ€ข Exec outputs > N   โ”‚
              โ”‚ โ€ข Large tool args    โ”‚
              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                         โ”‚
              Replace with tiny placeholders
                         โ”‚
                         โ–ผ
              LLM sees lean context โ†’ more room for work
              Compaction fires less often โ†’ saves money
```

### What Gets Squeezed

| Content Type | Typical Size | After Squeeze | When |
|-------------|-------------|--------------|------|
| Base64 image | 48,000 tokens | ~20 tokens | After 2 turns |
| Tool result (file read, exec output) | 2,000โ€“10,000 tokens | ~50 tokens | After 4 turns |
| Tool result (web fetch) | 1,000โ€“5,000 tokens | ~30 tokens | After 4 turns |
| Tool call arguments | 200โ€“2,000 tokens | ~20 tokens | After 4 turns |

### What's Never Touched

- Recent messages (within `staleTurns`)
- User text messages (always small)
- Assistant text responses (the actual conversation)
- Thinking blocks
- Small tool results (below `minTokensToSqueeze`)
- Tool call structure (type, id, name preserved for API pairing)

### Production Results

First production deployment:

```
Before ClawSqueezer:   Context fills to 180K โ†’ compaction fires
After ClawSqueezer:    73 blocks evicted, ~96K tokens freed per call
                       Image: 11K freed | Tool results: 85K freed
```

## Standalone Usage

```typescript
import { squeeze } from "@cldy-com/clawsqueezer";

const { messages: squeezed, stats } = squeeze(messages, {
  staleTurns: 4,
  imageAgeTurns: 2,
});

console.log(`Freed ${stats.tokensFreed} tokens`);
console.log(`Evicted: ${stats.imagesEvicted} images, ${stats.toolResultsEvicted} tool results`);
```

## Why Not Just Compress The Summary?

We tried that first. It works (55% smaller summaries), but the real waste isn't in the summary โ€” it's in the 86% of context that's stale images and tool outputs. Compressing the summary saves 3K tokens. Evicting one old screenshot saves 48K.

## License

Apache-2.0 โ€” Built by [CLDY](https://cldy.com)
tools

Comments

Sign in to leave a comment

Loading comments...