4 releases
Uses new Rust 2024
| new 0.0.4 | May 8, 2026 |
|---|---|
| 0.0.3 | Jun 4, 2025 |
| 0.0.2 | Jan 2, 2025 |
| 0.0.1 | Dec 1, 2024 |
#127 in Artificial intelligence
155KB
4K
SLoC
genify
MCP tool for AI coding agents to safely plan, diff, and apply structured file changes inside a project root.
Use genify for repeatable codebase edits: writing files, replacing text, inserting blocks around markers, moving/copying/deleting paths, creating directories, changing modes, and generating dry-run diffs before applying changes.
Turn one file into a complete project
The main idea is to have a single source file that can be used to generate or update a full project structure quickly and consistently using different configuration files.
There are three modes:
- CLI interactive mode – for manual use and quick input.
- Code mode – for automated and configurable project generation.
- MCP server mode – for AI coding agents that call structured tools over STDIO.
Features:
- Create files from templates based on config.
- Replace content using regular expressions.
- Append or prepend content to existing files.
- Easily update multiple projects using shared configs.
Installation
Cargo
- Install the rust toolchain in order to have cargo installed by following this guide.
- run
cargo install genify --features cli
Get Started
CLI
Turn one file into a complete project
Usage: genify [OPTIONS] [PATH]
genify <COMMAND>
Arguments:
[PATH] Path to a config file or http(s) URL
Options:
-p, --props-json <JSON> Override props using a JSON object (Array/Map supported)
-n, --no-interaction Do not ask any interactive question
-h, --help Print help
-V, --version Print version
Commands:
mcp Start genify as an MCP server over STDIO
help Print this message or the help of the given subcommand(s)
example.toml
[props]
value = "value"
dir = "tmp"
val = "val"
other = "{{ val }}"
override = "1"
[[rules]]
type = "write"
path = "{{ dir }}/some.txt" # if the file exists will be error
content = "{{ val }} {{ value }} {{ other | pascal_case }} {{ override }} - should be replaced"
if_exists = "error"
[[rules]]
type = "replace"
path = "{{ dir }}/some.txt"
replace = "should.*replaced"
content = "replaced {{ value }}"
[[rules]]
type = "prepend"
path = "{{ dir }}/some.txt"
content = "prepend {{ value }}"
[[rules]]
type = "append"
path = "{{ dir }}/some.txt"
content = "append {{ value }}"
genify example.toml
Override props from the CLI (including Array/Map) using JSON:
genify example.toml --props-json '{"tags": ["cli", "json"], "meta": {"license": "MIT"}}'
tmp/some.txt
prepend value
val value Val 1 - replaced value
append value
MCP
Run genify as an MCP server using the standard STDIO transport:
genify mcp --root .
For read-only agent sessions:
genify mcp --root . --read-only
Example Codex configuration:
[mcp_servers.genify]
command = "genify"
args = ["mcp", "--root", "."]
The MCP server writes protocol messages only to stdout; logs and diagnostics go to stderr.
All filesystem access is constrained to --root.
Available tools:
| Tool | Behavior |
|---|---|
genify_plan |
Returns planned file operations and affected paths without writing files. |
genify_diff |
Runs generation in dry-run mode and returns a unified diff. |
genify_apply |
Applies changes only when explicit_approval is true or confirm_token is "apply". |
genify_validate_config |
Validates config parsing, rendering, and generated paths. |
genify_list_templates |
Lists .toml configs and template files under the MCP root. |
genify_plan, genify_diff, and genify_apply accept the config directly as JSON in MCP tool arguments.
No temporary TOML config or template file is required.
{
"config": {
"rules": [
{
"type": "replace",
"path": "src/application.rs",
"replace": "old text",
"content": "new text"
}
]
},
"root": "."
}
Supported rule types:
| Type | Fields |
|---|---|
write |
path, content, if_exists (overwrite, error, or skip) |
delete |
path |
rename / move |
from, to |
copy |
from, to |
mkdir |
path |
chmod |
path, mode |
append / append_once / prepend |
path, content |
insert_before / insert_after |
path, marker, content |
replace / replace_or_append |
path, replace, content, optional replace_all, optional expected_matches |
managed_block |
path, start_marker, end_marker, content |
replace is strict by default: when replace_all is false or omitted, it fails unless the regex match count equals expected_matches, which defaults to 1.
Supported rule examples:
{
"config": {
"rules": [
{
"type": "write",
"path": "new/file.rs",
"content": "...",
"if_exists": "error"
}
]
}
}
{
"config": {
"rules": [
{
"type": "append_once",
"path": "README.md",
"content": "..."
}
]
}
}
{
"config": {
"rules": [
{
"type": "managed_block",
"path": "README.md",
"start_marker": "<!-- genify:start -->",
"end_marker": "<!-- genify:end -->",
"content": "..."
}
]
}
}
{
"config": {
"rules": [
{
"type": "insert_after",
"path": "README.md",
"marker": "## Usage",
"content": "..."
}
]
}
}
{
"config": {
"rules": [
{
"type": "move",
"from": "old/file.rs",
"to": "new/file.rs"
}
]
}
}
genify_validate_config returns a structured hint.minimal_config and per-operation examples when the config is missing or invalid.
Supported Variable Types
| Type | Description | CLI Interactive Support |
|---|---|---|
| String | Text value | ✅ Supported |
| Integer | Whole number | ✅ Supported |
| Float | Decimal number | ✅ Supported |
| Boolean | true or false | ✅ Supported |
| Array | List of values | ✅ JSON input |
| Map | Key-value pairs | ✅ JSON input |
Note: For Array and Map, enter JSON when prompted or provide them up front with --props-json.
Code
fn main() {
genify::generate(
Path::new("."),
&genify::parse_toml(
fs::read_to_string("example.toml")
.unwrap()
.as_str(),
)
.expect("The config should be valid"),
Some(vec![(
"value".to_string(),
genify::Value::String("val".to_string()),
)]),
)
.expect("The generation should be successful");
}
License
Contribution
Dependencies
~8–17MB
~301K SLoC