Automated code patching system for Rust with byte-span replacement and tree-sitter integration
codex-patcher is a robust, compiler-aware patching system designed to apply LLM-generated fixes, refactors, and insertions to Rust source files with high reliability. It preserves comments, formatting, and handles Rust's macro/cfg complexity without silent corruption.
# From crates.io (when published)
cargo install codex-patcher
# From source
git clone https://github.com/your-org/codex-patcher
cd codex-patcher
cargo install --path .# Apply all patches in patches/ directory
codex-patcher apply --workspace /path/to/codex-rs
# Dry run with diff output
codex-patcher apply --workspace /path/to/codex-rs --dry-run --diff
# Check status of patches
codex-patcher status --workspace /path/to/codex-rs
# Verify patches are applied correctly
codex-patcher verify --workspace /path/to/codex-rsAll edit operations compile down to a single primitive:
pub struct Edit {
file: PathBuf,
byte_start: usize,
byte_end: usize,
new_text: String,
expected_before: EditVerification,
}Why this design?
- Simplifies verification logic
- Makes debugging trivial (see exactly what changed)
- Enables multiple span location strategies
- Preserves formatting and comments
pub enum EditVerification {
ExactMatch(String), // For spans < 1KB
Hash(u64), // xxh3 for larger spans
}Automatic selection based on text size ensures both safety and performance.
| Document | Description |
|---|---|
| Getting Started | Installation and first steps |
| API Reference | Library API documentation |
| Patch Authoring | How to write patch definitions |
| Architecture | System design and internals |
| TOML Patching | TOML-specific query syntax |
| Command | Description |
|---|---|
apply |
Apply patches to a workspace |
status |
Check which patches are applied |
verify |
Verify patches match expected state |
list |
List available patches |
codex-patcher apply [OPTIONS]
Options:
-w, --workspace <PATH> Path to workspace root (auto-detected if not specified)
-p, --patches <FILE> Specific patch file to apply
-n, --dry-run Show what would be changed without modifying files
-d, --diff Show unified diff of changes
-h, --help Print help
-V, --version Print version
use codex_patcher::{Edit, EditResult, WorkspaceGuard};
// Create workspace guard for safety
let guard = WorkspaceGuard::new("/path/to/workspace")?;
// Validate path is within workspace
let file = guard.validate_path("src/main.rs")?;
// Create and apply edit
let edit = Edit::new(
file,
0, // byte_start
5, // byte_end
"HELLO", // new_text
"hello", // expected_before
);
match edit.apply()? {
EditResult::Applied { file, bytes_changed } => {
println!("Applied {} bytes to {}", bytes_changed, file.display());
}
EditResult::AlreadyApplied { file } => {
println!("Already patched: {}", file.display());
}
}use codex_patcher::Edit;
let edits = vec![
Edit::new("src/main.rs", 0, 5, "HELLO", "hello"),
Edit::new("src/main.rs", 10, 15, "WORLD", "world"),
Edit::new("src/lib.rs", 0, 3, "FOO", "foo"),
];
// Applies atomically per file, sorted correctly
let results = Edit::apply_batch(edits)?;
for result in results {
println!("{:?}", result);
}use codex_patcher::sg::PatternMatcher;
let source = r#"
fn main() {
let x = foo.clone();
let y = bar.clone();
}
"#;
let matcher = PatternMatcher::new(source);
// Find all .clone() calls
let matches = matcher.find_all("$EXPR.clone()")?;
for m in matches {
println!("Found clone at bytes {}..{}", m.byte_start, m.byte_end);
}The WorkspaceGuard prevents edits to:
~/.cargo/registry- Dependency source code~/.rustup- Toolchain installationstarget/- Build artifacts- Symlinks escaping workspace
codex-patcher/
├── src/
│ ├── lib.rs # Library entry point
│ ├── main.rs # CLI entry point
│ ├── edit.rs # Core Edit primitive
│ ├── safety.rs # WorkspaceGuard
│ ├── validate.rs # Parse/syn validation
│ ├── config/ # Patch configuration
│ │ ├── schema.rs # Patch definition types
│ │ ├── loader.rs # TOML config parser
│ │ ├── applicator.rs # Patch application logic
│ │ └── version.rs # Semver filtering
│ ├── ts/ # Tree-sitter integration
│ │ ├── parser.rs # Rust parser wrapper
│ │ ├── query.rs # Query engine
│ │ └── locator.rs # Structural locators
│ ├── sg/ # ast-grep integration
│ │ ├── matcher.rs # Pattern matching
│ │ ├── replacer.rs # Replacement operations
│ │ └── lang.rs # Language support
│ └── toml/ # TOML editing
│ ├── editor.rs # TomlEditor
│ ├── query.rs # Section/key queries
│ └── operations.rs # TOML operations
├── patches/ # Patch definitions
│ ├── privacy.toml # Telemetry removal
│ └── performance.toml # Build optimizations
├── tests/ # Integration tests
└── docs/ # Documentation
# Debug build
cargo build
# Release build
cargo build --release
# Run tests
cargo test
# Run clippy
cargo clippy --all-targets -- -D warnings
# Format code
cargo fmt# Run all tests with output
cargo test --all-targets -- --nocapture
# Run specific test
cargo test test_atomic_write
# Run integration tests only
cargo test --test integrationTest Results: 117 tests, 100% passing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes
- Run tests:
cargo test && cargo clippy --all-targets -- -D warnings - Commit:
git commit -m "feat: add amazing feature" - Push:
git push origin feature/amazing-feature - Open a Pull Request
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
Built with these excellent crates:
- tree-sitter - Incremental parsing
- ast-grep - Structural code search
- toml_edit - Format-preserving TOML
- clap - Command-line parsing
Made with care for the Rust community