Bounded AI code edits via Codestral fill-in-the-middle: rewrite only the region between two anchors, the rest stays byte-identical.
Project description
vibe-fim
Bounded AI code edits via Codestral fill-in-the-middle. Rewrite only the region between two anchors — the rest of the file comes out byte-for-byte identical, by construction.
Why this exists
Most coding agents edit by regenerating a block and pasting it back. The model re-emits your whole function (or file) token by token, so it can silently change things you never asked it to touch — reflow a comment, drop a trailing newline, "fix" an unrelated line, normalise quotes.
Fill-in-the-middle (FIM) makes that structurally impossible. You hand the model a verbatim prefix and suffix; it only writes the middle. So the edit is provably confined to the region between two anchors. Everything outside is never sent to be rewritten — it cannot drift.
vibe-fim wraps Mistral's Codestral FIM in a one-call surgical-patch
primitive and verifies the guarantee on every edit: the output must start with
the exact prefix and end with the exact suffix, or the patch is rejected.
This is the one thing competing agent CLIs can't express: none of Claude Code, Codex, or vanilla
vibehas a FIM patch primitive. Codestral does.vibe-fimturns it into a bounded edit you can trust.
Install
pip install vibe-fim
export MISTRAL_API_KEY=... # from https://console.mistral.ai
Zero runtime dependencies (stdlib urllib only).
CLI
# Rewrite only what's between the two anchors; show the diff without writing.
vibe-fim patch --file units.py \
--before "def to_celsius(f):" \
--after $'\n\ndef to_fahrenheit' \
--hint "round the result to 1 decimal place" \
--dry-run
The scope report goes to stderr:
[BOUNDED] edit confined between anchors.
frozen prefix: 142 chars (unchanged)
frozen suffix: 98 chars (unchanged)
region: 31 chars -> 39 chars
Drop --dry-run to write the file in place.
Library
from vibe_fim import patch_region
result = patch_region(
source_code,
before="def to_celsius(f):", # frozen prefix ends right after this
after="\n\ndef to_fahrenheit", # frozen suffix starts right at this
hint="round the result to 1 decimal place",
)
assert result.bounded # verified, not assumed
assert source_code.startswith(result.prefix) # prefix is byte-identical
new_source = result.text
The completion backend is injectable, so the bounded-edit logic is fully testable with no network:
patch_region(src, before, after, fim_fn=lambda prefix, suffix: " return 42")
Anchors must be unique in the file. A missing or ambiguous anchor raises
FimError instead of guessing — surgical edits should never be applied to the
wrong place.
The guarantee, benchmarked
examples/bench.py runs the same edit ("round to_celsius to 1 decimal") two
ways and counts changed lines outside the target function:
| approach | collateral changes outside target | guaranteed? |
|---|---|---|
surgical FIM (vibe-fim) |
0 | yes — by construction |
| block regeneration (chat returns the file) | drifts (e.g. dropped the file's trailing newline in our run) | no |
The block-regen baseline produced the correct body — and still silently altered the file outside the edit. FIM can't, because the prefix and suffix are never regenerated.
MISTRAL_API_KEY=... python examples/bench.py
How it works
- Locate the unique
beforeandafteranchors. prefix = text[:end_of_before],suffix = text[start_of_after:].- Send
(prefix, suffix)to Codestral FIM →middle. new_text = prefix + middle + suffix.- Verify
new_text.startswith(prefix) and new_text.endswith(suffix)— else raise. The bytes outside the region are identical because they're the same object slices, concatenated unchanged.
License
MIT © Guillaume Vele
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 vibe_fim-0.1.0.tar.gz.
File metadata
- Download URL: vibe_fim-0.1.0.tar.gz
- Upload date:
- Size: 9.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8cf94c02a1e246803a22a7f415964ead0a103b28ffda15352be476657255802e
|
|
| MD5 |
c5d2492fc4f590b22665f9a917a1671a
|
|
| BLAKE2b-256 |
77a92f52d8c6c278cb0abad323bc8afd98e3d6c342c96aeacb0ab865c26048e3
|
File details
Details for the file vibe_fim-0.1.0-py3-none-any.whl.
File metadata
- Download URL: vibe_fim-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9889b299547516aa9dd57b6d8a289e954799068e4b641b270a905fcb6b514284
|
|
| MD5 |
f5b468a8877493067ff6cd58573fc3e1
|
|
| BLAKE2b-256 |
7a0ff68b9b37802dda16732d25c4639e33ae9f651a29f18c59ade28c8a53ac2b
|