aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/nix
diff options
context:
space:
mode:
Diffstat (limited to 'nix')
-rw-r--r--nix/README.md73
-rwxr-xr-xnix/bootstrap.sh39
-rw-r--r--nix/common.nix16
-rw-r--r--nix/host.nix4
-rw-r--r--nix/justfile89
-rw-r--r--nix/vm.nix139
6 files changed, 178 insertions, 182 deletions
diff --git a/nix/README.md b/nix/README.md
index 26699d0..123bf60 100644
--- a/nix/README.md
+++ b/nix/README.md
@@ -24,14 +24,12 @@ GitHub on first launch.
1. Installs Nix (Determinate Systems multi-user installer).
2. Clones this repo to `~/.local/share/dotfiles`.
-3. Runs `home-manager switch --flake .../nix#vm`, which:
- - Installs the CLI tool subset (see `common.nix` + `vm.nix`).
- - Symlinks `~/.config/{nvim,zellij,zsh,direnv,ghostty,git}` and
- `~/.ssh/config` at the cloned working tree via
- `mkOutOfStoreSymlink`, so `git pull` is enough to pick up config
- edits — no rebuild needed for config-only changes.
- - Sets `ZDOTDIR=$HOME/.config/zsh` so the shared zshrc/zprofile load.
-4. Appends the nix-store zsh to `/etc/shells` and `chsh`'s to it.
+3. Runs `home-manager switch --flake .../nix#vm`, which installs the
+ shared CLI tool subset (see `common.nix` + `vm.nix`).
+4. Writes a VM-role chezmoi config and runs `chezmoi apply`, deploying
+ the same user dotfiles model as the host while skipping host-only
+ `/etc` and Firefox hooks.
+5. Appends the nix-store zsh to `/etc/shells` and `chsh`'s to it.
## Updating after a dotfiles change
@@ -44,15 +42,25 @@ just update # pull + home-manager switch (handles everything)
Or piece-by-piece if you know which one you need:
```sh
-just pull # config-only changes (nvim/zellij/zsh/git/ssh): no rebuild needed
+just pull # fetch the latest checkout only
just switch # rebuild home-manager from the current checkout
+just apply # apply VM-role chezmoi dotfiles from the current checkout
```
-> `just update` runs `pull` then `switch`. The home-manager invocation
-> uses `--impure --flake '.#vm' -b backup`; the single-quotes around the
-> flake ref matter because our zsh enables `extendedglob`, which would
-> otherwise interpret `.#vm` as a glob pattern. On the host, swap
-> `#vm` → `#host`.
+> `just update` runs `pull`, `switch`, and `apply`. The home-manager
+> invocation uses `--impure --flake '.#vm' -b backup`; the single-quotes
+> around the flake ref matter because our zsh enables `extendedglob`,
+> which would otherwise interpret `.#vm` as a glob pattern. On the host,
+> swap `#vm` → `#host`.
+
+Existing VMs that predate the chezmoi migration should run once:
+
+```sh
+just migrate-chezmoi
+```
+
+This removes only safe old Home-Manager-managed symlinks before applying
+chezmoi.
## Adding a tool
@@ -97,14 +105,16 @@ One-time setup on the VM:
```sh
rm -f ~/.ssh/agent.sock ~/.config/git/allowed_signers
+just fix-gpg-agent
+gpg-connect-agent 'getinfo version' /bye
gpg --import /path/to/work-private-key.asc
gpg --edit-key 3298945F717C85F8 trust quit
gpg --list-secret-keys --with-keygrip 3298945F717C85F8
```
-The VM profile symlinks the repo-owned `gpg.conf`, `gpg-agent.conf`,
-and `sshcontrol` into `~/.gnupg`. The tracked git config already uses
-normal OpenPGP signing, so no
+Chezmoi deploys the repo-owned `gpg.conf`, `gpg-agent.conf`, and
+`sshcontrol` into `~/.gnupg`. The tracked git config already uses normal
+OpenPGP signing, so no
`~/.config/git/config.local` override is needed for SSH-format signing.
If `~/.config/git/config.local` only contains the old SSH-format
signing override, remove it too.
@@ -112,6 +122,8 @@ signing override, remove it too.
Verify on the VM:
```sh
+gpg-connect-agent 'getinfo version' /bye
+echo 'Hello world!' | gpg -s --armor -
ssh-add -L
git commit --allow-empty -m test
git log --show-signature -1
@@ -121,9 +133,9 @@ git log --show-signature -1
- **GPG / pass**: HM installs `gnupg` and `pass` but does _not_ import
any private key. On the VM, import the work key manually; repo-owned
- `gpg.conf`, `gpg-agent.conf`, and `sshcontrol` are symlinked by
- `vm.nix`. On the host, smartcard access via `pcscd` is configured in `host.nix`
- (`~/.gnupg/scdaemon.conf`).
+ `gpg.conf`, `gpg-agent.conf`, and `sshcontrol` are deployed by
+ chezmoi. On the host, smartcard access via `pcscd` is configured in
+ `host.nix` (`~/.gnupg/scdaemon.conf`).
- **Disk usage**: Nix store + nvim plugins consumes ~3-5 GB. Check
partition size first on the VM.
- **Network for first nvim launch**: `vim.pack.add` fetches plugins
@@ -165,19 +177,22 @@ podman run --rm docker.io/library/alpine echo hi
```
The VM home-manager profile installs `podman`, `crun`, `conmon`,
-`netavark`, `aardvark-dns`, `slirp4netns`, and `passt`, and writes
-sensible `~/.config/containers/{registries,storage,policy}.conf` files.
+`netavark`, `aardvark-dns`, `slirp4netns`, and `passt`. Chezmoi deploys
+role-aware `~/.config/containers/{registries,storage,policy}.conf`
+files.
## How it's wired
-`common.nix` uses `config.lib.file.mkOutOfStoreSymlink` so the symlinks
-point at the **live working tree** at `~/.local/share/dotfiles/...`,
-not at copies in `/nix/store`. This means:
+Home-Manager installs packages only. Chezmoi owns dotfiles on both the
+host and VM, keyed by `machineRole` in the chezmoi config:
+
+- `host`: normal user dotfiles plus host-only `/etc`, Firefox, and
+ Flatpak integration hooks.
+- `vm`: normal user dotfiles, skipping host-only `/etc` and Firefox
+ hooks.
-- Editing `dot_config/nvim/init.lua` in the cloned repo takes effect
- on the next `nvim` launch with no rebuild.
-- `home-manager switch` only needs to re-run when adding/removing a
- package or changing what's symlinked.
+`home-manager switch` only needs to re-run when the Nix profile changes.
+Config-only edits are picked up by `chezmoi apply`.
The zsh plugins (`zsh-syntax-highlighting`, etc.) live in
`$HOME/.nix-profile/share/`. The shared `dot_zshrc` prefers the
diff --git a/nix/bootstrap.sh b/nix/bootstrap.sh
index 86f82ca..58ab190 100755
--- a/nix/bootstrap.sh
+++ b/nix/bootstrap.sh
@@ -8,7 +8,8 @@
# 1. Install Nix (Determinate Systems installer, multi-user).
# 2. Clone (or fast-forward) the dotfiles repo to ~/.local/share/dotfiles.
# 3. Run `home-manager switch --flake .../nix#vm`.
-# 4. Add Nix-store zsh to /etc/shells and chsh the user.
+# 4. Initialize VM-role chezmoi config and apply dotfiles.
+# 5. Add Nix-store zsh to /etc/shells and chsh the user.
#
# Environment overrides:
# DOTFILES_REPO Git URL (default: https://github.com/ruifm/dotfiles)
@@ -64,7 +65,41 @@ nix --extra-experimental-features 'nix-command flakes' \
run home-manager/master -- \
switch --impure --flake "$DIR/nix#vm" -b backup
-# ── 4. chsh to nix-store zsh ─────────────────────────────────────────────────
+# ── 4. Chezmoi dotfiles ──────────────────────────────────────────────────────
+log "Writing VM chezmoi config and applying dotfiles…"
+CHEZMOI="$HOME/.nix-profile/bin/chezmoi"
+if [ ! -x "$CHEZMOI" ]; then
+ CHEZMOI=$(command -v chezmoi)
+fi
+CHEZMOI_MACHINE_ROLE=vm "$CHEZMOI" init -S "$DIR" --promptDefaults
+CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.toml"
+if ! grep -Eq '^[[:space:]]*machineRole[[:space:]]*=[[:space:]]*"vm"[[:space:]]*$' "$CONFIG"; then
+ err "$CONFIG does not set machineRole = \"vm\""
+ exit 1
+fi
+"$CHEZMOI" apply -S "$DIR" -v
+
+log "Restarting GnuPG through the Nix profile…"
+GPGCONF="$HOME/.nix-profile/bin/gpgconf"
+GPG_CONNECT_AGENT="$HOME/.nix-profile/bin/gpg-connect-agent"
+if command -v systemctl >/dev/null 2>&1; then
+ systemctl --user stop \
+ gpg-agent.service \
+ gpg-agent.socket \
+ gpg-agent-ssh.socket \
+ gpg-agent-extra.socket \
+ gpg-agent-browser.socket >/dev/null 2>&1 || true
+ systemctl --user mask \
+ gpg-agent.socket \
+ gpg-agent-ssh.socket \
+ gpg-agent-extra.socket \
+ gpg-agent-browser.socket >/dev/null 2>&1 || true
+fi
+"$GPGCONF" --kill all >/dev/null 2>&1 || true
+"$GPGCONF" --launch gpg-agent
+"$GPG_CONNECT_AGENT" 'getinfo version' /bye
+
+# ── 5. chsh to nix-store zsh ─────────────────────────────────────────────────
NIX_ZSH="$HOME/.nix-profile/bin/zsh"
if [ -x "$NIX_ZSH" ]; then
if ! grep -qxF "$NIX_ZSH" /etc/shells 2>/dev/null; then
diff --git a/nix/common.nix b/nix/common.nix
index f9a7042..7290395 100644
--- a/nix/common.nix
+++ b/nix/common.nix
@@ -1,12 +1,10 @@
{ config, pkgs, lib, dotfilesRoot, ... }:
-# Shared Home-Manager module: ONLY package installation. Config-file
-# deployment is *not* handled here — on the Arch host, chezmoi owns
-# every dotfile under $HOME; on the remote-dev VM, `vm.nix` carries
-# its own `xdg.configFile`/`home.activation` block since chezmoi isn't
-# installed there. Keeping this module deployment-agnostic prevents
-# home-manager from conflicting with chezmoi on the host (which would
-# otherwise materialize as `.backup` files on every `nix-switch`).
+# Shared Home-Manager module: ONLY package installation. Dotfile deployment is
+# owned by chezmoi on both the Arch host and the remote-dev VM. Keeping this
+# module deployment-agnostic prevents home-manager from conflicting with
+# chezmoi-owned files (which would otherwise materialize as `.backup` files on
+# every `nix-switch`).
#
# Policy: this profile carries leaf CLI tools, editor/AI-agent runtimes
# (node, uv), and build *orchestrators* (cmake, ninja, ccache, sccache).
@@ -47,6 +45,7 @@
choose
zoxide
just
+ chezmoi
# Viewers
bat
@@ -160,8 +159,7 @@
# The nix `podman` is wrapped to find these helpers via /nix/store
# paths, so we don't need a containers.conf for `helper_binaries_dir`.
# Per-user containers config (registries/storage/policy) lives under
- # chezmoi at `private_dot_config/containers/` and is symlinked on the
- # VM by `vm.nix`'s xdg.configFile block.
+ # chezmoi at `dot_config/containers/`.
podman
crun # OCI runtime (lighter than runc; default for rootless)
conmon # container monitor process
diff --git a/nix/host.nix b/nix/host.nix
index de68230..5a3d8a9 100644
--- a/nix/host.nix
+++ b/nix/host.nix
@@ -185,10 +185,6 @@ in
# firefox/user-overrides.js into the Flatpak profile.
arkenfox-userjs-profile
- # Dotfile manager. bootstrap.sh uses the pacman `just` only long enough
- # to run nix-switch; after that, this nix-profile copy is on PATH.
- chezmoi
-
# ── OCR ──────────────────────────────────────────────────────────────────
# Override merges eng + por language data into a single derivation,
# replacing three pacman packages (tesseract, tesseract-data-eng,
diff --git a/nix/justfile b/nix/justfile
index 19e4a9b..3368193 100644
--- a/nix/justfile
+++ b/nix/justfile
@@ -4,10 +4,10 @@
default:
@just --list
-# Pull latest dotfiles and rebuild Home-Manager profile
-update: pull switch
+# Pull latest dotfiles, rebuild Home-Manager profile, and apply dotfiles
+update: pull switch apply
-# Pull latest dotfiles only (config-only changes, no nix rebuild)
+# Pull latest dotfiles only
pull:
git -C {{ justfile_directory() }}/.. pull --ff-only
@@ -15,6 +15,89 @@ pull:
switch:
home-manager switch --impure --flake '{{ justfile_directory() }}#vm' -b backup
+# Apply VM dotfiles with chezmoi
+apply: _ensure-vm-chezmoi-config
+ #!/usr/bin/env sh
+ set -eu
+ src=$(cd "{{ justfile_directory() }}/.." && pwd -P)
+ chezmoi apply -S "$src" -v
+
+_ensure-vm-chezmoi-config:
+ #!/usr/bin/env sh
+ set -eu
+ src=$(cd "{{ justfile_directory() }}/.." && pwd -P)
+ CHEZMOI_MACHINE_ROLE=vm chezmoi init -S "$src" --promptDefaults
+ config="${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.toml"
+ if ! grep -Eq '^[[:space:]]*machineRole[[:space:]]*=[[:space:]]*"vm"[[:space:]]*$' "$config"; then
+ echo "error: $config does not set machineRole = \"vm\"" >&2
+ exit 1
+ fi
+
+# Restart GnuPG through the Nix profile, avoiding Ubuntu's older user agent
+fix-gpg-agent:
+ #!/usr/bin/env sh
+ set -eu
+ gpgconf_bin="$HOME/.nix-profile/bin/gpgconf"
+ gpg_connect_agent_bin="$HOME/.nix-profile/bin/gpg-connect-agent"
+ [ -x "$gpgconf_bin" ] || gpgconf_bin=$(command -v gpgconf)
+ [ -x "$gpg_connect_agent_bin" ] || gpg_connect_agent_bin=$(command -v gpg-connect-agent)
+ if command -v systemctl >/dev/null 2>&1; then
+ systemctl --user stop \
+ gpg-agent.service \
+ gpg-agent.socket \
+ gpg-agent-ssh.socket \
+ gpg-agent-extra.socket \
+ gpg-agent-browser.socket >/dev/null 2>&1 || true
+ systemctl --user mask \
+ gpg-agent.socket \
+ gpg-agent-ssh.socket \
+ gpg-agent-extra.socket \
+ gpg-agent-browser.socket >/dev/null 2>&1 || true
+ fi
+ "$gpgconf_bin" --kill all >/dev/null 2>&1 || true
+ "$gpgconf_bin" --launch gpg-agent
+ "$gpg_connect_agent_bin" 'getinfo version' /bye
+
+# One-time migration from the old VM Home-Manager symlink deployment to chezmoi
+migrate-chezmoi: pull switch fix-gpg-agent _cleanup-home-manager-dotfiles apply
+
+_cleanup-home-manager-dotfiles: _ensure-vm-chezmoi-config
+ #!/usr/bin/env bash
+ set -euo pipefail
+ src=$(cd "{{ justfile_directory() }}/.." && pwd -P)
+
+ remove_old_symlink() {
+ path=$1
+ [ -L "$path" ] || return 0
+ raw=$(readlink "$path")
+ resolved=$(readlink -f "$path" 2>/dev/null || true)
+ case "$raw" in
+ "$src"/*|/nix/store/*) rm -f "$path"; return 0 ;;
+ esac
+ case "$resolved" in
+ "$src"/*|/nix/store/*) rm -f "$path"; return 0 ;;
+ esac
+ printf 'refusing to remove unexpected symlink: %s -> %s\n' "$path" "$raw" >&2
+ exit 1
+ }
+
+ while IFS= read -r path; do
+ remove_old_symlink "$path"
+ done < <(chezmoi managed -S "$src" --include=files,symlinks --path-style=absolute)
+
+ # The old VM profile materialized ~/.ssh/config as a real 0600 file because
+ # OpenSSH rejects group-writable symlink targets. Chezmoi now owns it; only
+ # remove the old file when it still exactly matches the repo source.
+ ssh_config="$HOME/.ssh/config"
+ if [ -f "$ssh_config" ] && [ ! -L "$ssh_config" ]; then
+ if cmp -s "$ssh_config" "$src/private_dot_ssh/config"; then
+ rm -f "$ssh_config"
+ else
+ printf 'refusing to overwrite modified %s; merge it before migrating\n' "$ssh_config" >&2
+ exit 1
+ fi
+ fi
+
# Garbage-collect old home-manager generations and nix store
gc:
home-manager expire-generations '-7 days'
diff --git a/nix/vm.nix b/nix/vm.nix
index 4465732..39bf52d 100644
--- a/nix/vm.nix
+++ b/nix/vm.nix
@@ -1,14 +1,8 @@
-{ config, pkgs, lib, dotfilesRoot, ... }:
+{ ... }:
-# VM-only Home-Manager profile (Ubuntu 22.04 remote-dev box). Adds the
-# rootless podman stack, the editor/zellij/zsh/git config symlinks
-# back into the cloned dotfiles tree, and a minimal ~/.zshenv shim —
-# all of which the Arch host gets from chezmoi instead.
-
-let
- dotfiles = "${builtins.getEnv "HOME"}/.local/share/dotfiles";
- link = path: config.lib.file.mkOutOfStoreSymlink "${dotfiles}/${path}";
-in
+# VM-only Home-Manager profile (Ubuntu remote-dev box). This installs the
+# shared tool profile and VM session variables only; dotfile deployment is
+# owned by chezmoi, matching the Arch host.
{
imports = [ ./common.nix ];
@@ -26,129 +20,4 @@ in
# No extra packages — the rootless podman stack now lives in
# `common.nix` so the host and VM share the same nix-pinned versions.
home.packages = [ ];
-
- # ── Shared config symlinks ──────────────────────────────────────────────────
- # Live symlinks back into the cloned working tree so `git pull` is enough
- # to update configs — no `home-manager switch` required after every edit.
- # On the Arch host the same files are deployed by chezmoi; this block
- # exists because the VM doesn't run chezmoi.
- #
- # INVARIANT: every program that is both (a) installed by `nix/common.nix`
- # and (b) has a config tree under `dot_config/<name>/` MUST appear here.
- # Otherwise the VM silently uses the tool's defaults while the host runs
- # the tracked config — drift that's hard to spot. See
- # `.github/copilot-instructions.md` (§ Nix VM symlink invariant).
- xdg.configFile = {
- # Editor + multiplexer + terminal
- "nvim".source = link "dot_config/nvim";
- "zellij".source = link "dot_config/zellij";
- "ghostty".source = link "dot_config/ghostty"; # for terminfo refs only
-
- # Shells
- "zsh/.zshrc".source = link "dot_config/zsh/dot_zshrc";
- "zsh/.zprofile".source = link "dot_config/zsh/dot_zprofile";
- "direnv/direnvrc".source = link "dot_config/direnv/direnvrc";
-
- # Git
- "git/config".source = link "dot_config/git/config";
- "git/attributes".source = link "dot_config/git/attributes";
- "git/ignore".source = link "dot_config/git/ignore";
- # Git hooks: source filenames carry the chezmoi `executable_` attribute
- # prefix which only chezmoi strips. In nix-managed setups we use raw
- # symlinks, so map each hook to its stripped name explicitly. The
- # executable bit comes from the working-tree file mode (git resolves
- # the symlink).
- "git/hooks/pre-push".source = link "dot_config/git/hooks/executable_pre-push";
- "git/hooks/pre-commit".source = link "dot_config/git/hooks/executable_pre-commit";
- "git/hooks/commit-msg".source = link "dot_config/git/hooks/executable_commit-msg";
- "git/hooks/post-commit".source = link "dot_config/git/hooks/executable_post-commit";
- "git/hooks/_dispatch.sh".source = link "dot_config/git/hooks/_dispatch.sh";
-
- # Leaf CLI tools whose binary lives in nix/common.nix
- "bat/config".source = link "dot_config/bat/config";
- "lsd/config.yaml".source = link "dot_config/lsd/config.yaml";
- "yazi".source = link "dot_config/yazi";
- "ripgrep/ripgreprc".source = link "dot_config/ripgrep/ripgreprc";
- "fd/ignore".source = link "dot_config/fd/ignore";
- "wget/wgetrc".source = link "dot_config/wget/wgetrc";
- "npm/npmrc".source = link "dot_config/npm/npmrc";
- "ipython/profile_default/ipython_config.py".source =
- link "dot_config/ipython/profile_default/ipython_config.py";
-
- # Debug / build tooling
- "gdb/gdbinit".source = link "dot_config/gdb/gdbinit";
- "gdb/gdbearlyinit".source = link "dot_config/gdb/gdbearlyinit";
- "clangd/config.yaml".source = link "dot_config/clangd/config.yaml";
- "ccache/ccache.conf".source = link "dot_config/ccache/ccache.conf";
-
- # Code review (binary from common.nix)
- "tuicr/config.toml".source = link "dot_config/tuicr/config.toml";
-
- # Rootless podman config — registries.conf + policy.json are
- # chezmoi-owned (shared with the host); storage.conf stays inline
- # below because the VM needs the overlay driver (ext4 host) while
- # the Arch host uses btrfs.
- "containers/registries.conf".source = link "dot_config/containers/registries.conf";
- "containers/policy.json".source = link "dot_config/containers/policy.json";
- };
-
- # VM-only: overlay driver. (Host's btrfs storage.conf is chezmoi-owned
- # at dot_config/containers/storage.conf.)
- xdg.configFile."containers/storage.conf".text = ''
- [storage]
- # runroot/graphroot default to $XDG_RUNTIME_DIR/containers and
- # $XDG_DATA_HOME/containers/storage respectively for rootless — leave unset.
- driver = "overlay"
-
- [storage.options.overlay]
- # Kernel >=5.13 supports rootless overlay natively (VM is on 5.15),
- # so mount_program is left unset → uses the kernel driver directly
- # instead of fuse-overlayfs.
- '';
-
- # Claude-code looks under ~/.claude (NOT XDG). Skills live there.
- # Symlink the whole tuicr skill directory so SKILL.md and the wrapper
- # script (chezmoi `executable_` prefix preserved → see the dispatch
- # comment in SKILL.md) are picked up together.
- home.file.".claude/skills/tuicr/SKILL.md".source =
- link "dot_claude/skills/tuicr/SKILL.md";
- home.file.".claude/skills/tuicr/tuicr-wrapper.sh".source =
- link "dot_claude/skills/tuicr/executable_tuicr-wrapper.sh";
-
- # GnuPG config is repo-owned like on the host. Private key material stays in
- # ~/.gnupg/private-keys-v1.d and is never tracked.
- home.file.".gnupg/gpg.conf".source = link "private_dot_gnupg/gpg.conf";
- home.file.".gnupg/gpg-agent.conf".source =
- link "private_dot_gnupg/gpg-agent.conf";
- home.file.".gnupg/sshcontrol".source =
- link "private_dot_gnupg/sshcontrol";
-
- # ~/.ssh/config from the dotfiles tree (read-only); keys + known_hosts
- # stay machine-local. We can't symlink via home.file because
- # mkOutOfStoreSymlink exposes the working-tree perms (0664 under a
- # default umask 002) and OpenSSH refuses any group-writable ssh_config.
- # Materialize a real 0600 file via activation instead.
- home.activation.sshConfig = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
- run install -D -m 600 \
- "${dotfiles}/private_dot_ssh/config" "$HOME/.ssh/config"
- '';
-
- # GnuPG cares about the homedir mode; the linked config files themselves
- # contain no secrets and are repo-owned.
- home.activation.gnupgDirectory = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
- run install -d -m 700 "$HOME/.gnupg"
- run chmod 700 "$HOME/.gnupg"
- '';
-
- # ZDOTDIR redirect so login shells find ~/.config/zsh/.zprofile etc.
- # Also source HM's session-vars — HM normally drops these into
- # ~/.profile, but zsh login shells don't read .profile, and we don't
- # use programs.zsh.enable.
- home.file.".zshenv".text = ''
- if [ -r "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh" ]; then
- . "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"
- fi
- export ZDOTDIR="$HOME/.config/zsh"
- [[ -r "$ZDOTDIR/.zshenv" ]] && source "$ZDOTDIR/.zshenv"
- '';
}