21 KiB
Executable File
Installer Configuration
The install field describes the steps to execute. Each step represents an action or group of
actions. Steps can be of several types, such as brew, rsync, shell, and more.
Categories
You can add category headers to visually organize your installers list. Categories are special entries that display a bordered header in the output but don't perform any installation.
Fields
-
category- Type: String (required for category entries)
- Description: The category name to display. When this field is present, the entry is treated as a category header, not an installer.
-
desc- Type: String (optional)
- Description: An optional description shown below the category name. Supports multi-line text with automatic word wrapping. Existing line breaks are preserved.
Example
install:
- category: Development Tools
- name: neovim
type: brew
- name: lazygit
type: brew
- category: System Utilities
desc: Tools for system maintenance and monitoring.
- name: htop
type: brew
- category: Configuration
desc: |
These installers sync configuration files from dotfiles.
They run on every execution to keep configs up to date.
- name: nvim-config
type: rsync
opts:
source: ~/.dotfiles/.config/nvim
destination: ~/.config/nvim
Output
The appearance of category headers is controlled by the top-level category_display option.
border (default)
Categories are displayed with a bordered header and spacing before/after:
┌──────────────────────────────────────────────────────────┐
│ Development Tools │
└──────────────────────────────────────────────────────────┘
With a description:
┌──────────────────────────────────────────────────────────┐
│ System Utilities │
├──────────────────────────────────────────────────────────┤
│ Tools for system maintenance and monitoring. │
└──────────────────────────────────────────────────────────┘
border-compact
Same as border, but without the empty lines before and after the box.
minimal
Categories are displayed as plain text without any border or spacing:
Development Tools
With a description:
System Utilities
Tools for system maintenance and monitoring.
The box width (for border and border-compact) adapts to narrower terminals (minimum of terminal
width or 60 characters).
Fields
These fields are shared by all installer types. Some fields may vary in behavior depending on the
type.
-
name- Type: String (required)
- Description: Identifier for the step. It does not have to be unique, but is usually used to
check for the app's existence (can be overridden using
bin_name).
-
type- Type: String (required)
- Description: Type of the step. See supported types for a comprehensive list of supported values.
-
enabled- Type: String or Boolean (optional)
- Description: Enable or disable the step. Disabled steps are not run. This can either be a
static boolean (
trueorfalse), or a command that returns a success status code for true, or a failure for false.
-
tags- Type String (optional)
- Description: Arbitrary tags to attach to an installer. These can later be used to filter this installer in or out when running sofmani. This should be a string containing space-separated tags.
-
platforms- Type: Object (optional)
- Description: Platform-specific execution controls. See
platformssubfields below. - Subfields:
platforms.only- Type: Array of Strings
- Description: Platforms where the step should execute (e.g.,
['macos', 'linux']). Supercedesplatforms.except.
platforms.except- Type: Array of Strings
- Description: Platforms where the step should not execute; replaces
platforms.only.
-
machines- Type: Object (optional)
- Description: Machine-specific execution controls. Use this to run installers only on
specific machines. Get the machine ID by running
sofmani --machine-id. You can use either raw machine IDs or aliases defined in the top-levelmachine_aliasesconfiguration. Seemachinessubfields below. - Subfields:
machines.only- Type: Array of Strings
- Description: Machine IDs or aliases where the step should execute. Supercedes
machines.except.
machines.except- Type: Array of Strings
- Description: Machine IDs or aliases where the step should not execute.
-
steps- Type: Array of Installers
- Description: Sub-steps for
grouptype. Allows nesting multiple steps together. Ignored for all other types.
-
opts- Type: Object (optional)
- Description: Step-specific options and configurations. Content varies depending on the
type. See supported types for a comprehensive list of supported values.
-
bin_name- Type: String (optional)
- Description: Binary name for the installed software, used instead of
namewhen checking for app's existence.
-
check_has_update- Type: String (shell script)
- Description: Shell command to check whether an update is available for the installed
software. This will override the default check provided by the corresponding
type. The check must succeed (return exit code 0) if the app has an update, or fail (other status codes) if the app is up to date.
-
check_installed- Type: String (shell script)
- Description: Shell command to check if the step has already been installed. If the check succeeds (exits with status 0), it means the app is already installed and can be skipped if not checking for updates.
-
pre_install- Type: String (shell script)
- Description: Shell script to execute before the step is installed.
-
post_install- Type: String (shell script)
- Description: Shell script to execute after the step is installed.
-
pre_update- Type: String (shell script)
- Description: Shell script to execute before the step is updated (if applicable).
-
post_update- Type: String (shell script)
- Description: Shell script to execute after the step is updated (if applicable).
-
env_shell- Type: Object (optional)
- Description: Shell to use for command executions. See
env_shellsubfields below. Windows always usescmd. - Subfields:
env_shell.macos- Type: String (optional)
- Description: Shell to use for macOS command executions. If not specified, the default shell will be used.
env_shell.linux- Type: String (optional)
- Description: Shell to use for Linux command executions. If not specified, the default shell will be used.
-
skip_summary-
Type: Boolean or Object (optional)
-
Description: Exclude this installer from the installation summary. Useful for installers that always run (like config sync scripts) and would clutter the summary output.
-
Values:
- Boolean: When set to
true, the installer is excluded from both install and update summaries. When set tofalse(default), the installer appears in summaries normally. - Object: For granular control, specify which summaries to skip:
skip_summary.install: Boolean - exclude from the "Installed" section of the summary.skip_summary.update: Boolean - exclude from the "Upgraded" section of the summary.
- Boolean: When set to
-
Examples:
# Skip from both install and update summaries - name: sync-dotfiles type: rsync skip_summary: true opts: source: ~/.dotfiles/.config destination: ~/.config # Skip only from install summary (still shows in upgrade summary) - name: config-setup type: shell skip_summary: install: true opts: command: ./setup.sh # Skip only from upgrade summary (still shows in install summary) - name: my-tool type: brew skip_summary: update: true
-
Supported type of Installers
-
shell- Description: Executes arbitrary shell commands.
- Options:
opts.command: The command to execute for installing.opts.update_command: The command to execute for updating.
-
group- Description: Executes a logical group of steps in sequence.
- Allows nesting multiple steps together.
- Options:
steps: List of nested steps.
- Description: Executes a logical group of steps in sequence.
-
git- Description: Clones a git repository to a local directory.
- If
nameis a full git URL (https or SSH), the repository is cloned directly. - If it is a repository path, e.g.
chenasraf/sofmani, GitHub is assumed.
- If
- Options:
opts.destination: The local directory to clone the repository to.opts.ref: The branch, tag, or commit to checkout after cloning.opts.flags: Additional flags to pass to git commands (fallback for install/update).opts.install_flags: Additional flags to pass only togit clone.opts.update_flags: Additional flags to pass only togit pull.
- Description: Clones a git repository to a local directory.
-
github-release- Description: Downloads a GitHub release asset. Optionally untar/unzip the downloaded file.
- Options:
-
opts.repository: The repository to download from. Should be in the format:user/repository-name -
opts.destination: The target directory to extract the files to. -
opts.strategy: The download strategy. Can be one of:tar,zip,none(default)none- the release file is not compressed, and should be copied directlytar- the release file is a tar file, and should be extractedzip- the release file is a zip file, and should be extracted
-
opts.download_filename: The filename of the release asset to download.This should either be a string, or a map of platforms to filenames.
You can use Go template syntax to insert dynamic values into the filename:
{{ .Tag }}- the full tag name, e.g.v1.0.0{{ .Version }}- the version without the leading "v", e.g.1.0.0{{ .Arch }}- the system architecture in Go format, e.g.amd64,arm64{{ .ArchAlias }}- the architecture in common alias format, e.g.x86_64,arm64{{ .ArchGnu }}- the architecture in GNU/Linux format, e.g.x86_64,aarch64{{ .OS }}- the current operating system, e.g.macos,linux,windows
Legacy syntax (deprecated): The old
{tag},{version},{arch},{arch_alias},{arch_gnu}, and{os}tokens are still supported but deprecated. A deprecation warning will be logged at DEBUG level when they are used.Examples:
# Using Go template syntax (recommended) download_filename: myapp_{{ .Tag }}_linux_{{ .ArchAlias }}.tar.gz # outputs: myapp_v1.0.0_linux_x86_64.tar.gz download_filename: myapp_{{ .Version }}_{{ .OS }}.tar.gz # outputs: myapp_1.0.0_linux.tar.gz # Platform-specific filenames download_filename: macos: myapp_{{ .Tag }}_darwin_{{ .ArchAlias }}.tar.gz linux: myapp_{{ .Tag }}_linux_{{ .ArchAlias }}.tar.gz windows: myapp_{{ .Tag }}_windows_{{ .ArchAlias }}.zip # Legacy syntax (deprecated, still works) download_filename: myapp_{tag}_linux.tar.gz # outputs: myapp_v1.0.0_linux.tar.gz -
opts.github_token: GitHub personal access token for authenticated API requests. Authenticated requests have a much higher rate limit (5,000/hour vs 60/hour for unauthenticated).Supports environment variable expansion, so you don't need to hard-code credentials:
# Using environment variables (recommended) github_token: $GITHUB_TOKEN github_token: ${GITHUB_TOKEN} # Can also be set as a default for all github-release installers defaults: type: github-release: opts: github_token: $GITHUB_TOKEN
-
-
manifest- Description: Installs an entire manifest from a local or remote file.
- Every entry in the
installarray will be run, similar to howstepsare run forgroupinstallers. debugandcheck_updateswill be inherited by the loaded config.envanddefaultswill be merged into the loaded config, overriding any existing values.- Remote manifests are fetched directly via HTTP (no git clone required).
- Every entry in the
- Options:
opts.source: The source of the manifest file. Supports:- Local file paths (e.g.,
~/.dotfiles/manifest.yml) - Git repository URLs (SSH or HTTPS) - GitHub, GitLab, Bitbucket, and self-hosted instances
- Raw HTTP URLs (e.g.,
https://raw.githubusercontent.com/user/repo/master/manifest.yml)
- Local file paths (e.g.,
opts.path: The path to the manifest file within the repository. Required for git URLs, optional for local files (will be appended to source). Ignored for raw HTTP URLs.opts.ref: The branch, tag, or commit to use ifopts.sourceis a git URL. Defaults tomaster. Ignored for local files and raw HTTP URLs.
- Description: Installs an entire manifest from a local or remote file.
-
rsync- Description: Copy files from
sourcetodestinationusing rsync. - Options:
opts.source: Source directory/file.opts.destination: Destination directory/file.opts.flags: Additional rsync flags (e.g.,--delete,--exclude).
- Description: Copy files from
-
brew-
Description: Installs packages using Homebrew.
-
Options:
opts.tap: Name of the tap to install the package from.opts.cask: Install as a cask instead of a formula.opts.flags: Additional flags to pass to brew commands (fallback for install/update).opts.install_flags: Additional flags to pass only tobrew install.opts.update_flags: Additional flags to pass only tobrew upgrade.
-
-
npm/pnpm/yarn- Description: Installs packages using npm/pnpm/yarn.
- Use
type: npmfornpm install,type: pnpmforpnpm install, andtype: yarnforyarn install.
- Use
- Options:
opts.flags: Additional flags to pass to commands (fallback for install/update).opts.install_flags: Additional flags to pass only during install.opts.update_flags: Additional flags to pass only during update.
- Description: Installs packages using npm/pnpm/yarn.
-
apt/apk- Description: Installs packages using apt install or apt add.
- Use
type: aptforapt install, andtype: apkforapk add.
- Use
- Options:
opts.flags: Additional flags to pass to commands (fallback for install/update).opts.install_flags: Additional flags to pass only during install.opts.update_flags: Additional flags to pass only during update.
- Description: Installs packages using apt install or apt add.
-
pacman/yay- Description: Installs packages using pacman or yay (Arch Linux).
- Use
type: pacmanfor official Arch repository packages. - Use
type: yayfor AUR (Arch User Repository) packages. - Both use
--noconfirmfor non-interactive installation.
- Use
- Options:
opts.needed: Skip reinstalling up-to-date packages (--neededflag).opts.flags: Additional flags to pass to commands (fallback for install/update).opts.install_flags: Additional flags to pass only during install.opts.update_flags: Additional flags to pass only during update.
- Description: Installs packages using pacman or yay (Arch Linux).
-
pipx- Description: Installs packages using pipx.
- Options:
opts.flags: Additional flags to pass to commands (fallback for install/update).opts.install_flags: Additional flags to pass only topipx install.opts.update_flags: Additional flags to pass only topipx upgrade.
-
docker-
Description: Pulls and runs Docker containers using
docker run. Also supports update checks by comparing image digests.- The image is pulled from the registry (e.g., Docker Hub or GHCR) and started with the provided options.
- If the container already exists, it will be started instead of run again.
- Updates are detected by comparing the image digest before and after a pull.
- The container is always run with
--restart always -d, unless overridden in a custom shell.
-
Required:
name: The full Docker image name, including tag (e.g.,ghcr.io/open-webui/open-webui:main).bin_name: The container name to assign to the running instance (used in install and update checks).
-
Options:
-
opts.flags: A string of flags to pass todocker run(e.g., ports, volumes, extra args). These are appended after the default flags and before the image name.-
Example:
opts: flags: > -p 3300:8080 -v data-volume:/app/data --add-host=host.docker.internal:host-gateway
-
-
opts.platform: Override the platform used when checking the image manifest for updates. Accepts a per-OS map with values inos/archformat (e.g.,linux/amd64).This is useful if you're running on a platform like
darwin/arm64, but want to compare digests for a different image target (e.g.,linux/amd64).-
Example:
opts: platform: macos: linux/amd64 linux: linux/amd64
-
-
opts.skip_if_unavailable: Whether to skip the installation/update if the Docker daemon is not running. Defaults to false (so it will fail the installer)
-
-
Installer Examples
All of these examples should be usable, but don't count on them being maintained. Why not look at the Recipes?
group
install:
- name: pyenv
type: group
tags: python
steps:
- name: pyenv
type: brew
platforms:
only: ['macos']
- name: pyenv
type: shell
platforms:
only: ['linux']
opts:
command: 'curl https://pyenv.run | bash'
Machine-specific installers
# Define friendly names for your machines (get IDs with `sofmani --machine-id`)
machine_aliases:
work-laptop: a1b2c3d4e5f67890
home-desktop: 5fa2a8e8193868df
home-server: fedcba0987654321
install:
# Only install on specific machines using aliases
- name: work-tools
type: group
machines:
only: ['work-laptop']
steps:
- name: slack
type: brew
opts:
cask: true
- name: zoom
type: brew
opts:
cask: true
# Install everywhere except the home server
- name: desktop-apps
type: group
machines:
except: ['home-server']
steps:
- name: firefox
type: brew
opts:
cask: true
# You can also use raw machine IDs directly
- name: special-tool
type: brew
machines:
only: ['a1b2c3d4e5f67890'] # Raw machine ID also works
manifest
install:
- name: lazygit
type: manifest
opts:
source: git@github.com:chenasraf/sofmani.git
path: docs/recipes/lazygit.yml
git
install:
- name: github/gitignore
type: git
opts:
destination: ~/.gitignore-templates
github-release
install:
- name: lazygit
type: github-release
opts:
repository: jesseduffield/lazygit
strategy: tar
destination: /usr/local/bin
download_filename: lazygit_{{ .Version }}_Linux_{{ .ArchAlias }}.tar.gz
github_token: $GITHUB_TOKEN # optional, for higher rate limits
shell
install:
- name: fnm
type: shell
tags: node
post_install: |
fnm install --lts
fnm use lts-latest
opts:
command: curl -fsSL https://fnm.vercel.app/install | bash
rsync
install:
- name: xdg-config
type: rsync
tags: config
opts:
source: ~/.dotfiles/.config
destination: ~/.config
brew
install:
- name: sofmani
type: brew
opts:
tap: chenasraf/tap
npm/pnpm/yarn
install:
- name: prettier
type: pnpm
tags: node
apt
install:
- name: pipx
type: apt
tags: python
platforms:
only: ['linux']
pacman/yay
install:
# Install from official Arch repositories
- name: neovim
type: pacman
bin_name: nvim
opts:
needed: true # Skip if already up-to-date
# Install from AUR using yay
- name: visual-studio-code-bin
type: yay
bin_name: code
docker
- name: ghcr.io/open-webui/open-webui:main
bin_name: open-webui
type: docker
opts:
flags: >
-p 3300:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data