Runtime Python bytecode patcher with guard knowledge base, persistence, and self-healing re-execution
Project description
CodeSuture
Runtime Python bytecode patcher. Catches crashes, synthesizes guards, rewrites functions in-memory, and persists fixes across runs.
What it does
CodeSuture sits between your Python program and its crashes. When an exception occurs, it intercepts the failing frame, disassembles the bytecode to identify the root cause, injects a deterministic guard directly into the function's code object, and retries execution — all without touching a single source file.
The fix persists. On subsequent runs, CodeSuture loads the patched bytecode before the first function call. The crash is gone until you choose to remove the patch.
It is a surgical tool for keeping programs running when structural failures — null access, missing keys, type mismatches, out-of-bounds reads — would otherwise bring them down.
Installation
pip install codesuture
Python 3.11+ required.
Quick start
codesuture run your_script.py
[CodeSuture] Caught AttributeError: 'NoneType' object has no attribute 'bio'
[CodeSuture] Applying null_guard on 'profile' ...
[CodeSuture] Patch applied to get_bio().
[CodeSuture] Re-executing after 1 patch(es)...
Session summary:
Patches applied: 1
Run it again:
[CodeSuture] Already healed, skipping: loaded persistent patch for get_bio
[CodeSuture] Session summary:
Patches applied: 0
How it works
- Catch — A
sys.settracecallback intercepts exceptions at the exact frame and bytecode offset where they occur. - Analyze — The pattern matcher disassembles the function's bytecode, walks the instruction chain, and identifies the failing variable or operation.
- Patch — The guard synthesizer injects new bytecode instructions into the function's code object in memory. A semantic diff gate rejects patches that would change too much of the function's logic.
- Rewind — Execution restarts from the patched function. The guard prevents the crash from recurring.
- Persist — The patched code object is serialized to
.codesuture_store/with JSON metadata. On subsequent runs it loads before execution begins.
No source files are modified at any point.
Supported guard types
| Guard type | Triggers on | Example |
|---|---|---|
null_guard |
AttributeError on None |
user.profile.bio when profile is None |
index_guard |
IndexError |
items[10] when len(items) == 2 |
key_guard |
KeyError |
cfg["timeout"] when key is missing |
subscript_guard |
TypeError subscripting None |
data["key"] when data is None |
chain_subscript_guard |
Nested subscript on None |
data["user"]["name"] |
type_coercion_guard |
TypeError on conversion |
int("not_a_number") |
division_guard |
ZeroDivisionError |
x / count when count == 0 |
str_coerce_guard |
TypeError on string concat |
"age: " + 25 |
file_guard |
FileNotFoundError |
open(path) when file is missing |
callable_guard |
TypeError calling None |
func() when func is None |
CLI reference
| Command | Flags | What it does |
|---|---|---|
codesuture run <script> |
Run script with live patching enabled | |
codesuture run <script> |
--verbose |
Show patch diffs and instruction deltas |
codesuture run <script> |
--shadow |
Warn when patched functions return sentinel values |
codesuture run <script> |
--dry-run |
Preview what would be patched without applying |
codesuture run <script> |
--ttl DAYS |
Set patch expiry in days (default: 7) |
codesuture run <script> |
--retries N |
Max re-execution attempts per crash (default: 3) |
codesuture watch <script> |
--max-restarts N |
Run continuously, restart after each patch |
codesuture audit |
Show all active patches in a formatted table | |
codesuture explain |
Human-readable breakdown of what each patch changed | |
codesuture explain <name> |
Explain one function's patch | |
codesuture rollback <name> |
Remove one persisted patch | |
codesuture rollback |
--all |
Remove all patches and the fingerprint registry |
codesuture rollback |
--dry-run |
Preview what would be removed |
Runtime Intelligence
Beyond basic patching, CodeSuture includes a set of higher-order behaviors that make it safe to use in real codebases:
Semantic diff gate — Patches that would modify too many instructions relative to the guard type are automatically rejected. The engine will never corrupt a complex function to patch a simple crash.
Caller-aware propagation — After patching a function, CodeSuture uses gc.get_referrers to find every live reference to the original code object — closures, bound methods, partials — and updates them all. No in-memory copy of the broken function survives.
Shadow execution mode — --shadow monitors the return value of patched functions. If a sentinel default ("", 0, None) leaks into downstream logic, CodeSuture logs a warning before it causes a second failure.
Patch expiry — Every persisted patch carries a configurable TTL. When a patch ages past its limit, CodeSuture logs a reminder that the underlying bug should be addressed in source code. Patches are scaffolding, not permanent fixes.
Bytecode fingerprint registry — Crash sites are hashed by their surrounding instruction window. When the same crash pattern appears again, CodeSuture applies the known guard directly without re-running analysis.
Audit trail — codesuture audit displays every active patch: function name, guard type, target variable, default value, age, and rollback instructions. codesuture explain gives a plain-language breakdown of exactly what each patch changed and whether the default value is safe for downstream consumers.
What CodeSuture is not
Not a logger. It does not record exceptions and move on. It patches the function and retries.
Not a fuzzer or static analyzer. It operates at runtime on live bytecode, not on source.
Not autonomous. Patches should be reviewed via codesuture audit and codesuture explain. The goal is to keep your program running while you address the root cause — not to replace the fix.
Limitations
Python 3.11+ only. CodeSuture depends on bytecode structures introduced in CPython 3.11. Earlier versions are not supported.
List and dict comprehensions are not patchable. Comprehensions are implemented as anonymous nested code objects in CPython. CodeSuture detects crashes inside them and logs a warning, but does not attempt to patch them. Refactor the comprehension into a named function to enable patching.
Semantic bugs are not patchable. CodeSuture fixes structural crashes — null access, missing keys, type mismatches, bounds errors. It cannot fix logic errors where the code runs but produces wrong results.
Single-process scope. Patches apply per-process. Multi-process applications need a CodeSuture instance per worker. The .codesuture_store/ directory is shared on disk, so patches load correctly on restart.
Web server support requires Python 3.11+ with threading.settrace active. Tested with socketserver and threading.Thread. ASGI frameworks (FastAPI, Starlette) require the ASGI middleware wrapper.
License
MIT. See LICENSE for details.
Project details
Release history Release notifications | RSS feed
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 codesuture-0.6.0.tar.gz.
File metadata
- Download URL: codesuture-0.6.0.tar.gz
- Upload date:
- Size: 41.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78d4baa1670c1cf973bd545b99a3455129c1150e39bede343bca9a2ddc29fe1c
|
|
| MD5 |
18c6067d6b0c231b5458effd4db44c5d
|
|
| BLAKE2b-256 |
df5d97ea9e229d1b114c705d81aba2c1232a391ffc8bce44c25f2894eeaa77e1
|
File details
Details for the file codesuture-0.6.0-py3-none-any.whl.
File metadata
- Download URL: codesuture-0.6.0-py3-none-any.whl
- Upload date:
- Size: 39.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b7f71baf6691dd598c1e83a0d87081d4ef74a735cbbe4536f0ce02b481f2598
|
|
| MD5 |
57822b1e04f72cd9661e8bb4cc033c7c
|
|
| BLAKE2b-256 |
c1681342cdcb38223934bdafbe7fdf772da05a9003a43b8f41ae09634eb9e672
|