Delta Read Interception Proxy — sends only file diffs to your LLM agent.
Website · Install · Benchmarks · Architecture
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.
- The problem
- How it works
- Install
- Quick start
- Commands
- Configuration
- Compatibility
- Privacy & security
- Documentation
- Contributing
- License
Your agent codes a feature on app.py (400 lines):
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:
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 for the full breakdown across
8 languages, 4 workflow styles, and verified
signature/import/type preservation on every fixture.
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.
┌─────────────────────────────────┐
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 |
| 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 |
<ignored> 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
Readtool can't. Claude refuses anything past ~25 000 tokens withFile 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 nativeReadflat-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 partialRead(offset, limit)to drill into specific bodies for editing. Threshold tunable viaDRIP_CLAUDE_READ_TOKEN_BUDGET.
Live numbers from your own session are always one command away:
drip meter # cumulative since install
drip meter --session # current Claude/Codex/Gemini session only
drip meter --history # per-command savings over timeConcrete 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 — 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 (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.
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.
-
Reads files Claude's
Readtool can't. Claude'sReadrefuses anything past ~25 000 tokens withFile content (X tokens) exceeds maximum allowed tokens (25000)— files of that size are simply unreadable from the agent's side. DRIP detects the threshold beforeprocess_readeven runs, routes through theDripRenderedentry point so semantic compression executes (skipped on the native passthrough path by default), and substitutes the compressed view viapermissionDecision: 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 partialRead(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 viaDRIP_CLAUDE_READ_TOKEN_BUDGET(default 10 000 DRIP tokens ≈ 24-26 k Claude tokens, since Claude's tokenizer runs ~2.5× tighter than DRIP'sbytes/4heuristic). When compression isn't available (non-code file, raw data,DRIP_NO_COMPRESS=1) the hook falls back toallowso the native error still points the agent atoffset/limit. -
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 1for 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. -
Javadoc / KDoc / JSDoc compression. Long doc blocks (≥ 6 lines) collapse to summary +
@param/@return/@throwstags, with a[DRIP-javadoc-elided: N lines]marker for the prose / examples that were removed. Disable withDRIP_COMPRESS_JAVADOC=0. -
.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. -
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 withDRIP_CERT_DISABLE=1. -
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. -
Cross-session file registry. First reads in a new session carry an
↔ unchanged since last sessionor↕ changed since last sessionorientation header so the agent doesn't restart blind.
# 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# 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/dripIf ~/.local/bin is not on your PATH, the script prints the
exact line to add to your shell rc.
# 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\<you>\bin
# 3. Verify
drip --versionA native PowerShell installer is on the roadmap. WSL users can follow the Linux instructions instead.
# 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 .drip update # auto-detects install method (brew / cargo / script)
drip update --dry-run # show what would happen, don't run anythingdrip 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.
First, remove DRIP's hooks from your agent — this preserves any
hand-edited content in CLAUDE.md / AGENTS.md:
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 integrationThen remove the binary itself, depending on how you installed it:
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 PATHTo purge cached state too (SQLite DB + on-disk file cache):
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).
Wire DRIP into your agent — one command, idempotent, non-destructive:
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:
drip doctor # ✅ / ⚠️ / ❌ report on every component
drip meter # token savings since installRemove cleanly:
drip uninstall # local
drip uninstall --global # global
drip uninstall --agent codex # one specific agentuninstall only removes the bytes DRIP wrote — hand-edited config,
pre-existing hooks, and unrelated MCP servers are left intact.
drip init [--agent <name>] [-g] # Wire DRIP into an agent
drip uninstall [--agent <name>] [-g] # Remove DRIP from an agent
drip update [--dry-run] # Upgrade DRIP via brew / cargo / script
drip doctor [--json] [--quiet] # Audit the install
drip read <file> # Manual read (you'll rarely call this)
drip refresh <file> # Drop one file's baseline
drip reset # Wipe the current session (cheap, reversible)
drip reset --stats # Zero lifetime counters, keep sessions/baselines
drip reset --all [--force] # Nuke EVERYTHING (sessions + lifetime + cache blobs)
drip sessions # List sessions with strategy + savings
drip meter [--session [id]] [--json] # Token-savings report
drip meter --history | --graph # Time-series view
drip meter --prune # Drop rows for files no longer on disk
drip replay [--full] [--since 5m] # Chronological read log
drip watch [path] # Pre-compute diffs in the background
drip cache stats | gc | compact # Storage hygiene
drip registry stats | gc # Cross-session file registry
drip mcp # Run as MCP server (stdio)
drip completions <shell> # Print shell completionsDetailed flag reference: drip <command> --help.
| Command | When to reach for it |
|---|---|
drip meter |
Sanity-check that DRIP is paying off; share the % with your team |
drip replay |
Debug a "why did the agent see X?" moment — exact bytes the agent received |
drip refresh <file> |
A teammate's git pull landed; force the next read to be a clean full read |
drip reset |
Start a new task with zero memory of the previous one |
drip reset --stats |
A bench polluted lifetime counters; zero them but keep working |
drip reset --all |
Wipe every session, baseline, blob, and lifetime counter (asks yes first) |
drip doctor |
Something feels off. One paste = full triage |
drip watch |
Want changed tracked files diffed in the background before the next read |
drip cache compact |
DB size is growing — hoist large inline rows to the file cache + VACUUM |
drip meter reports estimated file-read payload savings:
DRIP Token Savings (Since Install)
══════════════════════════════════════════════════════════════════
Files tracked: 47
Total reads: 312
Files edited: 18 (62 edits)
Tokens full: 133.3K
Tokens sent: 30.5K
Tokens saved: 102.7K (77 %)
$ saved: $0.31 (@ $3.00 / Mtok)
CO₂ avoided: 41 g (@ 0.40 g / Ktok)
Efficiency meter: ████████████▒▒▒▒ 77 %
Top Files
──────────────────────────────────────────────────────────────────
1. src/app.py 34 reads 8.20K saved 94 % ▓▓▓▓▓▓▓▓▓▓
2. src/utils.py 12 reads 3.10K saved 81 % ▓▓▓▓░░░░░░
3. config.toml 8 reads 1.20K saved 100 % ▓▓░░░░░░░░
Token totals use DRIP's lightweight bytes / 4 estimator and count the
payload DRIP substitutes (file bodies, diffs, certificates, registry
diff trailers). Tiny DRIP control headers are not included, so
unchanged means "zero file payload resent", not "zero literal
tokenizer cost".
Per-environment-variable. Defaults are sensible — most users never touch these.
| Variable | Default | Effect |
|---|---|---|
DRIP_DISABLE |
unset | =1 makes every hook a no-op (emergency bypass) |
DRIP_DATA_DIR |
~/.local/share/drip |
Where the SQLite store lives |
DRIP_SESSION_ID |
derived | Pin a session id verbatim (top priority) |
DRIP_SESSION_STRATEGY |
git in repo, else pid |
Force git / pid / cwd |
DRIP_SESSION_TTL_SECS |
7200 |
Heartbeat-based session lifetime (floor 1800) |
DRIP_NO_COMPRESS |
unset | =1 disables semantic compression on first reads |
DRIP_COMPRESS_MIN_BYTES |
1024 |
Skip compression below this file size |
DRIP_COMPRESS_MIN_BODY |
15 |
Minimum function-body line count to elide (floor 4) |
DRIP_MAX_HUNKS |
6 |
Diff with more hunks falls back to a full re-read |
DRIP_MAX_CHANGED_PCT |
0.40 |
Diff changing more than this fraction falls back to full |
DRIP_INLINE_MAX_BYTES |
32768 |
Above this, content goes to cache/<hash>.bin (0 = always cache) |
DRIP_IGNORE_FILE |
unset | Explicit .dripignore path (overrides cwd / ~/) |
DRIP_WATCH_RESCAN_MS |
1000 |
Polling fallback interval for drip watch when FS events are missed |
DRIP_REJECT_SYMLINKS |
unset | =1 refuses to follow symlinks |
DRIP_WORKSPACE_ROOT |
unset | MCP read_file refuses paths outside this directory |
DRIP_REGISTRY_DISABLE |
unset | =1 opts out of cross-session orientation |
DRIP_REPLAY_LOG |
enabled | =0 disables the read_events log |
DRIP_REPLAY_KEEP |
500 |
Per-session rolling cap on replay events |
DRIP_CHECK_UPDATES |
unset | =1 makes drip doctor check the GitHub Releases API for a newer tag |
DRIP_UPDATE_FAKE_LATEST |
unset | =X.Y.Z short-circuits the update check (used by tests / live demo) |
DRIP_PRICE_PER_MTOK |
3.00 |
USD per million input tokens (default = Sonnet 4.6) |
DRIP_CO2_G_PER_KTOK |
0.40 |
Grams CO₂e per Ktok of input |
NO_COLOR |
unset | Disables ANSI color codes |
FORCE_COLOR |
unset | Forces color output even when piped |
Like .gitignore, but for things you never want fed to your agent
in full — lock files, node_modules, build artefacts, secrets.
DRIP applies it to file reads, glob results, and grep results.
Lookup order (highest priority first):
$DRIP_IGNORE_FILE— explicit path override./.dripignore— project-level rules~/.dripignore— user-level rules- Built-in defaults (always applied unless explicitly negated)
Built-in defaults cover .git/**, node_modules/**, target/**,
dist/**, __pycache__/**, all common lock files, and binary
artefacts (images, archives, fonts, video). Use !pattern to
re-include a default.
Pattern note. Agents pass absolute paths to DRIP, so anchor patterns with
**/when you want them to match anywhere (**/secrets/**). Bare basename patterns like*.lockalready work everywhere.
| Platform | Status |
|---|---|
| macOS arm64 | ✅ first-class |
| macOS x86_64 | ✅ first-class |
| Linux x86_64 | ✅ first-class |
| Linux arm64 | ✅ first-class |
| WSL (any distro) | ✅ first-class |
| Windows x86_64 |
Windows specifics: %APPDATA%\drip\sessions.db for the store,
%USERPROFILE%\.claude\settings.json for hooks, brief retry loop on
ERROR_SHARING_VIOLATION during atomic writes. Branch isolation via
the git keying strategy works the same; the pid strategy
gracefully falls through to cwd.
| Agent | Mode | Scope (default → -g) |
Auto-install |
|---|---|---|---|
| Claude Code | PreToolUse (Read, Glob, Grep) + PostToolUse |
./.claude/ → ~/.claude/ |
drip init |
| Codex CLI (OpenAI) | MCP server (read_file tool) |
always ~/.codex/ (no project-level) |
drip init --agent codex |
| Gemini CLI | MCP server (read_file tool) |
./.gemini/ → ~/.gemini/ |
drip init --agent gemini |
Codex specifics. Codex CLI reads its config exclusively from
~/.codex/config.toml— there's no project-level override path in the agent itself, sodrip init --agent codexis always global. Passing-gis a no-op for this agent (silently accepted; ignored). Same fordrip uninstall --agent codex.Codex: compaction visibility. Codex CLI does not yet expose a before-compress / on-compact hook upstream (openai/codex#16098). DRIP baselines therefore persist across Codex's context compactions — the agent will re-issue Reads and DRIP will short-circuit them with
[unchanged]against a baseline the agent's tracker has lost. Workaround: rundrip resetmanually after a Codex compaction, or wait for the upstream hook to land. Claude Code (v9+) and Gemini CLI both wire this automatically via their respective hooks.
Why no Cursor? Cursor is a VS Code-based IDE whose agent has a built-in
read_filetool that bypasses MCP. Even with DRIP's MCP server registered, the agent reaches for its native read by default — DRIP would only see the calls the model explicitly routed through it, which is not the contract the rest of the agents get. We'd rather not advertise a half-working integration.
For Claude Code, drip init writes:
- 5 hooks in
~/.claude/settings.json(or./.claude/) drip.md— the read-hint contract for the agent@drip.mdline inCLAUDE.mdso the agent loads that contract every session
For MCP-based agents, drip init registers the drip mcp server in
the agent's config (~/.codex/config.toml or
~/.gemini/settings.json) and appends a usage hint to the agent's
system-prompt file. Every write is idempotent and atomic
(tmp-file + rename(2)).
A note on Claude Code's "blocking error" wording. When DRIP intercepts a re-read, the substituted output may show up prefixed with
PreToolUse:Read hook blocking error from command: …. This is cosmetic — DRIP uses Claude Code's only currently-stable hook mechanism (permissionDecision: "deny"+permissionDecisionReason) to feed the delta back to the model. The model receives the diff as the tool result; the "blocking error" framing is the renderer, not an actual failure.
drip init auto-installs completions for the detected $SHELL
(zsh / bash / fish). PowerShell and Elvish are emitted on stdout:
drip completions zsh > ~/.zsh/completions/_drip
drip completions bash > ~/.bash_completion.d/drip.bash
drip completions fish > ~/.config/fish/completions/drip.fish
drip completions powershell # add to $PROFILE
drip completions elvish # add to ~/.config/elvish/rc.elvDRIP runs entirely on your machine. No network calls, no
telemetry, no third-party services — verified on every release
by cargo machete +
manual audit of the dependency graph. Everything tracked lives in
a single SQLite file under your platform's data dir:
| OS | Path |
|---|---|
| Linux | ~/.local/share/drip/sessions.db |
| macOS | ~/Library/Application Support/drip/sessions.db |
| Windows | %LOCALAPPDATA%\drip\sessions.db |
Override with DRIP_DATA_DIR=/your/path. drip doctor prints the
current location.
| Concern | What DRIP does |
|---|---|
| File contents at rest | Stored only in sessions.db, chmod 0600 on Unix (parent dir 0700) |
| Secrets in files | Add patterns to .dripignore — DRIP returns a placeholder, never the content |
| Symlink-redirect reads | DRIP_REJECT_SYMLINKS=1 refuses any symlinked path |
| MCP tool reaching outside a workspace | DRIP_WORKSPACE_ROOT=/path/to/repo refuses anything outside that root |
| Memory / OOM on huge files | Files > 50 MB short-circuited via metadata().len() before loading |
| Atomic config edits | drip init writes settings via tmp-file + rename(2) |
| Existing file mode preservation | atomic_write copies the target's Unix mode bits |
| Replay log secrets | Per-event content capped at 32 KB; DRIP_REPLAY_LOG=0 disables it entirely |
| Emergency bypass | DRIP_DISABLE=1 short-circuits every hook to a no-op |
To wipe state: drip reset clears the current session;
drip reset --all (with a yes confirmation, or --force for
scripts) clears every session, baseline, cache blob, and lifetime
counter — equivalent to deleting the data dir from the table above
but safer because the schema gets rebuilt on the next call.
DRIP's threat model assumes a single trusted user owns the data dir
(sessions.db is chmod 0600, parent 0700). The DRIP_SESSION_ID
environment variable is treated as authoritative — anyone who can set
it can read or pollute the baselines of any session whose id they
guess.
That's fine for a normal developer workstation. It is not safe in shared dev containers, multi-tenant Linux hosts where users share a home directory, or CI runners that re-use a writable cache between unrelated jobs. In those environments:
- give each tenant their own
DRIP_DATA_DIR, or - set
DRIP_DISABLE=1for jobs that shouldn't see another tenant's reads, or - accept the risk and treat session ids as untrusted (don't run DRIP against secrets-bearing files in such jobs).
DRIP does not authenticate session ids on purpose: every supported agent passes one in as plain text and adding HMAC/signing would break the "drop-in, zero-config" contract that makes the tool worth running.
drip replay captures the rendered output of every read so you can
reconstruct what the agent saw. For first reads of a file
(FullFirst), that rendered output is the file's full content,
which means a secret-bearing file that slips past .dripignore will
have its bytes sit in read_events.rendered until the keep-window
rolls them off (default 500 events) or you run drip reset --all.
The built-in dripignore patterns now cover the common shapes
(.env*, *.pem, id_rsa*, ~/.ssh/**, ~/.aws/credentials,
.netrc, .npmrc, kubeconfig, …); for project-specific secret
filenames (secret.toml, creds.json, …) add patterns to a project
.dripignore. To opt out of the replay capture entirely set
DRIP_REPLAY_LOG=0.
BENCHMARKS.md— measured numbers, per-language compression rates, latency budgets, cost projections.ARCHITECTURE.md— design rationale: why per-session, why SQLite, hook contract, edge-case decisions.CONTRIBUTING.md— setup, conventions, how to add support for a new agent or compression language.CHANGELOG.md— release-by-release notes.CODE_OF_CONDUCT.md— Contributor Covenant v2.1.
Issues and PRs welcome. Read CONTRIBUTING.md
first — it covers setup, commit conventions, and how to add a new
agent or compression language.
Every PR needs:
- Tests for any behavioural change (
cargo testmust pass). - Commit messages in Conventional Commits
format — CI lints them, and
release-pleaseparses them to bump the version automatically. - A signed Contributor License Agreement — the CLA-bot posts the sign-off instructions on your first PR. You only sign once.
Built by Perform Code SAS in Lille, France.
| Founder | Focus | GitHub | |
|---|---|---|---|
| 🎨 | Maxence Bombeeck | Designer & Swift | @MaxenceB59 |
| 🦀 | Hugo Barbosa | Core DRIP | @Hugobrbs |
| 🛠️ | Hugo Ponthieux | DevOps & Infra | @Hugoy8 |
Apache-2.0 © Perform Code SAS