Skip to content

dmg

Install macOS applications distributed as DMG disk images. The plugin mounts the DMG read-only and hidden from the Finder, 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. When the image cannot be detached afterwards, even with hdiutil detach -force (a process can hold a file on the volume open), the install fails with an error naming the mount point, which is left in place; detach the image yourself before installing again.

Without appName, the bundle installed is the first .app at the root of the volume, and a volume that holds none fails the install. The bundle installed is recorded, so dotfiles tool uninstall removes that bundle (with the hidden .dotfiles-new- and .dotfiles-old- copies an interrupted install can leave beside it) even when its name is not the tool’s. A tool with no recorded installation is uninstalled by appName; with neither, it removes nothing from /Applications rather than a guessed bundle.

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'). Defaults to the first .app at the volume’s root; it must end in .app and contain no /
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
urlurl—Direct 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.