Skip to Content
DocumentationDocumentationSchema Reference

Schema Reference

hams reads and writes three kinds of YAML files. All of them round-trip through the parser with comments intact — which matters, because Hamsfiles tend to collect useful “why did I install this” notes over time.

Global config

Lives at ~/.config/hams/hams.config.yaml:

profile_tag: macOS machine_id: MacbookProM5X store_repo: zthxxx/hams-store store_path: ~/.local/share/hams/repo/zthxxx/hams-store llm_cli: claude provider_priority: - homebrew - apt - pnpm - npm - bash

This file tells hams who this machine is, which profile to use, where the store lives, and the order in which providers run during apply.

Hamsfile

Hamsfiles are split by provider, one file per provider. The general shape is: a header that names the schema and provider, and a groups section that holds resources organised under your own tags.

Package-style (Homebrew, pnpm, npm, and friends)

schema_version: 1 provider: Homebrew groups: - tag: terminal-tool items: - app: lazygit intro: Simple terminal UI for git commands. - app: htop intro: Improved top (interactive process viewer).

Field-by-field:

  • app — the package name, exactly as you’d type it in the native CLI
  • intro — a one-line reminder to your future self
  • tags — optional, for filtering and grouping

Key-value style (defaults, git-config)

Each entry is a single setting:

configs: - urn: "urn:hams:defaults:com.apple.dock.autohide" args: domain: com.apple.dock key: autohide type: bool value: "true" preview-cmd: "defaults write com.apple.dock autohide -bool true" check: "defaults read com.apple.dock autohide"
  • urn — hams’s internal unique ID. Make it readable
  • args — whatever the provider needs (domain, key, value, type)
  • preview-cmd — what gets printed in a dry-run (optional)
  • check — the idempotency probe

Bash-style (bash, ansible)

The core of this type is a run/check pair: run is what to do, check is how to know it’s already done.

setup: - urn: "urn:hams:bash:init-zsh" step: Install ZSH theme run: "curl -sSL .../installer.sh | bash" check: "test -f ~/.oh-my-zsh/custom/themes/jovial.zsh-theme"

Check exits 0 and hams skips. Anything else and hams runs run.

State file

Lives at <store>/.state/<machine-id>/<Provider>.state.yaml:

schema_version: 2 provider: homebrew machine_id: MacbookProM5X last_apply_session: "20260413T100000" resources: htop: state: ok version: "3.3.0" first_install_at: "20260413T100000" updated_at: "20260413T100000"

The first_install_at timestamp is set once on the resource’s very first install and is immutable thereafter — re-install, upgrade, removal, and re-install-after-remove never change it. updated_at bumps on every transition. When a resource is removed, hams adds a removed_at field (and clears it again on the next install). Legacy schema_version: 1 files with the old install_at field are migrated forward to first_install_at automatically on the next read.

State files capture what’s actually true on this machine right now: is the resource installed, at what version, as of when. .state/ is gitignored by default — it’s a local fact, not something you share between machines.

Key bits:

  • last_apply_session — timestamp of the most recent successful apply for this provider
  • resources — keyed by resource name. Each one tracks state (ok / missing / outdated / failed), version, and install timestamp

File suffixes worth knowing

SuffixMeaning
.hams.yamlThe main Hamsfile. Checked into git
.hams.local.yamlMachine-specific overrides. Gitignored by default. Good for secrets and personal tools
.state.yamlState file. Gitignored
hams.config.yamlGlobal / project-level config
hams.config.local.yamlLocal overrides. Gitignored

If a provider has both .hams.yaml and .hams.local.yaml, hams merges them at apply time. The local entries won’t leak to your store repo, but they’ll still be installed on this machine.

Last updated on