Skip to content

santhoshtr/hm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

home-maker (hm)

A single Makefile that installs and upgrades every tool on your dev machine — CLI utilities, language toolchains, desktop apps — grouped by purpose, with a fuzzy-search frontend to run anything with a keystroke.

Works with apt, cargo, uv, go, and npm. Adding a package is one line.

Requirements

  • Linux (Debian/Ubuntu — adapt APT_INSTALL for other distros)
  • make, bash, fzf
  • The package managers you want to use (e.g. cargo for Rust tools, uv for Python tools)

Usage

make ripgrep       # install a single package
make cli           # install a group
make dev           # install all dev tools
make all           # install everything
make clean         # purge package manager caches
./hm.sh            # interactive fuzzy installer

Adding a package

Open the relevant .mk file and append to the right list:

# dev/python.mk
UV += ruff black isort my-new-tool

That's it. The Makefile generates a my-new-tool target automatically. make my-new-tool works, and it appears in hm the next time you run it.

Pin a version

UV += black@24.2.0
GO += golangci-lint@v1.55.0

Rename the target

If the Make target name differs from what the package manager expects, add a PKG_ override:

CARGO += fd
PKG_fd := fd-find

Now make fd installs the fd-find package.

Custom install scripts

For tools not in any package manager — curl scripts, tarballs, local builds — add a hand-written .PHONY target:

.PHONY: my-tool
my-tool:
	@echo "installing/upgrading $@..."
	@curl -fsSL https://example.com/my-tool -o /usr/local/bin/my-tool
	@chmod +x /usr/local/bin/my-tool

See desktop/apps.mk for an example.

hm — interactive installer

hm.sh is a fuzzy-search frontend. It discovers every target from the Makefiles and presents them in fzf. Tab selects multiple items, Enter installs them. The preview pane shows exactly what will run.

Add it to your PATH:

ln -s "$(pwd)/hm.sh" ~/bin/hm

The list is derived live from make -pn, so every package defined in any .mk file appears automatically. Nothing to keep in sync manually.

Structure

.
├── Makefile           # target generators, group targets, meta-targets
├── hm.sh              # interactive fzf installer
├── dev/
│   ├── cli.mk         # ripgrep, jq, bat, fzf, htop, tmux, eza, zoxide, fd
│   ├── python.mk      # uv (bootstrap) + ruff, black, isort, pyright
│   ├── node.mk        # nodejs/npm + eslint, prettier, typescript
│   ├── go.mk          # gopls, golangci-lint
│   ├── rust.mk        # cargo-cache, cargo-edit
│   └── lsp.mk         # shellcheck, shfmt, stylua, bash-language-server, yaml-language-server
└── desktop/
    └── apps.mk        # example custom target (alacritty)

How it works

Detailed blogpost: https://thottingal.in/blog/2026/03/29/home-maker/

Each .mk file appends packages to one of five lists: APT, CARGO, UV, GO, NPM. The Makefile expands each list into individual .PHONY targets using $(foreach ...) and a gen-* macro per manager. Each macro generates a target that runs the right install command with optional version pinning.

Group targets (cli, python, etc.) depend on their member packages. Meta-targets (dev, desktop, all) depend on groups. make all installs everything. make clean purges caches.

hm.sh runs make -pn, filters out group and meta targets, and feeds the remainder to fzf.

Why not Nix, Ansible, or similar?

Nix solves a different problem — reproducible, hermetic, declarative environments. That power comes with a parallel package universe, a functional language most developers don't already know, multi-gigabyte closures, and a learning curve that takes weeks before it feels productive.

Ansible is designed for fleet management — applying configuration to dozens of remote machines idempotently. A single developer laptop is not a fleet.

This system uses two things every Linux developer already knows: make and shell. The entire mechanism is visible in plain text in files you own. There is no daemon, no hidden state, no lock-in.

The tradeoffs are honest: installs are not hermetic, there is no rollback, and reproducibility depends on upstream package managers staying stable. For a personal development machine those are acceptable costs in exchange for a system that is transparent, fast to modify, and requires zero framework knowledge to operate.

Note: The packages in this repo are for examples. They are not the packages I configured.

About

home-maker: A single Makefile that installs and upgrades every tool on your dev machine — CLI utilities, language toolchains, desktop apps — grouped by purpose, with a fuzzy-search frontend to run anything with a keystroke.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors