Skip to content

Platform-Specific Configuration

Use .platform() for cross-platform tool configurations.

import { Architecture, Platform } from "@alexgorbatchev/dotfiles";
// Platforms (bitwise flags)
Platform.Linux; // 1
Platform.MacOS; // 2
Platform.Windows; // 4
Platform.All; // All platforms (7)
// Architectures (bitwise flags)
Architecture.X86_64; // 1
Architecture.Arm64; // 2
Architecture.All; // Both (3)
import { defineTool, Platform } from "@alexgorbatchev/dotfiles";
export default defineTool((install) =>
install()
.bin("tool")
.platform(Platform.MacOS, (install) => install("brew", { formula: "tool" }))
.platform(Platform.Linux, (install) =>
install("github-release", {
repo: "owner/tool",
assetPattern: "*linux*.tar.gz",
}),
)
.platform(Platform.Windows, (install) =>
install("github-release", {
repo: "owner/tool",
assetPattern: "*windows*.zip",
}),
),
);
import { Architecture, defineTool, Platform } from "@alexgorbatchev/dotfiles";
export default defineTool((install) =>
install()
.bin("tool")
.platform(Platform.Linux, Architecture.X86_64, (install) =>
install("github-release", {
repo: "owner/tool",
assetPattern: "*linux-amd64*.tar.gz",
}),
)
.platform(Platform.Linux, Architecture.Arm64, (install) =>
install("github-release", {
repo: "owner/tool",
assetPattern: "*linux-arm64*.tar.gz",
}),
)
.platform(Platform.MacOS, Architecture.All, (install) => install("brew", { formula: "tool" })),
);

There are three platforms: Linux, MacOS and Windows. Combine them with | to share configuration between several, rather than reaching for a named alias:

export default defineTool((install) =>
install()
.bin("tool")
// One POSIX install script serves both Linux and macOS.
.platform(Platform.Linux | Platform.MacOS, (install) =>
install("curl-script", {
url: "https://example.com/install.sh",
shell: "bash",
}),
)
.platform(Platform.Windows, (install) =>
install("github-release", {
repo: "owner/tool",
assetPattern: "*windows*.zip",
}),
),
);

Only group platforms when the configuration is genuinely identical for each of them. Release assets are built per operating system, so assetPattern almost always belongs in a separate block per platform — grouping Linux with macOS there would hand a Mac a Linux build. See the architecture example above for the per-platform form.

export default defineTool((install) =>
install("github-release", { repo: "owner/tool" })
.bin("tool")
.platform(Platform.Linux | Platform.MacOS, (install) =>
install().zsh((shell) =>
shell.env({
TOOL_CONFIG: "~/.config/tool",
}),
),
)
.platform(Platform.Windows, (install) =>
install().powershell((shell) =>
shell.env({
TOOL_CONFIG: "~\\.config\\tool",
}),
),
),
);

Root-level hooks still apply when the actual installer is defined inside .platform(...). Use that pattern for shared lifecycle logic, then put only the platform-specific install method inside each override.

export default defineTool((install) =>
install("github-release", { repo: "owner/tool" })
.bin("tool")
.hook("after-install", async ({ systemInfo, $ }) => {
if (systemInfo.platform === Platform.MacOS) {
await $`./setup-macos.sh`;
} else if (systemInfo.platform === Platform.Linux) {
await $`./setup-linux.sh`;
}
if (systemInfo.arch === Architecture.Arm64) {
await $`./configure-arm64.sh`;
}
}),
);
PlatformPattern Examples
macOS*darwin*.tar.gz, *macos*.zip
Linux*linux*.tar.gz, *x86_64-unknown-linux-gnu*
Windows*windows*.zip, *pc-windows-msvc*
x86_64*amd64*, *x86_64*
ARM64*arm64*, *aarch64*