envsync documentation
Commands
Choose the command form and shell that fit each tool.
Every check, install, and update field accepts a command value. A command can be a string, a list of steps, a command object, null, or a platform map.
A string
A string runs as one command in the selected shell:
"install": "brew install gh"
The default shell is bash on Unix systems when it is available, then sh. On Windows it is pwsh when it is available, then Windows PowerShell. Set a default per OS in the root shell field, or set a shell on one command object.
Supported shell names are bash, sh, zsh, pwsh, powershell, and cmd.
A list of steps
Use an array when a command has multiple steps:
"install": [
"curl -fsSL https://example.com/tool.tar.gz -o /tmp/tool.tar.gz",
"mkdir -p \"$HOME/.local/bin\"",
"tar -xzf /tmp/tool.tar.gz -C \"$HOME/.local/bin\" tool"
]
envsync stops at the first failed step. It uses set -e in Bash and sh, $ErrorActionPreference = 'Stop' in PowerShell, and && in cmd.
A command object
Use an object when a command needs a named shell or its own process group:
"install": {
"run": "irm https://astral.sh/uv/install.ps1 | iex",
"shell": "pwsh"
}
Set isolate to true for a non-interactive command that manages its own terminal or process group:
"update": {
"run": "opencode upgrade",
"isolate": true
}
An isolated command receives EOF on standard input and runs in its own process group. This keeps terminal signals local to that command.
null
Use null when nothing should run for a selector. envsync reports a deliberate skip rather than an unsupported command:
"update": {
"linux": null,
"windows": "winget upgrade --id Example.Tool --exact"
}
See Selectors for how envsync chooses the key in a platform map.
Platform maps
A platform map uses selectors as keys. envsync checks the machine’s selector list from most specific to least specific and uses the first matching key:
"install": {
"linuxmint": "sudo apt-get install -y foo-mint-build",
"apt": "$ENVSYNC_SUDO apt-get install -y foo",
"brew": "brew install foo",
"winget": "winget install --id Example.Tool --exact",
"default": null
}
The value for each key can be any command form except another platform map. A platform map without a matching key is reported as unsupported.
Checks
A bare word with no whitespace is a path lookup. For example, "check": "gh" checks whether gh is on PATH instead of starting a shell command. A check with spaces runs in a shell and must exit with code 0 to count as present.
Environment refresh
After every successful install or update, envsync re-reads the environment the way a new terminal would. It updates PATH and other platform values before the next tool runs. This lets a tool installed by one command be found by the next command without opening another terminal.
Every command can read these variables. The syntax depends on the shell:
| Variable | Example | Meaning |
|---|---|---|
ENVSYNC_OS |
linux |
OS family: linux, macos, or windows. |
ENVSYNC_ID |
linuxmint |
Distro ID, or the OS family on macOS and Windows. |
ENVSYNC_VERSION |
22.1 |
Distro or OS version when known. |
ENVSYNC_ARCH |
x64 |
Machine architecture. |
ENVSYNC_HOST |
codex,container |
Hosts detected around the machine. |
ENVSYNC_SUDO |
sudo or empty |
Privilege prefix for a non-root Unix machine. |
ENVSYNC_INTERACTIVE |
1 or 0 |
Whether input and output are terminals. |
ENVSYNC_TERMINAL |
vscode |
Terminal name when detected. |
ENVSYNC_SELECTORS |
ubuntu-24.04,apt,... |
The full selector list, most specific first. |
Time limits and output
Install and update commands have a two-minute limit. A timed-out command is reported as failed, and envsync continues with later tools. Use --verbose to print checks, selected commands, shells, and environment refresh details.