@richardgill/gmail
AMy opinionated Nix config inspired by Omarchy's system choices and chenglab's configuration structure.
Install
agr install @richardgill/gmail --target claudeWrites 1 file into .claude/skills/, pinned to git-65872f50.
- .claude/skills/gmail/SKILL.md
Document
name: gmail description: Gmail via gws.
Gmail via gws
Use gws for Gmail operations.
When you need the official generated skill docs, create a temp directory under /tmp/, run gws generate-skills there, concatenate the generated Gmail skill docs into one file, then read that file:
tmpdir="$(mktemp -d /tmp/gws-gmail.XXXXXX)"
combined="$tmpdir/gws-gmail.md"
(
cd "$tmpdir"
gws generate-skills
shopt -s nullglob
: > "$combined"
for file in skills/gws-gmail*/SKILL.md; do
printf '\n\n%s\n\n' "--- $file ---" >> "$combined"
cat "$file" >> "$combined"
done
)
You only need to read this:
$tmpdir/gws-gmail.md
Repository README
Describes richardgill/nix as a whole, which may contain artifacts other than this one. Where this artifact had no useful description of its own, its summary was taken from here.
My opinionated Nix config inspired by Omarchy's system choices and chenglab's configuration structure.
Pragmatic Nix: Simple config with plain .conf and .json files. Uses .nix features when they provide clear benefits.
Dotfiles: flake/modules/home-manager/dot-files
Features
- Modern Nix flakes
- home-manager manages dotfiles
- Dotfiles are kept in plain
.confor.jsonwhere possible. Mustache for templating.
- Dotfiles are kept in plain
- LUKS disk encryption:
- remote unlock via SSH
- Secure Boot with TPM2 auto-unlock of LUKS
- disko: declarative disk partitioning with btrfs
- impermanence with btrfs
- Filesystem wipes on reboot, keeping only folders that you explicitly persist in your config
- Detect files which need persistence with
just find-impermanent
- Full installation happens entirely inside the NixOS ISO (works on machines with small memory)
- sops-nix manages secrets
- Btrfs snapshots for backup and recovery of user data
.justfilecontains useful aliases for frequentnixcommands
Folder structure
Configuration works simply by importing .nix files. There is minimal Nix conditionals / logic - just import files with features you want on your machine.
Configuration is split onto folders:
headless/- CLI-only, server environmentsgraphical/- Desktop with GUIoptional/- Opt-in features requiring explicit import the machine'sconfiguration.nix.shared/- Cross-platform configs (works on both NixOS and macOS)
├── .justfile # Run `just --list` to see the commands
├── flake/
│ ├── flake.nix # Entry point - defines all machines in nixosConfigurations
│ ├── flake.lock
│ ├── vars.nix # Shared variables (username, etc.)
│ ├── treefmt.nix
│ ├── machines/ # Per-machine configurations
│ ├── modules/ # System + home-manager modules
│ ├── overlays/
│ ├── assets/
│ ├── secrets/ # Encrypted secrets (via sops-nix)
│ └── utils/ # Utilities
├── out-of-store-config/ # Mutable sources for mkOutOfStoreSymlink
├── built/ # Template outputs (kept out of the flake root)
├── ts-utils/ # JS helpers (bundle copied into flake/template-builder)
└── scripts/ # Helper scripts (install, publish, etc.)
Getting started
Check flake/vars.nix and update your username, public keys etc.
Installation - NixOS (Linux)
▶️ Video walkthrough of the installation process
Boot Nix ISO and enable SSH
Download the minimal (or graphical) ISO for your platform from the official NixOS website.
Boot from the ISO, then set a password to enable SSH:
passwd
Find the IP address:
ip addr show
On your local machine where you've checked out this repo, set the ISO IP and confirm SSH access:
export ISO_IP="192.168.1.XXX"
ssh nixos@$ISO_IP
Create a new Machine
Each NixOS machine has the following structure:
flake/machines/<machine-name>/
├── configuration.nix # Machine config
└── hardware-configuration.nix # Auto-generated hardware config
Create hardware-configuration.nix
Every machine needs a flake/machines/<machine-name>/hardware-configuration.nix
You can generate hardware configuration directly from the live ISO:
ssh nixos@$ISO_IP "sudo nixos-generate-config --no-filesystems && cat /etc/nixos/hardware-configuration.nix"
Copy the configuration to: flake/machines/<machine-name>/hardware-configuration.nix on your local machine.
Commit and push it to git.
Create configuration.nix
-
Copy an existing configuration as a starting point:
- Example: um790/configuration.nix
-
Import the disko module with your disk configuration:
(import ../../../../modules/system/nixos/headless/disko.nix { device = "/dev/nvme0n1"; # Your primary disk device (find with: lsblk) resumeOffset = "533760"; # For hibernate support (get with: btrfs inspect-internal map-swapfile -r /.swapvol/swapfile) swapSize = "16G"; # Swap file size (see https://itsfoss.com/swap-size) isSsd = true; # Enable SSD optimizations })Finding your device name:
ssh nixos@$ISO_IP "lsblk" # List all block devices from the NixOS ISO # Common device names: /dev/nvme0n1 (NVMe SSD), /dev/sda (SATA/SCSI), /dev/vda (VM) -
Import a base module depending on your machine type:
flake/modules/system/nixos/headless— for server machinesflake/modules/system/nixos/graphical— for GUI machines (includes headless features)
-
Add optional features as needed:
- Example:
flake/modules/system/nixos/headless/optional/thunderbolt.nix
- Example:
Install
The install happens directly from the live ISO. It does not require a large amount of RAM to work.
During the install you'll be prompted to set a password for your user and for LUKS encryption:
# Using public repository without token (if already authenticated)
scp scripts/clone-and-install.sh nixos@$ISO_IP:/tmp/ && \
ssh nixos@$ISO_IP "/tmp/clone-and-install.sh richardgill/nix"
# Using private repository with github token
scp scripts/clone-and-install.sh nixos@$ISO_IP:/tmp/ && \
ssh nixos@$ISO_IP "/tmp/clone-and-install.sh richardgill/nix-private $(gh auth token)"
macOS
On macOS, first install the Determinate Systems Nix installer:
Then install the configuration:
nix-shell -p git gh just
gh auth login
gh repo clone nix-private
cd nix-private
just mac-install
Place your sops key in ~/.config/sops/age/keys.txt (retrieve from 1Password).
Rebuild with just switch.
Additional macOS setup:
- Go to System Settings → Keyboard → Keyboard Shortcuts and disable conflicting shortcuts
- If Homebrew casks are blocked, go to System Settings → Privacy & Security and click "Open Anyway"
Useful commands
Install just to access the simple aliases below.
Locally deploy changes
just switch
Setup LUKS
By default you can unlock LUKS locally
Remote unlock over SSH
ssh root@<machine-ip> -p 2222
You'll be prompted to enter the LUKS passphrase. The machine will continue booting and you can SSH normally:
ssh username@<machine-ip>
Configuration: remote-unlock.nix
LUKS auto unlock with Secure Boot + TPM2
Import flake/modules/system/nixos/headless/optional/secure-boot.nix in your machine's configuration.nix, then follow the setup instructions in that file.
Impermanence
This configuration uses btrfs with impermanence, where the root filesystem is reset on every boot. Only explicitly declared files and directories in /persistent survive reboots.
When adding new persistence directories/files, they need to be added in flake/modules/system/nixos/headless/impermanence.nix (for actual persistence)
Find impermanent files
Find files that have been written in ephemeral storage but aren't in your impermanence config:
just find-impermanent
Switching fails
If switching to latest version fails with "Path X already exists", move conflicting files to persistence first:
sudo mkdir -p /persistent/home/$USER/<folder>
sudo mv /home/$USER/<file> /persistent/home/$USER/<folder>/
sudo chown -R $USER:users /persistent/home/$USER/<folder>
just build
Directly Editable Configs (Out-of-Store Symlinks)
Some configs (like nvim) are symlinked directly to the repo rather than the Nix store, so edits take effect immediately without rebuilding.
To make a config directly editable, use mkOutOfStoreSymlink in flake/modules/home-manager/shared/headless/dot-files.nix:
".config/nvim".source =
config.lib.file.mkOutOfStoreSymlink "${homeDir}/code/nix-private/out-of-store-config/nvim";
For directories where only some files need to be mutable, use the sourceDirectory helper with outOfStoreSymlinks:
(sourceDirectory {
target = ".config/example";
source = ../../dot-files/example;
outOfStoreSymlinks = [ "mutable-file.json" ];
})
Acknowledgments
- eh8/chenglab - Primary inspiration for this configuration structure
- Omarchy - Opinionated Linux setup inspiration
- dbeley/nixos-config - Btrfs impermanence implementation
- Misterio77/nix-starter-configs - Initial starter configuration
- Great beginner friendly introduction to NixOS and flakes
Trustgrade A
- passBody integrity
Whether the stored document is plausibly the kind of file the artifact declares, rather than something fetched by mistake.
- passType matchnot applicable to this artifact type
Whether the artifact is really the kind of thing its metadata claims it is.
- passFreshness
How long since the source repository was last pushed to.
- passPrompt injection
Scans the artifact's own text for instructions aimed at your agent rather than at you.
- passLicense
Whether the source repository declares an SPDX license permissive enough to redistribute.
How the grade is calculated
Each check contributes 0 points when it passes, 1 when it warns, and 2 when it fails. The total maps to a letter:
- Aevery check passed
- Bone warning
- Ctwo warnings
- Dprompt injection or body integrity failed, or three warnings
- Fone of those failed, and something else is wrong
These are automated hygiene checks, not a security audit, and not a dependency or vulnerability scan. A grade of A means nothing was flagged — not that the artifact is safe.
Versions
git-65872f50aacd2026-07-31