# Zero-conflict upstream pulls Goal: `git pull --ff-only` on the Hermes clone always succeeds. No conflicts, no rebases, no `--force-with-lease`. ## The rule **Never edit upstream files.** Put your customisations in directories that don't exist upstream: | Want to add… | Put it in… | Why | |---|---|---| | A dashboard plugin | `~/.hermes/plugins/<name>/` | User-plugins dir; not part of Hermes repo at all | | A skill | `~/.hermes/skills/<name>/` | Same | | A hook | `~/.hermes/hooks/<name>/` | Same | | Env vars | `~/.hermes/.env` | Already outside the repo | The only thing that lives **inside** `/Users/atem/sites/hermes-agent` is upstream code. Everything else lives in `~/.hermes/`. ## Setup commands ```bash # 1. Pristine main branch — your only commit policy is "never" cd /Users/atem/sites/hermes-agent git config pull.ff only # rejects ambiguous pulls # 2. Local-only ignores so noise files don't show up as untracked cat >> .git/info/exclude <<EOF .claude/ web/package-lock.json EOF # 3. Routine pull (no branch dance needed) git pull --ff-only ``` ## What the alternative costs If you instead modify Hermes files directly on a `local/atem` branch: - Every `git pull` becomes `git rebase main` → conflict odds rise - `pyproject.toml`, `setup.py`, anything upstream churns becomes a recurring fight - You can't easily archive your customisations later ## What this unlocks - **One-line update**: `git pull --ff-only` works forever. - **Plugins are portable.** Each `~/.hermes/plugins/<name>/` is its own git repo → can be shared, forked, archived independently. - **Onboarding is a clone command.** A fresh machine: clone Hermes, clone plugins into `~/.hermes/plugins/`, done. ## When this rule breaks down If you genuinely need to patch Hermes core (a bug, a feature toggle), then either: 1. PR upstream and wait 2. Maintain a *minimal* `local/patches` branch with `git rebase main` discipline But the bar should be high. 95% of customisations belong in `~/.hermes/plugins/` or `~/.hermes/skills/`, not in Hermes itself.
← All notes