# Drip

> Delta Read Interception Proxy — sends only file diffs to your LLM agent. ~60–80% fewer tokens on file reads.

- **Type:** MCP server
- **Install:** `agentstack add mcp-drip-cli-drip`
- **Verified:** Pending review
- **Seller:** [drip-cli](https://agentstack.voostack.com/s/drip-cli)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [drip-cli](https://github.com/drip-cli)
- **Source:** https://github.com/drip-cli/drip
- **Website:** https://drip-ai.app/en/

## Install

```sh
agentstack add mcp-drip-cli-drip
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# DRIP

**Delta Read Interception Proxy — sends only file diffs to your LLM agent.**

[Website](https://drip-ai.app/) · [Install](#installation) · [Benchmarks](./BENCHMARKS.md) · [Architecture](./ARCHITECTURE.md)

[](https://github.com/drip-cli/drip/actions)
[](https://crates.io/crates/drip-cli)
[](https://github.com/drip-cli/homebrew-drip)
[](https://drip-ai.app/)
[](./LICENSE)
[](./tests)
[](./BENCHMARKS.md)

A single Rust binary that sits between your coding agent (Claude
Code, Codex, Gemini) and the filesystem. It records a baseline on
the first read, then returns just a unified diff or `[unchanged]` on
re-reads. MCP/manual first reads can be semantically compressed
for code; Claude Code's native `Read` first pass stays native full
content so Claude's read-before-edit tracker remains correct. Same
agent, same workflow, **~60–80 % fewer tokens** spent on file reads.

---

## Table of contents

- [The problem](#the-problem)
- [How it works](#how-it-works)
- [Install](#install)
- [Quick start](#quick-start)
- [Commands](#commands)
- [Configuration](#configuration)
- [Compatibility](#compatibility)
- [Privacy & security](#privacy--security)
- [Documentation](#documentation)
- [Contributing](#contributing)
- [License](#license)

---

## The problem

Your agent codes a feature on `app.py` (400 lines):

```text
read app.py     →  400 lines
edit 3 lines    →  …
read app.py     →  400 lines  ← already saw 397 of them
edit 2 lines    →  …
read app.py     →  400 lines  ← still re-reading the same content
read app.py     →  400 lines
read app.py     →  400 lines
                    ─────────
                    2,000 lines sent to the model
```

With DRIP the same five reads look like this:

```text
read app.py     →  ~40 lines (semantic-compressed first read)
read app.py     →  ~6 lines  (unified diff)
read app.py     →  ~4 lines
read app.py     →  unchanged — 0 lines
read app.py     →  ~2 lines
                    ─────────
                    ~52 lines sent to the model
```

Same agent. Same workflow. **~97 % fewer tokens** on this loop —
that example is illustrative; on a measured 8-language fixture
set the workflow means land at **34 % – 88 %** depending on the
mix of unchanged re-reads (high) vs. live edits (lower) — see
[`BENCHMARKS.md`](./BENCHMARKS.md) for the full breakdown across
**8 languages, 4 workflow styles, and verified
signature/import/type preservation** on every fixture.

---

## How it works

DRIP intercepts file-read calls before they reach the agent's tool
result and replaces them with the smallest payload that brings the
agent up to date.

```text
                ┌─────────────────────────────────┐
   Agent ────►  │  DRIP hook (Read / MCP)         │  ────► smallest payload
                └────────────┬────────────────────┘            │
                             │ SHA-256(content)                │
                             ▼                                 │
                ┌─────────────────────────────────┐             │
                │  ~/.local/share/drip/sessions.db │ ◄──────────┘
                │   (session_id, file) → baseline │
                └─────────────────────────────────┘
```

Per `(session_id, file_path)` DRIP picks one outcome:

| Outcome                              | What the agent receives                                |
|--------------------------------------|--------------------------------------------------------|
| First read                           | Full content. MCP/manual substitutions are semantically compressed when applicable; Claude `Read` first pass stays native full content |
| Same hash as last read               | `[DRIP: unchanged]` (zero-byte body)                   |
| Different hash, small diff           | Unified diff via [`similar`](https://docs.rs/similar)  |
| Diff would cost more than file       | Auto-fallback to full content                          |
| Partial read with baseline, same     | `[DRIP: unchanged (lines X-Y)]` — window-scoped 0-byte |
| Partial read with baseline, drifted  | Unified diff scoped to the requested window only       |
| Partial read on unknown file         | Native passthrough (no baseline to compare against)    |
| File deleted                         | `[DRIP: file deleted since last read]`                 |
| Read after your own edit             | `[DRIP: edit verified \| hash: …]` certificate (file hash + touched ranges, ~390 B) |
| First read past Claude's `Read` 25 k-token limit | Semantic-compressed view substituted via `deny` (signatures + `[DRIP-elided]` stubs) — the agent sees the file's shape instead of the native `exceeds maximum allowed tokens` error |
| Path matches `.dripignore`           | `` placeholder                                |

**Tokens, in practice.** Every row below is **measured**, not
estimated, on a real fixture in this repo. Re-run with
`bash scripts/bench_multilang.sh` (~30 s on Apple Silicon).

| Scenario                                                     | Without DRIP   | With DRIP        | Saved        |
|--------------------------------------------------------------|---------------:|-----------------:|-------------:|
| First read of a 731-line Python file (semantic-compressed)   |    6,774 tok   |    2,575 tok     |   **62 %**   |
| 5 reads of the same Python file — 1 first + 4 unchanged      |   33,870 tok   |    2,806 tok     |   **92 %**   |
| Edit cycle on a 744-line Java file (4 reads, 1 edit + cert)  |   28,306 tok   |    5,206 tok     |   **82 %**   |
| 7-read refactor session, 3 edit cycles (8 langs combined)    |  364,496 tok   |  188,287 tok     |   **48 %**   |

> **Bonus — DRIP reads files Claude's `Read` tool can't.** Claude
> refuses anything past ~25 000 tokens with `File content (X tokens)
> exceeds maximum allowed tokens (25000)`. DRIP detects the threshold,
> runs semantic compression even on the native-passthrough path, and
> substitutes the compressed view. **Live numbers: a 130 KB,
> 1 980-line Python module that native `Read` flat-out refuses comes
> back as 1 781 tokens of structured signatures + `[DRIP-elided]`
> stubs — a 95 % reduction *on a file the agent otherwise couldn't
> open at all*.** The agent navigates the file's shape, then uses
> partial `Read(offset, limit)` to drill into specific bodies for
> editing. Threshold tunable via `DRIP_CLAUDE_READ_TOKEN_BUDGET`.

Live numbers from your own session are always one command away:

```bash
drip meter                            # cumulative since install
drip meter --session                  # current Claude/Codex/Gemini session only
drip meter --history                  # per-command savings over time
```

**Concrete dollar impact** at typical solo-dev usage (5 sessions/day,
22 work-days/month), **linearly extrapolated** from the multi-edit
refactor workload above (read the caveat in
[`BENCHMARKS.md section 3`](./BENCHMARKS.md#3-cost-projection) — this is
*not* a prediction of your real monthly invoice, just a back-of-envelope
sense of scale on file-read traffic):
**~\$50/month on Sonnet 4.6**, **~\$249/month on Opus 4.6**,
**~\$166/month on GPT-5/Codex**. To estimate your own case, run
`drip meter --history` against a real session and override the price
with `DRIP_PRICE_PER_MTOK=N`.

> ⚠ **Caveat — prompt caching cuts the headline.** The figures above
> assume the **full per-token price** for every read. If your agent
> uses Anthropic's [prompt caching](https://docs.claude.com/en/docs/build-with-claude/prompt-caching)
> (or any provider equivalent), repeated reads of the same file hit
> the cache at **~10% of the price**. In that world, DRIP's
> unchanged/delta savings stack on top of caching for a smaller
> additional gain — order **1/3 to 1/2 of the headline $ figure** in
> the typical case. DRIP still wins on first-read compression (large
> files past the 25k Read budget that the agent couldn't open at all)
> and on cross-session orientation, but the $ projection above is the
> **no-caching upper bound**, not the cache-aware one.

Full reproducible benchmarks (per-language compression, latency,
8-language workload, signature-preservation audit) live in
[`BENCHMARKS.md`](./BENCHMARKS.md).

State lives in a single SQLite file. There is no daemon, no network
call, no telemetry. For the design rationale (why per-session, why
SQLite, why `similar`, edge cases) see
[`ARCHITECTURE.md`](./ARCHITECTURE.md).

### What DRIP also does well

1. **Reads files Claude's `Read` tool can't.** Claude's `Read` refuses
   anything past ~25 000 tokens with `File content (X tokens) exceeds
   maximum allowed tokens (25000)` — files of that size are simply
   unreadable from the agent's side. DRIP detects the threshold before
   `process_read` even runs, routes through the `DripRendered` entry
   point so semantic compression executes (skipped on the native
   passthrough path by default), and substitutes the compressed view
   via `permissionDecision: deny`. The agent sees the file's full
   structure — signatures, class declarations, imports, plus
   `[DRIP-elided]` stubs for bodies — and then drills into specific
   regions with partial `Read(offset, limit)` reads (which populate
   the harness's edit-tracker for the window). Live numbers from a
   130 KB / 1 980-line Python fixture: native errored out; DRIP
   returns **1 781 tokens of structure (95 % reduction)** on a file
   that's otherwise totally unreadable. Threshold tunable via
   `DRIP_CLAUDE_READ_TOKEN_BUDGET` (default 10 000 DRIP tokens ≈
   24-26 k Claude tokens, since Claude's tokenizer runs ~2.5× tighter
   than DRIP's `bytes/4` heuristic). When compression isn't available
   (non-code file, raw data, `DRIP_NO_COMPRESS=1`) the hook falls back
   to `allow` so the native error still points the agent at
   `offset`/`limit`.

2. **Semantic compression on first reads.** 13 languages recognised
   — Python, Rust, JS/TS, Go, Java, C, C++, C#, Kotlin, Swift, Scala,
   PHP. Function bodies are elided, signatures + imports + class
   declarations preserved (verified zero structural loss on the 8
   benchmarked fixtures). Compression ratio varies by file density:
   measured 60 % on Python, 44 % on Go, 43 % on C++, 42 % on
   TypeScript, 38 % on Java, 36 % on Rust, 36 % on Kotlin, 33 % on
   C# — see
   [`BENCHMARKS.md section 1`](./BENCHMARKS.md#1-semantic-compression-on-first-reads)
   for the full per-language table. The C-family parser handles
   both K&R (`signature {`) and Allman (`signature` + lone-`{` line)
   brace styles plus attributes / primary constructors / records.
3. **Javadoc / KDoc / JSDoc compression.** Long doc blocks (≥ 6
   lines) collapse to summary + `@param` / `@return` / `@throws`
   tags, with a `[DRIP-javadoc-elided: N lines]` marker for the
   prose / examples that were removed. Disable with
   `DRIP_COMPRESS_JAVADOC=0`.
4. **`.dripignore`** — gitignore-style. Filters reads, glob results,
   and grep results at the source. Built-in defaults for lock files,
   `node_modules`, build artefacts, binaries, fonts, video.
5. **Edit certificates.** Read a file immediately after editing it
   and DRIP returns a compact `[DRIP: edit verified | hash: …]`
   attestation (file hash + touched line ranges + symbol names
   parsed from the diff, ~390 B) instead of letting the harness
   ship the full file. Disable with `DRIP_CERT_DISABLE=1`.
6. **Session keying — crash-resistant, branch-isolated.** Session id
   derives from `(cwd, git branch, worktree)` so a relaunched agent
   on the same branch reuses its prior baselines, and a branch
   switch isolates them.
7. **Cross-session file registry.** First reads in a new session
   carry an `↔ unchanged since last session` or `↕ changed since
   last session` orientation header so the agent doesn't restart
   blind.

---

## Install

### macOS

```bash
# Homebrew (recommended) — Apple Silicon + Intel
brew install drip-cli/drip/drip

# Or via the install script
curl -fsSL https://raw.githubusercontent.com/drip-cli/drip/main/install.sh | sh
```

### Linux

```bash
# Install script (recommended) — drops the binary into ~/.local/bin.
# Pulls the static musl build, which runs unmodified on every distro
# (glibc, Alpine, NixOS) without an interpreter mismatch.
curl -fsSL https://raw.githubusercontent.com/drip-cli/drip/main/install.sh | sh

# Or via Homebrew (linuxbrew)
brew install drip-cli/drip/drip
```

If `~/.local/bin` is not on your `PATH`, the script prints the
exact line to add to your shell rc.

### Windows

```powershell
# 1. Download the latest archive from
#    https://github.com/drip-cli/drip/releases/latest
#    (file: drip-x86_64-pc-windows-msvc.zip)
# 2. Extract `drip.exe` somewhere on your PATH, e.g. C:\Users\\bin
# 3. Verify
drip --version
```

A native PowerShell installer is on the roadmap. WSL users can
follow the Linux instructions instead.

### Cross-platform (any OS with a Rust toolchain ≥ 1.74)

```bash
# From crates.io — installs the `drip` binary
cargo install drip-cli

# Or from source
git clone https://github.com/drip-cli/drip
cd drip
cargo install --path .
```

### Updating

```bash
drip update                          # auto-detects install method (brew / cargo / script)
drip update --dry-run                # show what would happen, don't run anything
```

`drip update` detects how DRIP is installed by inspecting the
binary path (`/opt/homebrew/`, `~/.cargo/bin/`, `~/.local/bin/`)
and runs the matching upgrade command. Already up-to-date is a
clean no-op.

### Uninstalling

First, remove DRIP's hooks from your agent — this preserves any
hand-edited content in `CLAUDE.md` / `AGENTS.md`:

```bash
drip uninstall                       # default: --agent claude (project-level)
drip uninstall -g                    # remove the global Claude hooks (~/.claude/)
drip uninstall --agent codex         # remove Codex CLI integration
drip uninstall --agent gemini        # remove Gemini CLI integration
```

Then remove the binary itself, depending on how you installed it:

```bash
brew uninstall drip                  # Homebrew install
brew untap drip-cli/drip             # also drop the tap if you're done with it
cargo uninstall drip-cli             # `cargo install drip-cli` install
rm ~/.local/bin/drip                 # install-script install
# Windows: delete drip.exe from wherever you put it on PATH
```

To purge cached state too (SQLite DB + on-disk file cache):

```bash
rm -rf ~/.local/share/drip                       # Linux
rm -rf "~/Library/Application Support/drip"      # macOS
# Windows (PowerShell): Remove-Item -Recurse -Force "$env:LOCALAPPDATA\drip"
```

(or set `DRIP_DATA_DIR=...` to relocate state — `drip doctor`
shows the current path).

---

## Quick start

Wire DRIP into your agent — one command, idempotent, non-destructive:

```bash
drip init                            # Claude Code, project-level   (./.claude/)
drip init -g                         # Claude Code, global          (~/.claude/)
drip init --agent codex              # Codex CLI                    (~/.codex/, always global — no project-level)
drip init --agent gemini             # Gemini CLI, project-level    (./.gemini/)
drip init -g --agent gemini          # Gemini CLI, global           (~/.gemini/)
```

That's it. The agent now goes through DRIP for every file read. You
never call `drip read` yourself.

Verify the install:

```bash
drip doctor                          # ✅ / ⚠️ / ❌ report on every component
drip meter                            # token savings since install
```

Remove cleanly:

```bash
drip uninstall                       # local
drip uninstall --global              # global
drip uninstall --agent codex         # one specific agent
```

`uninstall` only removes the bytes DRIP wrote — hand-edited config,
pre-existing hooks, and unrelated MCP servers are left intact.

---

## Commands

```bash
drip init [--agent ] [-g]      # Wire DRIP into an agent
drip uninstall [--agent ] [-g] # Remove DRIP from an agent
drip update [--dry-run]              # Upgrade DRIP via brew / ca

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [drip-cli](https://github.com/drip-cli)
- **Source:** [drip-cli/drip](https://github.com/drip-cli/drip)
- **License:** Apache-2.0
- **Homepage:** https://drip-ai.app/en/

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-drip-cli-drip
- Seller: https://agentstack.voostack.com/s/drip-cli
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
