Repo-scoped instructions for anyone automating or editing this configuration. Global guardrails still live in
opencode/AGENTS.md.Stretch goal: keep this file ~150 lines so it is readable end-to-end during a run.
- This repository is the single source of truth for macOS (nix-darwin), NixOS, and standalone Home Manager environments.
- Everything is orchestrated through the flake in
nix/; resist ad-hoc OS/package changes. - Secrets are delivered via
sops-nix+ thesecretsflake input—never open decrypted payloads, only reference the managed paths.
- Run
bash init.shonce after cloning; it links~/.dotfiles, installs Nix if needed, then performs the appropriate rebuild (darwin-rebuild,nixos-rebuild, orhome-manager switch). - Direnv is configured via
direnv/direnvrcanddirenv.toml; allow it so devshells inject env vars and MCP tokens automatically. - MCP servers (filesystem, nixos, context7, etc.) are configured in
nix/modules/home/mcp; prefer using the provided MCP tasks + skills whenever possible.
- Full validation:
nix flake check ./nix— builds all outputs (darwin, nixos, home-manager) and runs any defined checks. - macOS rebuild:
sudo darwin-rebuild switch --flake ./nix(automatically manages Homebrew throughnix-homebrew). - NixOS rebuild:
sudo nixos-rebuild switch --flake ./nix(pulls in shared + host-specific modules). - Standalone Home Manager:
home-manager switch --flake ./nix#<user>@<host>; default attr ischris@full-tuxedofor the Linux HM-only case. - Single target build ("single test"): use
nix build ./nix#darwinConfigurations.logic.system(or another attribute like.#nixosConfigurations.penguin-tuxedo.config.system.build.toplevel) to isolate one output instead of running every check. - Format Nix:
nix fmt ./nix(Alejandra via flake). For single files:alejandra path/to/file.nixif available. - Lua formatting:
cd neovim && stylua .(configs expect 2 spaces / 120 cols; formatting on save is normally enabled). - Shell linting: use
bash -n script.shfor syntax checks andshellcheck script.sh(install via Nix if missing) before committing substantive shell changes. - Neovim health: open Neovim and run
:checkhealthwhen touching plugin/runtime changes. - Kanata configs: rebuild through the flake; for ad-hoc tests run
kanata --config path/to/config.kbd.
nix/— flakes, overlays, modules, and home profiles (work,private,shared). Anything user/system-facing ultimately flows through here.shell/— shared shell glue and per-shell snippets; sourced via Home Manager modules.neovim/,starship/,ghostty/,wezterm/,tmux/,kanata/,wezterm/,git/, etc. — tool-specific configs; edit in place and keep Catppuccin palette alignment.equaliser/,wezterm/,ghostty/,wallpapers/— platform-adjacent assets (audio routing, terminal profile, theming, imagery).opencode/— skills, commands, and MCP agent definitions exposed to agents; tweak only if you understand how the automation uses them.
- Read before you edit; respect scope-specific instructions (no nested
AGENTS.mdtoday, but check before deep changes). - Keep one TodoWrite item
in_progressat a time; update as you move through subtasks. - Prefer
nix fmt,nix flake check, and attribute-scoped builds over bespoke scripts. - Never run
brew installdirectly—Homebrew state is managed declaratively vianix-homebrewinnix/modules/darwin. - Do not open decrypted SOPS files; access values through the paths exposed in Home Manager modules (see
nix/homes/work/default.nix).
HOME_CONFIGURATION_CONTEXTdifferentiates “work” vs “private” profiles and toggles shells (bash vs zsh) plus MCP servers. Preserve this variable when adding new modules.- Work profile (
nix/homes/work) injects secrets for Docker registries, GitHub tokens, etc.; reference them viaconfig.sops.secrets.<name>.path. - Private profile (
nix/homes/private) focuses on zsh and Ollama; avoid work-only tooling there. shell/commonprovides shared aliases (gitui theming, Docker helpers, mirrord integration). Source it rather than duplicating logic.
General
- 2-space indentation, 120-character soft limit unless a tool mandates otherwise.
- Favor small, composable modules and overlays; avoid monolithic files.
- Keep Catppuccin color choices consistent across shell prompts, terminals, themes, and UI configs.
Nix
- Alejandra formatting is canonical; never hand-wrap differently afterwards.
- Inputs should use
inputs.<name>.followswhere practical; avoid hard pin divergence without a comment. - Modules belong under
nix/modules/<platform>/<topic>; shared logic sits innix/modules/shared. - Prefer
lib.mkIf,lib.mkOptionDefault, andlib.optionalsto keep conditionals declarative. - When adding Home Manager secrets, use the existing pattern in
nix/homes/work/default.nix(SOPS module import,genAttrsfor multi-secret lists).
Shell (bash/zsh)
- Start scripts with
#!/usr/bin/env bashandset -e(orset -euo pipefailif safe); keep functions inshell/commonwhen they need cross-shell reuse. - Use long-form function names; avoid single-letter aliases except where already established.
- Rely on built-in helpers from
shell/commonfor git/distro detection; avoid copy/pasting OS detection logic.
Lua / Neovim
- Keep plugin specs under
neovim/logic/lua/plugins/; language-specific configuration belongs inneovim/logic/lua/lang/. - Stylua with default project settings (2 spaces, 120 columns). No trailing semicolons.
- When adding plugins, ensure they are hooked into the appropriate lazy loader and note dependencies inside the same table.
TOML / YAML / JSON
- Preserve key ordering that matches upstream tool docs (e.g., Starship, WezTerm). Alphabetize where no semantic order exists.
- Avoid trailing commas in TOML; keep double quotes for strings unless the format prefers bare words.
Rust / Other Languages
- Rust toolchain is managed via
rust/andrustup; runcargo fmt+cargo clippyin affected projects before merging. - Go/Node/Python tooling is typically project-local; when editing global helpers, prefer version managers provided via Home Manager (see
nix/homes/work/global-dev-tools.nix).
- In shell scripts, check command availability with
command -vbefore use (seeinit.sh). - Use descriptive
echostatements orprintffor user-facing messaging; keep debug logs minimal and optionally gated by an env var. - For Nix modules, provide helpful option descriptions and default values; fail fast with assertions when an assumption must hold (e.g., context-specific host names).
- Add new system packages via the appropriate module (
nix/modules/darwin,nix/modules/nixos, or shared overlays). Avoidnix-env -i. - For Home Manager packages, prefer per-context modules (
homes/work,homes/private) to avoid leaking work-only tools into private machines. - Use overlays under
nix/overlaysto patch upstream packages; keep them minimal and documented. - When adding binary blobs (wallpapers, themes), store them under the most specific directory and reference them declaratively via modules.
- After editing a module, run
nix repl ./nixand:lfthe module to ensure evaluation succeeds before a full rebuild. - For incremental checks, target specific attributes:
nix eval ./nix#homeConfigurations."chris@full-tuxedo".activationPackageto ensure the HM profile builds. - When adjusting Neovim configs, open Neovim with
NVIM_APPNAME=logic nvim(if applicable) to ensure the correct runtime is used. - For kanata configs on non-NixOS hosts, follow
kanata/kanata_install_darwin.nixand test viakanata --config ...before enabling at boot.
- Never commit without explicit user approval. Prepare diffs with
git status+git difffor inspection. - Reference changed files by path + line numbers in final summaries so users can jump straight to them.
- Mention any follow-up work (e.g., “needs
nix flake update”) instead of silently skipping it.
- Formatting-on-save is generally enabled Neovim. Temporarily disable with
:FormatDisableonly if a formatter is broken, and re-enable afterwards. - Catppuccin theme variants: prefer Mocha for dark, Latte for light, and keep prompt/terminal/Neovim in sync.
gituitheme auto-detects platform and color scheme viashell/common—reuse that function rather than introducing new env checks.- When touching MCP server definitions, ensure runtime inputs exist on both darwin (
aarch64-darwin) and linux (x86_64-linux) systems. - Large binary additions (fonts, wallpapers) should include a short README in the containing directory explaining provenance and usage.
Happy automating! Stay declarative, keep secrets sealed, and let nix do the heavy lifting.