Fuzzy edit tool for LLM coding agents — never fail a str_replace again
Project description
🔧 HarnessKit
Fuzzy edit tool for LLM coding agents — never fail a
str_replaceagain.
The Problem
Every LLM coding agent has the same Achilles' heel: edit application.
When Claude, GPT, or any model tries to modify code, it generates an old_text → new_text pair. The tool then does an exact string match to find where to apply the change. And it fails. A lot.
- Whitespace differences — the model adds a space, drops a tab, or normalizes indentation
- Minor hallucinations — a variable name is slightly off, a comment is paraphrased
- Format fragility — diffs, patches, and line-number schemes all break in different ways
The result? Up to 50% edit failure rates on non-native models. Every failed edit wastes a tool call, burns tokens on retries, and breaks agent flow.
The Solution
HarnessKit (hk) is a drop-in edit tool that fuzzy-matches the old text before replacing it. It uses a 4-stage matching cascade:
- Exact match — zero overhead when the model is precise
- Normalized whitespace — catches the most common failure mode
- Sequence matching —
difflib.SequenceMatcherwith configurable threshold (default 0.8) - Line-by-line fuzzy — finds the best contiguous block match for heavily drifted edits
Every edit returns a confidence score and match type, so your agent knows exactly how the edit was resolved.
Quick Start
pip install harnesskit
Or just copy hk.py into your project — it's a single file, stdlib only.
CLI Usage
# Direct arguments
hk apply --file app.py --old "def hello():\n print('hi')" --new "def hello():\n print('hello world')"
# JSON from stdin (perfect for tool_use integration)
echo '{"file": "app.py", "old_text": "def hello():", "new_text": "def greet():"}' | hk apply --stdin
# From a JSON file
hk apply --edit changes.json
# Dry run — see what would change without writing
hk apply --file app.py --old "..." --new "..." --dry-run
JSON Edit Format
{
"file": "path/to/file.py",
"old_text": "def hello():\n print('hi')",
"new_text": "def hello():\n print('hello world')"
}
Batch multiple edits:
{
"edits": [
{"file": "a.py", "old_text": "...", "new_text": "..."},
{"file": "b.py", "old_text": "...", "new_text": "..."}
]
}
Output
{
"status": "applied",
"file": "app.py",
"match_type": "fuzzy",
"confidence": 0.92,
"matched_text": "def hello():\n print( 'hi' )"
}
Exit Codes
| Code | Meaning |
|---|---|
0 |
Edit applied successfully |
1 |
No match found |
2 |
Ambiguous — multiple matches |
Integration
HarnessKit is designed to slot into any agent framework as the edit backend:
import subprocess, json
def apply_edit(file, old_text, new_text):
result = subprocess.run(
["hk", "apply", "--stdin"],
input=json.dumps({"file": file, "old_text": old_text, "new_text": new_text}),
capture_output=True, text=True
)
return json.loads(result.stdout)
Or import directly:
from hk import apply_edit
result = apply_edit("app.py", old_text, new_text, threshold=0.8)
Design Principles
- Single file, stdlib only — copy it, vendor it, pip install it. No dependency hell.
- 419 lines of Python — small enough to audit in one sitting
- Graceful degradation — exact match when possible, fuzzy only when needed
- Transparent — every result tells you how it matched and how confident it is
- Model-agnostic — works with any LLM that can produce old/new text pairs
Configuration
| Flag | Default | Description |
|---|---|---|
--threshold |
0.8 |
Minimum similarity score for fuzzy matching |
--dry-run |
false |
Preview changes without writing to disk |
Development
git clone https://github.com/alexmelges/harnesskit.git
cd harnesskit
python3 test_hk.py # 39 tests, stdlib unittest
License
MIT — see LICENSE.
Built for the agents that build everything else.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file harnesskit-0.1.0.tar.gz.
File metadata
- Download URL: harnesskit-0.1.0.tar.gz
- Upload date:
- Size: 7.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b0a012f6e1f451a463901875377a689173eb58cca25efbd07d7ec2e713bc2dc
|
|
| MD5 |
834e5777c7dea898885a47464cba903b
|
|
| BLAKE2b-256 |
0a2cd74c9a321ccfffbaf3ff23e51b0be47b9db1f737672c5325215fb448feb0
|
File details
Details for the file harnesskit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: harnesskit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
28aa49c1f02bf50750edf8c23477928351a3024701c5657e18725ee6d5a3a4a3
|
|
| MD5 |
8d5051d7173c418cf672ddc0888248c6
|
|
| BLAKE2b-256 |
b69bb04d5cf7d26caefa063b48f68825580858efd7930576a7bdb7901f032d6c
|