Registering the first Mac surfaced problems that would have hit every future one, not just this machine: metapac keys off a raw gethostname(), which on macOS carries the mDNS ".local" suffix, while the registry is keyed by chezmoi's .chezmoi.hostname, which stops at the first dot. A bare key never matched and metapac refused to run at all. config.toml.tmpl now emits each host twice, bare and ".local", so nothing in the registry has to declare which machines are Macs; the spare key is inert elsewhere. chezmoi was rewriting ~/Library from 0700 to 0755 on every apply, loosening a directory macOS deliberately closes. Both levels now carry the private_ prefix. dot_gitconfig.tmpl would have destroyed real config on adoption: the git-lfs filters, seven aliases, diff.noprefix, rerere and the gh credential helper. All folded in. The lfs block and the GitHub helper are lookPath-gated like the signing block -- lfs filters run on every checkout and abort wholesale when the binary is missing, so asserting them unconditionally breaks a minimal box rather than degrading. gh's path comes from lookPath, not a hardcoded /opt/homebrew/bin/gh. Laugh-Tale takes common + a new darwin group, the macOS counterpart to archlinux.toml, holding only the tooling a backend needs. Its baseline captures 325 packages, 24 taps and 21 App Store apps -- without it `metapac clean` would offer to remove every one of them. Verified on Laugh-Tale: chezmoi status clean after apply, ~/Library still 0700, `metapac unmanaged` reports nothing, `metapac sync` is a no-op, and the status line renders correctly under macOS bash 3.2. Shared groups are still arch-only, so this host draws nothing from common yet; that gap is documented, not closed. Claude-Session: https://claude.ai/code/session_01BvpSVPsLrUK4N53LVTofR8
3.7 KiB
Git
Signing uses SSH, not GPG
1Password has no GPG agent and ships only op-ssh-sign, so SSH signing is the
only thing it can actually do. Git has supported it since 2.34, and
git.nakama.town (Forgejo 14) verifies it, as do GitHub, GitLab and Bitbucket.
The private key never leaves 1Password.
Storing a GPG key in 1Password as a Document is possible, but 1Password cannot
serve it to gpg — the key would have to be imported into ~/.gnupg on every
machine, which is exactly what this avoids.
Only the public half is committed, in .chezmoi.toml.tmpl under [data.user].
It feeds both the gitconfig and allowed_signers, so rotating the key is a
one-line change.
The signing block is capability-gated
dot_gitconfig.tmpl emits it only where the signer binary exists —
/opt/1Password/op-ssh-sign on Linux, /Applications/1Password.app/Contents/ MacOS/op-ssh-sign on macOS — checked with stat at apply time. A machine with
only the 1Password CLI gets a working git with signing off, rather than one that
fails on every commit. No per-host declaration to keep in sync.
allowed_signers
~/.config/git/allowed_signers is managed so git log --show-signature can
verify our own commits locally. Without it signing works but every signature
reads as an unknown key.
Registering the key with a forge
Adding the key to Forgejo or GitHub requires signing a challenge token with it. The obvious command from their UI assumes a private key on disk, which does not exist here; the key has to come from the agent instead. In fish:
set -l sock $HOME/.1password/agent.sock
env SSH_AUTH_SOCK=$sock ssh-add -L | grep 'Git Signing Key' > /tmp/sig.pub
echo -n 'TOKEN' | env SSH_AUTH_SOCK=$sock ssh-keygen -Y sign -n git.nakama.town -f /tmp/sig.pub
env is required because fish has no VAR=value cmd form, and SSH_AUTH_SOCK
is not set anywhere. The grep matters — the agent holds more than one key, and
an auth key will fail to sign. Change -n to match the host asking.
The key must be added as a signing key, separately from any auth key.
Credentials
git-credential-op answers credential queries from 1Password at auth time, so no
token is ever written to disk. It is scoped per host via
credential.<url>.helper, and reads whatever GIT_CREDENTIAL_OP_REF points at —
the script itself never sees a URL.
Other capability gates
Two more blocks follow the same rule as the signing block — emitted only where
the binary exists, checked with lookPath at apply time.
filter "lfs" is the dangerous one. Those filters are declared per-repository
work that git runs on every checkout, so asserting them on a machine without
git-lfs breaks checkouts wholesale rather than degrading. Gating it means the
same gitconfig is safe on a minimal remote box.
The GitHub credential helper is emitted with gh's absolute path from
lookPath, not a hardcoded /opt/homebrew/bin/gh, so the same template serves
Homebrew on Apple silicon, Homebrew on Intel and a distro package. The empty
helper = line before it is deliberate: it resets any helper inherited from the
system config, so the stack cannot silently fall back to a stale keychain entry.
Aliases
br |
branch |
cane |
commit --amend --no-edit |
co |
checkout |
d |
diff |
fp |
fetch all remotes with prune, then pull --ff-only |
last |
log -1 HEAD |
lo |
log --oneline -n 10 |
pr |
pull --rebase |
s |
status |
fp refuses to merge or rebase a diverged branch, matching dotfiles update.
Work identity
When the work laptop arrives, its identity belongs in git's own conditional include, not a new registry field:
[includeIf "gitdir:~/work/"]
path = ~/.config/git/config.work