Skip to content

dmg

Install macOS applications distributed as DMG disk images. The plugin mounts the DMG, copies the .app bundle to /Applications, and is silently skipped on non-macOS platforms. The copy keeps the bundle’s directory structure, file contents and permission bits, and recreates every symlink with its original target (extended attributes and resource forks are not copied). It replaces a bundle of the same name that is already installed rather than merging into it; the installed bundle stays in place until the new copy is complete.

The DMG source is configured via a required source object. Sources can be direct URLs or GitHub releases.

If the resolved source points to a supported archive (.zip, .tar.gz, etc.) containing a .dmg file, the archive is automatically extracted first. This is common for GitHub releases that compress DMGs into zip files.

DMG-installed applications are externally managed: temporary files (download, mount point, optional archive extraction) use stagingDir, the final .app is installed to /Applications, and .bin() names the command-line executables inside the bundle so dotfiles can shim them (see .bin() runtime behavior).

import { defineTool } from "@alexgorbatchev/dotfiles";
export default defineTool((install) =>
install("dmg", {
source: {
type: "url",
url: "https://example.com/MyApp-1.0.0.dmg",
},
}),
);
ParameterDescription
sourceRequired. DMG source definition (see source variants below)
appNameName of the .app bundle (e.g., 'MyApp.app'). Auto-detected if omitted
binaryNameExecutable inside Contents/MacOS of the bundle. Defaults to the tool name
binaryPathRelative path to the binary inside .app, when it is not Contents/MacOS/{binaryName}
versionArgsArguments for version check (e.g., ['--version'])
versionRegexRegex to extract version from output (string or RegExp)
tokenGitHub API token for a github-release source
Source typeRequired fieldsOptional fieldsNotes
urlurlDirect DMG URL or archive URL containing a DMG
github-releaserepoversion, assetPattern, assetSelector, ghCli, prereleaseResolves release asset first, then installs from the DMG

assetSelector goes inside source, next to the repository it selects from, and behaves as it does for github-release: see github-release › With an Asset Selector.

A github-release source’s version takes precedence over .version(), and dotfiles update refuses a tool it pins (tool update).

install("dmg", {
source: {
type: "url",
url: "https://example.com/MyApp-1.0.0.dmg",
},
appName: "MyApp.app",
}).version("1.0.0");
install("dmg", {
source: {
type: "url",
url: "https://github.com/example/app/releases/download/v1.0.0/MyApp.dmg.zip",
},
});
install("dmg", {
source: {
type: "github-release",
repo: "manaflow-ai/cmux",
assetPattern: "*macos*.dmg",
},
appName: "cmux.app",
});
install("dmg", {
source: {
type: "url",
url: "https://example.com/MyApp-1.0.0.dmg",
},
versionArgs: ["--version"],
versionRegex: /v(\d+\.\d+\.\d+)/,
});
PlatformBehavior
macOSFull installation via hdiutil
LinuxSilently skipped (returns empty binaries)
WindowsSilently skipped (returns empty binaries)

No .platform() wrapper is needed — the plugin handles platform detection internally.

  • macOS applications distributed as .dmg disk images
  • Tools that ship as .app bundles
  • GitHub releases that distribute .dmg files inside .zip or .tar.gz archives

Prefer brew when the tool is available as a Homebrew formula or cask. Prefer curl-binary or github-release for cross-platform tools.