A fast, cross-platform command-line file preprocessor built with Rust that uses MiniJinja templates to transform files with dynamic variables.
- Flexible Input: Process single files, multiple files, directories (with optional recursion), or stdin
- Smart Output: Write to stdout, single files, or directories while preserving structure
- Multiple Config Formats: Load variables from JSON, YAML, or TOML configuration files
- Variable Precedence: Layer variables from environment (explicit), config files, and CLI arguments
- Environment Control: Load specific environment variables with
--envflag - Cross-Platform: Builds on Linux, macOS, and (future) Windows
- Powered by MiniJinja: Full access to MiniJinja's powerful template syntax and filters
git clone https://github.com/bbeardsley/shinkansen
cd shinkansen
cargo build --release
# Binary will be at ./target/release/shinkansenjust installThis installs the binary to your Cargo bin directory (typically ~/.cargo/bin).
Add the binary to your PATH or use it directly:
./target/release/shinkansen --helpProcess a single template file with CLI variables:
shinkansen template.txt -D name="John" -D app="MyApp" -o -JSON Config (config.json):
{
"name": "Alice",
"version": "1.0.0",
"environment": "production"
}shinkansen template.txt -c config.json -o output.txtYAML Config (config.yaml):
name: Bob
version: "2.0.0"
debug: trueshinkansen template.txt -c config.yaml -o -TOML Config (config.toml):
name = "Charlie"
version = "3.0.0"
features = ["auth", "api"]shinkansen template.txt -c config.toml -o output.txtecho "Hello, {{ name }}!" | shinkansen - -D name="World"
# Output: Hello, World!
# Explicit stdout with -o -
echo "Hello, {{ name }}!" | shinkansen - -D name="World" -o -Variables are layered with increasing precedence:
- Environment variables (only when specified with
--env, lowest) - Config file variables
- CLI arguments (highest)
export GREETING="Hi"
shinkansen template.txt -c config.yaml --env="GREETING" -D GREETING="Hello" -o -
# CLI value "Hello" winsLoad specific environment variables:
shinkansen template.txt --env="PATH,HOME,USER" -o -When using -D flag or environment variables, you can escape special
characters:
\\- escaped backslash\,- escaped comma\=- escaped equals\[- escaped left bracket\]- escaped right bracket\{- escaped left curly brace\}- escaped right curly brace
Examples:
# Escape curly brackets in command line
shinkansen template.txt -D "message=Hello\{world\}"
# Escape multiple characters
shinkansen template.txt -D "data=key\=value\,more\\data"
# Environment variables with escaping
export VAR="test\{curly\}brackets"
shinkansen template.txt --env VAREnvironment variables are not loaded automatically. You must explicitly
specify which variables to load using the --env flag. Multiple variables can
be specified as a comma-separated list.
Process all files in a directory (non-recursive):
shinkansen templates/ -o output/ -D env="prod"Process directory recursively:
shinkansen templates/ -r -o output/ -c config.jsonDirectory structure is preserved in the output:
templates/
├── app.conf
└── services/
└── api.conf
→ output/
├── app.conf
└── services/
└── api.conf
shinkansen file1.txt file2.txt file3.txt -o output_dir/ -D version="1.0"To stdout (default for single input):
shinkansen template.txt -D var="value"
# Or explicitly with -o -
shinkansen template.txt -D var="value" -o -To a specific file:
shinkansen template.txt -D var="value" -o result.txtTo a directory:
shinkansen template.txt -D var="value" -o output/
# Creates output/template.txtShinkansen uses MiniJinja templates. Here are some common patterns:
Hello, {{ name }}!
Version: {{ version }}
{{ name | upper }}
{{ email | default(value="no-email") }}
{{ price | round(precision=2) }}
{% if debug %}
Debug mode is ON
{% else %}
Production mode
{% endif %}
{% for item in items %}
- {{ item }}
{% endfor %}
{# This is a comment and won't appear in output #}
For complete MiniJinja syntax documentation, see: https://docs.rs/minijinja/latest/minijinja/
| Input Type | Valid Output Options |
|---|---|
| Single file | File, directory, or stdout |
| Multiple files | Directory only |
| Directory | Directory only |
| Stdin | File, directory, or stdout |
Generate configuration files for different environments:
# Development
shinkansen app.conf.template -c dev.yaml -o config/dev/app.conf
# Production
shinkansen app.conf.template -c prod.yaml -o config/prod/app.confshinkansen api_template.rs -c schema.json -o src/generated/api.rsshinkansen README.template.md -D version="1.2.3" -D date="2024-01-15" -o README.mdshinkansen templates/ -r -c project.yaml -o output/The project is designed to be cross-platform.
Linux:
cargo build --releasemacOS:
cargo build --releaseWindows:
cargo build --releaseCross-compilation:
# For Windows from Linux/macOS
cargo build --release --target x86_64-pc-windows-msvcShinkansen provides helpful error messages for common issues:
- Missing required template variables
- Invalid template syntax
- File/directory access errors
- Invalid input/output combinations
- Config file parsing errors
- Rust 2024 edition or later
- Cargo
- Optional: just for build tasks
- clap - Command-line argument parsing with derive macros
- clap_complete - Shell completion generation
- minijinja - Template engine
- serde - Serialization framework
- serde_json - JSON support
- serde_yaml - YAML support
- toml - TOML support
- walkdir - Directory traversal
- tempfile - Temporary file handling (dev and runtime)
See the examples/ directory for complete, working examples:
- project.md.template - Project README template with conditionals and loops
- nginx.conf.template - Nginx configuration template
- config.json - Sample JSON configuration
- EXAMPLES.md - Detailed usage examples
Run examples directly:
# Simple template with CLI variables
./target/release/shinkansen examples/project.md.template \
-D project_name="My Project" \
-D version="2.0.0" \
-o -
# Using config file
./target/release/shinkansen examples/project.md.template \
-c examples/config.json \
-o -MIT License - see repository for details.
If you see Variable 'x' not found in context, ensure:
- The variable is defined via
-D, config file, or environment - The variable name matches exactly (case-sensitive)
- Use the
defaultfilter for optional variables:{{ var | default(value="fallback") }}
When processing multiple files, specify an output directory:
shinkansen file1.txt file2.txt -o output_dir/