Files
dotfiles/.claude/skills/sofmani/SKILL.md

7.8 KiB

name, description
name description
sofmani Add, edit, or manage sofmani installer entries in sofmani.yml. This skill should be used when the user wants to add software to their provisioning manifest, modify existing installer steps, create cross-platform install groups, or troubleshoot sofmani configuration. Triggers on requests involving sofmani.yml, adding packages/tools to the manifest, or provisioning setup.

Sofmani

Work with sofmani (Software Manifest) — a declarative provisioning tool that automates software installations via YAML config. The config file lives at ~/.dotfiles/.config/sofmani.yml.

Quick Reference

CLI Flags

Flag Purpose
-u / -U Enable/disable update checking
-d / -D Enable/disable debug mode
-s / -S Enable/disable summary
-f <filter> Filter installers (see below)
-m Show machine ID

Filter syntax: -f <name>, -f tag:<tag>, -f type:<type>. Negate with !: -f "!tag:system".

Template Variables

Available in shell commands and opts string fields:

Variable Value
{{ .Arch }} CPU architecture
{{ .ArchAlias }} Architecture alias (e.g. amd64)
{{ .OS }} Operating system
{{ .DeviceID }} Machine unique ID
{{ .DeviceIDAlias }} Friendly machine name from machine_aliases
{{ .Tag }} Release tag (github-release only)
{{ .Version }} Version without v prefix (github-release only)

Environment variables $DEVICE_ID and $DEVICE_ID_ALIAS are also injected into shell commands.

Installer Entry Reference

Every entry in the install array supports these fields:

Field Type Purpose
name string (required) Step identifier
type string (required) Installer type
tags string Space-separated tags for filtering
bin_name string Binary name if different from name
enabled bool/string Conditional execution (string = shell command)
platforms object only / except arrays: macos, linux, windows
machines object only / except arrays of machine alias names
check_installed string Shell command to verify installation
check_has_update string Shell command to check for updates
pre_install string Shell hook before install
post_install string Shell hook after install
pre_update string Shell hook before update
post_update string Shell hook after update
skip_summary bool/object Exclude from summary (true, or { install: true, update: true })
env_shell object Platform-specific shell override (e.g. { linux: /bin/bash })
opts object Type-specific options (see below)

Installer Types

brew

Homebrew package. The project defaults restrict brew to macOS only — no need to add platforms for brew entries.

- name: ripgrep
  type: brew

With tap:

- name: sofmani
  type: brew
  opts:
    tap: chenasraf/tap

opts: tap, cask (bool).

group

Sequence multiple steps. The primary pattern for cross-platform installs: brew on macOS + github-release or apt on Linux.

- name: lazygit
  type: group
  steps:
    - name: lazygit
      type: brew
    - name: lazygit
      type: github-release
      platforms:
        only: ['linux']
      opts:
        repository: jesseduffield/lazygit
        strategy: tar
        destination: ~/.local/bin
        download_filename: lazygit_{{ .Version }}_Linux_{{ .ArchAlias }}.tar.gz

shell

Execute arbitrary shell commands. The most flexible type.

- name: git-config
  type: shell
  check_installed: git config --global user.name > /dev/null 2>&1
  opts:
    command: |
      git config --global user.name "Name"
      git config --global user.email "email@example.com"
    update_command: <same or different command for updates>

opts: command (required), update_command.

git

Clone a git repository.

- name: my-plugin
  type: git
  opts:
    repository: https://github.com/user/repo.git
    destination: ~/.local/share/plugins/repo
    ref: main

opts: repository (required), destination (required), ref.

GitHub shorthand: repository: user/repo expands to https://github.com/user/repo.git.

github-release

Download a binary from GitHub releases.

- name: tool
  type: github-release
  opts:
    repository: user/tool
    destination: ~/.local/bin
    strategy: tar          # or: binary, zip
    download_filename: tool_{{ .Version }}_Linux_{{ .ArchAlias }}.tar.gz

opts: repository (required), destination (required), strategy (tar/binary/zip), download_filename (supports template vars including {{ .Version }}, {{ .Tag }}, {{ .Arch }}, {{ .ArchAlias }}).

manifest

Load an external sofmani config file (local or from a git repo).

- name: lazygit
  type: manifest
  opts:
    source: git@github.com/chenasraf/sofmani.git
    path: docs/recipes/lazygit.yml

opts: source, path.

apt

Debian/Ubuntu package manager.

- name: stow
  type: apt
  platforms:
    only: ['linux']

npm / pnpm / yarn

Node.js package managers. Install global packages.

- name: typescript
  type: pnpm
  opts:
    global: true

pipx

Python tool installer.

- name: black
  type: pipx

cargo

Rust package installer.

- name: ripgrep
  type: cargo

rsync

File synchronization.

- name: sync-config
  type: rsync
  opts:
    source: ./config/
    destination: ~/.config/app/

docker

Pull and optionally run containers.

- name: my-service
  type: docker
  opts:
    image: nginx:latest

Common Patterns

Cross-platform group (brew + github-release)

The standard pattern for CLI tools. Brew handles macOS, github-release handles Linux:

- name: tool-name
  type: group
  steps:
    - name: tool-name
      type: brew
    - name: tool-name
      type: github-release
      platforms:
        only: ['linux']
      opts:
        repository: owner/tool-name
        destination: ~/.local/bin
        strategy: tar
        download_filename: tool-name-linux-{{ .Arch }}.tar.gz

Cross-platform group (brew + apt)

For packages available in both package managers:

- name: stow
  type: group
  steps:
    - name: stow
      type: brew
    - name: stow
      type: apt
      platforms:
        only: ['linux']

Config installer with idempotency

Use check_installed and check_has_update for shell installers that manage config:

- name: tmux-config
  type: shell
  tags: config tmux
  enabled: test -f "$HOME/.config/tmux_{{ .DeviceIDAlias }}.yml"
  check_installed: test -f ~/.config/tmux_local.yml
  check_has_update: '! diff -q "$HOME/.config/tmux_{{ .DeviceIDAlias }}.yml" ~/.config/tmux_local.yml > /dev/null 2>&1'
  opts:
    command: cp "$HOME/.config/tmux_{{ .DeviceIDAlias }}.yml" ~/.config/tmux_local.yml
    update_command: cp "$HOME/.config/tmux_{{ .DeviceIDAlias }}.yml" ~/.config/tmux_local.yml

Machine-specific installer

Restrict to specific machines using aliases defined in machine_aliases:

- name: glab
  type: brew
  machines:
    only: ['planck']

Working with the Config File

  • The config file is at ~/.dotfiles/.config/sofmani.yml and symlinked to ~/.config/sofmani.yml via stow.
  • Read the full file before making changes to understand existing structure and conventions.
  • New entries should be placed in the appropriate category section (marked by comment headers).
  • Follow the existing indentation and style conventions in the file.
  • When adding a new tool, check if a similar entry already exists that can be extended.
  • For detailed installer type documentation, see references/installer-types.md.