GuideJuly 8, 20256 min read

Template Variables: Machine-Specific Config Without the Headache

One config file. Different values per machine. No manual editing after every pull. ConfigSync templates make machine-specific configuration effortless.

The Problem: Same File, Different Values

Your .gitconfig has your email address. Your .zshrc references a path that differs between macOS and Linux. Your editor config points to a font that is not installed on every machine. These are all the same config file, but they need different values depending on where they run.

Without templates, you have two bad options: maintain separate config files per machine (defeats the purpose of syncing), or manually edit files after every pull (tedious and error-prone). ConfigSync templates give you a third option: one file that adapts automatically.

Marking Files as Templates

Any tracked file can be marked as a template using the --template flag:

Add a file as a template
configsync add file ~/.gitconfig --template

Template files are stored with their template syntax intact. When ConfigSync restores them during a pull, it evaluates the template expressions and writes the resolved output. The template source is preserved in the cloud; only the local file gets the resolved values.

Built-in Variables

ConfigSync provides several built-in variables that are always available without any setup:

Built-in variables
{{platform}} # "darwin", "linux", or "win32" {{hostname}} # Machine hostname, e.g., "MacBook-Pro.local" {{arch}} # "arm64", "x64", etc. {{home}} # Home directory path, e.g., "/Users/sean"

These are resolved at pull time based on the machine receiving the config. A .zprofile that uses {{platform}} renders differently on macOS versus Linux without any manual intervention.

Machine Variables

For values that are specific to a machine but not derivable from the system (like your preferred editor or a custom path), set machine variables:

Set machine variables
configsync machine var set editor nvim configsync machine var set font "JetBrains Mono" configsync machine var set projects_dir ~/dev

Use them in templates as {{vars.editor}}, {{vars.font}}, and {{vars.projects_dir}}. Each machine can have different values for the same variable names, and the correct value is always substituted during pull.

Conditionals

Templates support conditional blocks for platform-specific or context-specific configuration:

Conditional syntax
{{#if platform == "darwin"}} # macOS-specific config export BROWSER="open" export CLIPBOARD="pbcopy" {{else}} # Linux-specific config export BROWSER="xdg-open" export CLIPBOARD="xclip -selection clipboard" {{/if}} {{#unless platform == "linux"}} # Everything except Linux export HOMEBREW_PREFIX="/opt/homebrew" {{/unless}}

You can also check tags assigned to the current machine or profile:

Tag-based conditionals
{{#if tags contains "work"}} [url "git@github-work:"] insteadOf = git@github.com: {{/if}} {{#if tags contains "server"}} # Headless-only settings export EDITOR="vim" {{/if}}

Profile Variables Override Machine Variables

When a profile is active, its variables take precedence over machine-level variables of the same name. This creates a clean layering system:

Resolution order: Profile variable > Machine variable > Built-in variable. If vars.editor is set on both the machine and the active profile, the profile value wins.

This is useful when a single machine serves multiple contexts. Your machine default might be nvim, but your work profile overrides editor to code because your team standardizes on VS Code.

Example: A Complete .gitconfig Template

Here is a real-world example that combines built-in variables, machine variables, conditionals, and tag checks in a single .gitconfig template:

~/.gitconfig template
[user] name = {{vars.GIT_NAME}} email = {{vars.GIT_EMAIL}} [core] editor = {{vars.editor}} autocrlf = {{#if platform == "win32"}}true{{else}}input{{/if}} {{#if platform == "darwin"}} [credential] helper = osxkeychain {{/if}} {{#if tags contains "work"}} [commit] gpgsign = true [gpg] program = /usr/local/bin/gpg {{/if}} [init] defaultBranch = main

One file. Every machine gets the right email, the right editor, the right credential helper, and the right signing configuration. Push it once, pull it everywhere, and never manually edit .gitconfig after a sync again.

Ready to try ConfigSync?

Sync your entire dev environment across machines in minutes. Free forever for up to 3 devices.