Fork channel

Create a new channel as a copy of main.

Rename channel

Rename main to:

Delete channel

Delete main? This cannot be undone.

mode name
-rw-r--r-- README.md
-rw-r--r-- global.ml
README

Global macOS env, the Elpe way — pinned, no drift

An emacs (git, ripgrep, …) available in every terminal on your Mac, installed by Elpe from pinned Homebrew bottles — without a mutable global profile.

This is the “global env” people actually want on a work Mac, minus the thing that makes nix-env / ~/.nix-profile (and brew install one-at-a-time) age badly: there is no mutable state that accretes. The whole environment is the single declarative manifest global.ml. It is re-derived atomically from the pinned closure every time a shell starts, so it can’t drift.

Setup

  1. Put your toolbox in ~/.config/elpe/global.ml (copy global.ml, edit the formulae list).

  2. Add one line to ~/.zshrc:

    eval "$(ELPE_TARGET_OS=darwin ELPE_TARGET_ARCH=aarch64 \
            elpe shell --export ~/.config/elpe/global.ml)"
    
  3. Open a terminal. emacs, git, rg are on PATH — resolved from the content-addressed store via baked @rpath, so they just run.

To change your global set: edit the manifest, open a new terminal (or source ~/.zshrc). No install, no uninstall, no generations.

Why this doesn’t drift (and nix-env/brew do)

nix-env -i foo / brew install foo mutate a global profile package-by-package: generations accrete, PATH order depends on install history, cleanup is a chore. Here the global env is one file. elpe shell --export prints the export lines derived from that file’s pinned closure; you eval them. Editing the file and re-sourcing fully replaces the env — nothing is left behind.

Global vs per-project — you can have both

A single global env cannot give each project its own conflicting versions (project A wants node 18, project B node 22). That’s the real, irreducible trade-off — and it’s what the per-project layer solves: a repo’s .envrc (eval "$(elpe shell --export)" via direnv) prepends its pinned-divergent tools in front of this global PATH when you cd in, and drops back to the global set when you leave. Both layers are derived, not installed, so they compose without fighting: global for ambient tools, per-project for the ones that must diverge.