A powerful CLI tool for converting existing projects into reusable Jinja2 templates. Transform your project files and directory structures by replacing tokens with template variables while preserving the original functionality.
brew install archetect/tap/templatize
cargo install templatize
Download the latest release for your platform from the releases page.
git clone https://github.com/archetect/templatize
cd templatize
cargo build --release
# 1. ALWAYS escape existing Jinja syntax first (critical step!)
templatize escape --dry-run
# 2. Apply case shape transformations for compound words
templatize shapes "my-project" "{{ project_name }}" -p -c --dry-run
# 3. Make precise replacements for specific tokens
templatize exact "MyCompany" "{{ company_name }}" -p -c --dry-run
# Remove --dry-run when you're ready to apply changes
β οΈ Critical: Runescape
before any other commands, or it will break your template variables!
Escapes existing Jinja2 template syntax so it can be embedded within templates.
templatize escape [TARGET] [OPTIONS]
Example:
# Escape all Jinja syntax in current directory
templatize escape --interactive
# Before: {{ existing_var }}
# After: {{'{'}}{ existing_var }
Options:
TARGET
- Target file or directory (defaults to current directory)--dry-run
- Preview changes without applying them--interactive
- Prompt for each change with diff preview
Replaces compound words with all their case variants (camelCase, PascalCase, kebab-case, etc.).
templatize shapes <TOKEN> <REPLACEMENT> [TARGET] [OPTIONS]
Example:
templatize shapes "my-project" "{{ project_name }}" -p -c
# Transforms:
# my-project β {{ project_name }}
# myProject β {{ projectName }}
# MyProject β {{ ProjectName }}
# my_project β {{ project_name }}
# MY_PROJECT β {{ PROJECT_NAME }}
# My-Project β {{ Project-Name }}
# MY-PROJECT β {{ PROJECT-NAME }}
Arguments:
<TOKEN>
- Compound word to replace (must contain hyphens, underscores, or mixed case)<REPLACEMENT>
- Jinja2 template variable (e.g.,{{ project_name }}
)[TARGET]
- Target directory (defaults to current directory)
Options:
-p, --path
- Transform file and directory names-c, --contents
- Transform file contents--dry-run
- Preview changes without applying them--interactive
- Prompt for each change with diff preview
Replaces exact token matches with specified Jinja2 syntax.
templatize exact <TOKEN> <REPLACEMENT> [TARGET] [OPTIONS]
Example:
templatize exact "MyCompany Inc." "{{ company_name }}" -p -c
# Replaces only exact matches of "MyCompany Inc." with "{{ company_name }}"
Arguments:
<TOKEN>
- Exact token to replace<REPLACEMENT>
- Jinja2 template variable[TARGET]
- Target directory (defaults to current directory)
Options:
-p, --path
- Transform file and directory names-c, --contents
- Transform file contents--dry-run
- Preview changes without applying them--interactive
- Prompt for each change with diff preview
β οΈ Important: Always runtemplatize escape
FIRST, before any other commands. Running escape after creating template variables would escape your newly created{{ variables }}
, breaking your templates.
Handle existing Jinja syntax first, then apply transformations from broad to specific:
# Step 1: ALWAYS escape existing Jinja syntax first
templatize escape --interactive
# Step 2: Apply broad case shape transformations
templatize shapes "my-awesome-project" "{{ project_name }}" -p -c --interactive
# Step 3: Handle specific cases that shapes missed or got wrong
templatize exact "AwesomeLib" "{{ library_name }}" -p -c --interactive
# Step 4: Handle version numbers, dates, or other specific tokens
templatize exact "1.0.0" "{{ version }}" -c --interactive
templatize exact "2024" "{{ current_year }}" -c --interactive
If your project doesn't contain any existing Jinja syntax, you can skip the escape step:
# Step 1: Apply broad case shape transformations
templatize shapes "my-project" "{{ project_name }}" -p -c --interactive
# Step 2: Handle specific edge cases
templatize exact "SPECIAL_CONSTANT" "{{ app_constant }}" -c --interactive
# Navigate to your React project
cd my-react-app
# 1. Escape existing template syntax (if any)
templatize escape --dry-run
templatize escape
# 2. Transform the main project name across all case variants
templatize shapes "my-react-app" "{{ app_name }}" -p -c --dry-run
templatize shapes "my-react-app" "{{ app_name }}" -p -c
# 3. Handle specific branding
templatize exact "My Amazing React App" "{{ app_display_name }}" -c --interactive
# 4. Replace author information
templatize exact "John Doe" "{{ author_name }}" -c --interactive
templatize exact "john@example.com" "{{ author_email }}" -c --interactive
# 5. Handle version and year
templatize exact "1.0.0" "{{ version }}" -c --interactive
templatize exact "2024" "{{ current_year }}" -c --interactive
cd my-python-package
# 1. Escape existing Jinja (common in setup.py templates)
templatize escape --interactive
# 2. Transform package name variants
templatize shapes "my-python-package" "{{ package_name }}" -p -c --interactive
# 3. Handle module-specific names that might differ
templatize exact "MyPythonPackageError" "{{ package_name | title }}Error" -c --interactive
# 4. Replace metadata
templatize exact "A fantastic Python package" "{{ package_description }}" -c --interactive
templatize exact "MIT" "{{ license }}" -c --interactive
cd my-java-project
# 1. Escape existing Jinja syntax (if any)
templatize escape --interactive
# 2. Transform the main project name across all case variants
templatize shapes "my-java-project" "{{ project_name }}" -p -c --interactive
# 3. Handle Java package structure (multi-level directory paths)
templatize exact "com/acme/widgets" "{{ package_root }}" -p --interactive
# 4. Replace specific company/project references
templatize exact "Acme Corporation" "{{ company_name }}" -c --interactive
templatize exact "widgets@acme.com" "{{ contact_email }}" -c --interactive
# 5. Handle version and configuration
templatize exact "1.0.0-SNAPSHOT" "{{ version }}" -c --interactive
cd my-docs
# 1. Escape existing Jinja syntax (common in static site generators)
templatize escape --interactive
# 2. Transform project references
templatize shapes "awesome-docs" "{{ project_name }}" -p -c --interactive
# 3. Handle specific documentation strings
templatize exact "Awesome Documentation Site" "{{ site_title }}" -c --interactive
templatize exact "https://awesome-docs.com" "{{ site_url }}" -c --interactive
# 4. Replace navigation and branding
templatize exact "Β© 2024 Awesome Corp" "{{ copyright_notice }}" -c --interactive
Interactive mode (--interactive
or -i
) shows you a diff preview of each change and asks for confirmation:
π File: src/components/MyProject.tsx
π Content change:
- const projectName = 'MyProject';
+ const projectName = '{{ ProjectName }}';
β Apply this change? [y/N/q] y
β
Applied change
π Path change: File
- src/components/MyProject.tsx
+ src/components/{{ ProjectName }}.tsx
β Apply this change? [y/N/q] y
β
Applied change
# Preview changes before applying
templatize shapes "my-project" "{{ project_name }}" -p -c --dry-run
# Review each change individually
templatize shapes "my-project" "{{ project_name }}" -p -c --interactive
- Escape existing Jinja syntax FIRST (always!)
- Shapes for broad compound word transformations
- Exact for precise, specific replacements
β οΈ Never runescape
aftershapes
orexact
- it will escape your template variables!
# Paths and contents together
templatize shapes "my-app" "{{ app_name }}" -p -c
# Just file contents (safer for first attempts)
templatize exact "MyCompany" "{{ company }}" -c
# Just paths (for renaming files/directories)
templatize shapes "my-project" "{{ project_name }}" -p
After templatizing, test your template with a template engine:
# Using Jinja2 CLI or your preferred templating tool
jinja2 your-template.txt.j2 --format=json < variables.json
# Transform all variants of a project name
templatize shapes "my-awesome-app" "{{ app_name }}" -p -c
# Replace exact company references
templatize exact "Acme Corporation" "{{ company_name }}" -c
templatize exact "contact@acme.com" "{{ contact_email }}" -c
# Replace version strings
templatize exact "1.0.0" "{{ version }}" -c
templatize exact "2024-01-01" "{{ release_date }}" -c
templatize exact "2024" "{{ current_year }}" -c
# Database and service configurations
templatize exact "localhost:5432" "{{ database_url }}" -c
templatize exact "my-service-key-123" "{{ api_key }}" -c
# Transform multi-level directory paths (Java packages, etc.)
templatize exact "com/acme/widgets" "{{ package_root }}" -p
# Before: src/main/java/com/acme/widgets/entities/User.java
# After: src/main/java/{{ package_root }}/entities/User.java
# Python package structures
templatize exact "my_company/my_project" "{{ python_package }}" -p
# Before: src/my_company/my_project/models/user.py
# After: src/{{ python_package }}/models/user.py
If your template variables like {{ project_name }}
became {{'{'}}{ project_name }
, you ran escape
after creating them:
# β Wrong order - this breaks your templates
templatize shapes "my-app" "{{ app_name }}" -p -c
templatize escape # This will escape the {{ app_name }} you just created!
# β
Correct order
templatize escape # Escape existing templates first
templatize shapes "my-app" "{{ app_name }}" -p -c # Then create new ones
The shapes
command requires compound words with separators:
# β This will fail
templatize shapes "example" "{{ name }}" -p -c
# β
These work
templatize shapes "example-name" "{{ name }}" -p -c
templatize shapes "ExampleName" "{{ name }}" -p -c
templatize shapes "example_name" "{{ name }}" -p -c
Use --dry-run
and --interactive
to preview changes:
# Preview all changes
templatize shapes "my-app" "{{ app_name }}" -p -c --dry-run
# Review each change individually
templatize shapes "my-app" "{{ app_name }}" -p -c --interactive
Templatize automatically skips binary files when processing contents. Only text files are modified.
-v, --verbose
- Show detailed logging information-q, --quiet
- Suppress all output except errors-h, --help
- Show help information
This project follows a workspace-based architecture:
crates/templatize-bin/
- CLI application and user interfacecrates/templatize-core/
- Core templating logic and algorithmsxtask/
- Build automation and development tasks
# Run comprehensive test suite
cargo xtask test all
# Run specific test suites
cargo xtask test core # Core library tests
cargo xtask test bin # Binary crate tests
cargo xtask test integration # Integration tests
# Build and run with arguments
cargo xtask run -- exact "token" "{{ replacement }}" -p -c
# Install locally
cargo xtask install
For detailed technical information:
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
MIT License - see LICENSE file for details.