Skip to Content
DocumentationDocumentationCLI ReferenceOverview

CLI Reference

Every hams command fits the same shape:

hams [global-flags] <command> [args] [--hams-flags] [-- <passthrough>]

Three rules cover most confusion:

  • Global flags sit between hams and the command name. Put them anywhere else and they stop being global.
  • --hams- flags belong to hams. They never reach the underlying tool.
  • Anything after -- is handed straight to the underlying tool, untouched.

Commands by category

Core commands

CommandWhat it does
hams applyReconcile your machine with the Hamsfiles (install/remove/update)
hams refreshRe-scan machine reality and update .state/. Doesn’t touch anything else
hams listList everything hams is managing
hams configRead/write hams’s own config
hams storeManage the store repo (init, clone, push, pull)
hams self-upgradeUpgrade the hams binary

Provider commands

Provider commands all follow hams <provider> <verb> [args]. The verbs map to whatever the underlying tool exposes:

hams brew install htop hams pnpm add serve hams npm install --global prettier hams brew remove ripgrep hams brew list hams brew enrich htop

The verb rulebook lives in Provider Commands. Per-provider specifics live in the Providers chapter.

Global flags

FlagTypeDefaultWhat it does
--debugboolfalseTurn on debug logging (great for figuring out what a provider is actually doing)
--dry-runboolfalsePrint the plan, don’t do the work
--jsonboolfalseMachine-readable output, for scripts and AI agents
--no-colorboolfalseKill ANSI colors (for file redirects, plain terminals)
--config=<path>string~/.config/hams/hams.config.yamlUse a different config file
--store=<path>stringfrom configOverride the store directory
--profile=<tag>stringfrom configSwitch profile for this run
--helpboolfalsePrint help
--versionboolfalsePrint version info

Full details in Global Flags.

Exit codes

CodeMeaning
0Success
1Generic error
2Bad usage (wrong flags, missing args)
3Lock conflict — another hams process is already running
4Partial failure — some resources made it, some didn’t
10Needed sudo, didn’t get it
11–19Provider-specific errors
126Command not executable (POSIX)
127Command not found (POSIX)

Errors that scripts and agents can read

Every error is structured output by design. Plain mode looks like this:

ERROR LOCK_CONFLICT: Another hams session is running. PID: 42567 command: apply started: 20260412T143022 Suggestions: - Wait for the existing session to complete - Run: kill 42567 (if the process is stuck)

With --json:

{ "code": "LOCK_CONFLICT", "message": "Another hams session is running. PID: 42567, command: apply, started: 20260412T143022.", "suggestions": [ "Wait for the existing session to complete", "kill 42567" ] }

The --hams- prefix is how you pass hams-specific flags in the same command as flags for the wrapped tool. Example: hams brew install htop --hams-tag=cli records htop tagged cli, while brew has no idea that flag ever existed.

--hams- flags at a glance

FlagWhat it does
--hams-tag=<tags>Attach tags to the resource. Comma-separated
--hams-intro=<text>One-line description saved into the Hamsfile
--hams-localWrite to <Provider>.hams.local.yaml (gitignored) instead of the main Hamsfile
# Install ripgrep tagged 'search,cli' with a description hams brew install ripgrep --hams-tag=search,cli --hams-intro="Fast recursive grep alternative" # Install a tool that's only for this machine, not the shared store hams brew install zoom --hams-local
Last updated on