Migrate global configuration to and expand home

- Move lots of system config to home (browser, editors, etc.)
- Improve catppuccin support (kitty, cursors, etc.)
- Improve overall theme (fonts, icons in kitty)
- Add coded's system hardware configuration ("shorthair")
- Add the ed editor
- Split minion's system hardware configuration ("greylag") into several files
- Improve shell support (aliases, useful packages, replacements, etc.)

Change-Id: Ie6d40f809b2662268a9a6fa8b241641bbfef9442
Reviewed-on: https://git.clicks.codes/c/Chimera/NixFiles/+/383
Tested-by: Skyler Grey <minion@clicks.codes>
Reviewed-by: Samuel Shuert <coded@clicks.codes>
diff --git a/modules/home/audio/default.nix b/modules/home/audio/default.nix
index 3d7903b..253ac3e 100644
--- a/modules/home/audio/default.nix
+++ b/modules/home/audio/default.nix
@@ -1,5 +1,4 @@
-{ pkgs, ... }: {
-  home.packages = [
-    pkgs.helvum
-  ];
-}
\ No newline at end of file
+{ pkgs, ... }:
+{
+  home.packages = [ pkgs.helvum ];
+}
diff --git a/modules/home/browser/chromium/default.nix b/modules/home/browser/chromium/default.nix
index 16dd34e..c21f21c 100644
--- a/modules/home/browser/chromium/default.nix
+++ b/modules/home/browser/chromium/default.nix
@@ -1,4 +1,5 @@
-{ lib, config, ... }: {
+{ lib, config, ... }:
+{
   options.chimera.browser.chromium = {
     enable = lib.mkEnableOption "Use chromium browser";
     extensions = {
@@ -12,22 +13,58 @@
       ublockOrigin.enable = lib.mkEnableOption "Turn on uBlock Origin ad blocker";
     };
     extraExtensions = lib.mkOption {
-      type = lib.types.listOf (lib.types.either { id = lib.types.str; } { id = lib.types.str; crxPath = lib.types.path; version = lib.types.str; });
+      type = lib.types.listOf (
+        lib.types.either { id = lib.types.str; } {
+          id = lib.types.str;
+          crxPath = lib.types.path;
+          version = lib.types.str;
+        }
+      );
       description = "Extra extensions to add to chromium on launch";
-      default = [];
+      default = [ ];
     };
   };
   config = lib.mkIf config.chimera.browser.chromium.enable ({
     programs.chromium = {
       enable = true;
       extensions =
-        (if config.chimera.browser.chromium.extensions.bitwarden.enable then [{ id = "nngceckbapebfimnlniiiahkandclblb"; }] else []) #Bitwarden
-        ++ (if config.chimera.browser.chromium.extensions.youtube.sponsorBlock.enable then [{ id = "mnjggcdmjocbbbhaepdhchncahnbgone"; }] else []) #Sponsor Block
-        ++ (if config.chimera.browser.chromium.extensions.youtube.returnDislike.enable then [{ id = "gebbhagfogifgggkldgodflihgfeippi"; }] else []) #Return youtube dislike
-        ++ (if config.chimera.browser.chromium.extensions.youtube.deArrow.enable then [{ id = "enamippconapkdmgfgjchkhakpfinmaj"; }] else []) #DeArrow
-        ++ (if config.chimera.browser.chromium.extensions.reactDevTools.enable then [{ id = "fmkadmapgofadopljbjfkapdkoienihi"; }] else []) #React Dev Tools
-        ++ (if config.chimera.browser.chromium.extensions.ublockOrigin.enable then [{ id = "cjpalhdlnbpafiamejdnhcphjbkeiagm"; }] else []) #uBlock Origin
+        (
+          if config.chimera.browser.chromium.extensions.bitwarden.enable then
+            [ { id = "nngceckbapebfimnlniiiahkandclblb"; } ]
+          else
+            [ ]
+        ) # Bitwarden
+        ++ (
+          if config.chimera.browser.chromium.extensions.youtube.sponsorBlock.enable then
+            [ { id = "mnjggcdmjocbbbhaepdhchncahnbgone"; } ]
+          else
+            [ ]
+        ) # Sponsor Block
+        ++ (
+          if config.chimera.browser.chromium.extensions.youtube.returnDislike.enable then
+            [ { id = "gebbhagfogifgggkldgodflihgfeippi"; } ]
+          else
+            [ ]
+        ) # Return youtube dislike
+        ++ (
+          if config.chimera.browser.chromium.extensions.youtube.deArrow.enable then
+            [ { id = "enamippconapkdmgfgjchkhakpfinmaj"; } ]
+          else
+            [ ]
+        ) # DeArrow
+        ++ (
+          if config.chimera.browser.chromium.extensions.reactDevTools.enable then
+            [ { id = "fmkadmapgofadopljbjfkapdkoienihi"; } ]
+          else
+            [ ]
+        ) # React Dev Tools
+        ++ (
+          if config.chimera.browser.chromium.extensions.ublockOrigin.enable then
+            [ { id = "cjpalhdlnbpafiamejdnhcphjbkeiagm"; } ]
+          else
+            [ ]
+        ) # uBlock Origin
         ++ config.chimera.browser.chromium.extraExtensions;
     };
   });
-}
\ No newline at end of file
+}
diff --git a/modules/home/browser/firefox/default.nix b/modules/home/browser/firefox/default.nix
index d1aa88f..3fcbf06 100644
--- a/modules/home/browser/firefox/default.nix
+++ b/modules/home/browser/firefox/default.nix
@@ -1,4 +1,5 @@
-{ lib, config, ... }: {
+{ lib, config, ... }:
+{
   options.chimera.browser.firefox = {
     enable = lib.mkEnableOption "Use firefox browser";
     extensions = {
@@ -20,14 +21,50 @@
   config = lib.mkIf config.chimera.browser.firefox.enable ({
     programs.firefox = {
       enable = true;
-      profiles.chimera.extensions = (if config.chimera.browser.firefox.extensions.bitwarden.enable then [ config.nur.repos.rycee.firefox-addons.bitwarden ] else [])
-        ++ (if config.chimera.browser.firefox.extensions.youtube.sponsorBlock.enable then [ config.nur.repos.rycee.firefox-addons.sponsorblock ] else [])
-        ++ (if config.chimera.browser.firefox.extensions.youtube.returnDislike.enable then [ config.nur.repos.rycee.firefox-addons.return-youtube-dislikes ] else [])
-        ++ (if config.chimera.browser.firefox.extensions.youtube.deArrow.enable then [ config.nur.repos.rycee.firefox-addons.dearrow ] else [])
-        ++ (if config.chimera.browser.firefox.extensions.reactDevTools.enable then [ config.nur.repos.rycee.firefox-addons.react-devtools ] else [])
-        ++ (if config.chimera.browser.firefox.extensions.ublockOrigin.enable then [ config.nur.repos.rycee.firefox-addons.ublock-origin ] else [])
-        ++ (if config.chimera.browser.firefox.extensions.adnauseam.enable then [ config.nur.repos.rycee.firefox-addons.adnauseam ] else [])
+      profiles.chimera.extensions =
+        (
+          if config.chimera.browser.firefox.extensions.bitwarden.enable then
+            [ config.nur.repos.rycee.firefox-addons.bitwarden ]
+          else
+            [ ]
+        )
+        ++ (
+          if config.chimera.browser.firefox.extensions.youtube.sponsorBlock.enable then
+            [ config.nur.repos.rycee.firefox-addons.sponsorblock ]
+          else
+            [ ]
+        )
+        ++ (
+          if config.chimera.browser.firefox.extensions.youtube.returnDislike.enable then
+            [ config.nur.repos.rycee.firefox-addons.return-youtube-dislikes ]
+          else
+            [ ]
+        )
+        ++ (
+          if config.chimera.browser.firefox.extensions.youtube.deArrow.enable then
+            [ config.nur.repos.rycee.firefox-addons.dearrow ]
+          else
+            [ ]
+        )
+        ++ (
+          if config.chimera.browser.firefox.extensions.reactDevTools.enable then
+            [ config.nur.repos.rycee.firefox-addons.react-devtools ]
+          else
+            [ ]
+        )
+        ++ (
+          if config.chimera.browser.firefox.extensions.ublockOrigin.enable then
+            [ config.nur.repos.rycee.firefox-addons.ublock-origin ]
+          else
+            [ ]
+        )
+        ++ (
+          if config.chimera.browser.firefox.extensions.adnauseam.enable then
+            [ config.nur.repos.rycee.firefox-addons.adnauseam ]
+          else
+            [ ]
+        )
         ++ config.chimera.browser.firefox.extraExtensions;
     };
   });
-}
\ No newline at end of file
+}
diff --git a/modules/home/catppuccin/default.nix b/modules/home/catppuccin/default.nix
index 3389ba1..d705e57 100644
--- a/modules/home/catppuccin/default.nix
+++ b/modules/home/catppuccin/default.nix
@@ -1,4 +1,9 @@
-{ lib, config, ... }:
+{
+  pkgs,
+  lib,
+  config,
+  ...
+}:
 {
   options.chimera.theme.catppuccin = {
     enable = lib.mkEnableOption "Whether to use Catppuccin themes";
@@ -1410,9 +1415,18 @@
       };
     in
     {
-      chimera.theme.colors = catppuccinColors.${config.chimera.theme.catppuccin.style} // {
-        Highlight =
-          catppuccinColors.${config.chimera.theme.catppuccin.style}.${config.chimera.theme.catppuccin.color};
+      chimera.theme = {
+        colors = catppuccinColors.${config.chimera.theme.catppuccin.style} // {
+          Accent =
+            catppuccinColors.${config.chimera.theme.catppuccin.style}.${config.chimera.theme.catppuccin.color};
+        };
+
+        cursor = {
+          package =
+            pkgs.catppuccin-cursors."${lib.strings.toLower config.chimera.theme.catppuccin.style}${config.chimera.theme.catppuccin.color}";
+          name = "Catppuccin-${config.chimera.theme.catppuccin.style}-${config.chimera.theme.catppuccin.color}-Cursors";
+          size = 32;
+        };
       };
     }
   );
diff --git a/modules/home/editor/ed/default.nix b/modules/home/editor/ed/default.nix
new file mode 100644
index 0000000..80e4ac6
--- /dev/null
+++ b/modules/home/editor/ed/default.nix
@@ -0,0 +1,24 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+{
+  options.chimera.editor.ed = {
+    enable = lib.mkEnableOption "Enable the standard text editor, the greatest WYGIWYG editor of all, the only viable text editor, Ed";
+    defaultEditor = lib.mkOption {
+      type = lib.types.bool;
+      description = "Use Ed as the default editor";
+      default = true;
+    };
+  };
+
+  config = lib.mkIf config.chimera.editor.ed.enable {
+    home.packages = [ pkgs.ed ];
+
+    home.sessionVariables = lib.mkIf config.chimera.editor.ed.defaultEditor {
+      EDITOR = "${pkgs.ed}/bin/ed";
+    };
+  };
+}
diff --git a/modules/home/editor/emacs/default.nix b/modules/home/editor/emacs/default.nix
new file mode 100644
index 0000000..4151db1
--- /dev/null
+++ b/modules/home/editor/emacs/default.nix
@@ -0,0 +1,19 @@
+{ config, lib, ... }:
+{
+  options.chimera.editor.emacs = {
+    enable = lib.mkEnableOption "Enable emacs editor";
+    defaultEditor = lib.mkOption {
+      type = lib.types.bool;
+      description = "Use emacs as the default editor";
+      default = true;
+    };
+  };
+
+  config = lib.mkIf config.chimera.editor.emacs.enable {
+    programs.emacs.enable = true;
+    services.emacs = {
+      enable = true;
+      defaultEditor = config.chimera.editor.emacs.defaultEditor;
+    };
+  };
+}
diff --git a/modules/home/editor/neovim/default.nix b/modules/home/editor/neovim/default.nix
new file mode 100644
index 0000000..7098365
--- /dev/null
+++ b/modules/home/editor/neovim/default.nix
@@ -0,0 +1,18 @@
+{ config, lib, ... }:
+{
+  options.chimera.editor.neovim = {
+    enable = lib.mkEnableOption "Enable neovim editor";
+    defaultEditor = lib.mkOption {
+      type = lib.types.bool;
+      description = "Use neovim as the default editor";
+      default = true;
+    };
+  };
+
+  config = lib.mkIf config.chimera.editor.neovim.enable {
+    programs.neovim = {
+      enable = true;
+      defaultEditor = config.chimera.editor.neovim.defaultEditor;
+    };
+  };
+}
diff --git a/modules/home/git/default.nix b/modules/home/git/default.nix
new file mode 100644
index 0000000..6a161ea
--- /dev/null
+++ b/modules/home/git/default.nix
@@ -0,0 +1,175 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+{
+  options.chimera.git = {
+    gitReview.enable = lib.mkEnableOption "Enable git review";
+    delta.enable = lib.mkEnableOption "Enable delta, an alternative pager for git diffs that highlights syntax";
+    auth = {
+      clicksUsername = lib.mkOption {
+        type = lib.types.str;
+        description = "Username for Clicks Gerrit";
+      };
+    };
+  };
+
+  config = {
+
+    home.packages = (if config.chimera.git.gitReview.enable then [ pkgs.git-review ] else [ ]);
+
+    programs.zsh.shellAliases =
+      if config.chimera.git.gitReview.enable then { "gr!" = "git review"; } else { };
+
+    programs.bash.shellAliases =
+      if config.chimera.git.gitReview.enable then { "gr!" = "git review"; } else { };
+
+    programs.git = {
+      enable = true;
+
+      delta.enable = config.chimera.git.delta.enable;
+
+      extraConfig = {
+        init.defaultBranch = "main";
+        advice.skippedcherrypicks = false;
+        commit.gpgsign = true;
+        credential.helper = "cache";
+        core = {
+          repositoryformatversion = 0;
+          filemode = true;
+          bare = false;
+          logallrefupdates = true;
+          fsmonitor = true;
+          autocrlf = "input";
+          splitIndex = true;
+          untrackedCache = true;
+        };
+        pull = {
+          rebase = "merges"; # TODO: from git docs, should we provide an option for this?: NOTE: this is a possibly dangerous operation; do not use it unless you understand the implications (see git-rebase[1] for details).
+        };
+        push = {
+          autoSetupRemote = true;
+          gpgSign = "if-asked";
+        };
+        url = {
+          "ssh://git@github.com/".pushInsteadOf = "https://github.com/";
+          "ssh://minion@ssh.clicks.codes:29418/".pushInsteadOf = "https://git.clicks.codes/";
+        };
+        merge.conflictstyle = "diff3";
+        trailer.ifexists = "addIfDifferent";
+      };
+    };
+  };
+}
+
+/* [alias]
+   	recommit = "!git commit --verbose -eF $(git rev-parse --git-dir)/COMMIT_EDITMSG"
+   	stash-working = "!f() { \
+   		git commit --quiet --no-verify -m \"temp for stash-working\" && \
+           	git stash push \"$@\" && \
+           	git reset --quiet --soft HEAD~1; \
+   	}; f"
+   	checkout-soft = "!f() { \
+   	   hash=$(git hash); \
+   	   git checkout \"$@\"; \
+   	   git reset --soft $hash; \
+   	}; f" # basically the opposite of a soft reset: change all the files but do not change the HEAD reference
+   	graph = "log --graph --oneline --decorate"
+   	fmt = "clang-format"
+   	hash = "rev-parse HEAD"
+   	fmt-last = "!f() { \
+   		hash=$(git hash); \
+   		git reset --soft HEAD^ && \
+   		git fmt; \
+   		git reset --soft $hash; \
+   	}; f"
+   	personal = "config user.email skyler3665@gmail.com"
+   	clicks = "config user.email minion@clicks.codes"
+   	collabora = "config user.email skyler.grey@collabora.com"
+   	# review = "!git-review -T": cannot be set here, set in .zshrc instead
+
+   [credential]
+   	helper = "store"
+
+   /*
+   [user]
+   	name = "Skyler Grey"
+   	signingkey = "7C868112B5390C5C"
+     useConfigOnly = true # avoid auto-setting user.email by hostname
+
+   [alias]
+   	recommit = "!git commit --verbose -eF $(git rev-parse --git-dir)/COMMIT_EDITMSG"
+   	stash-working = "!f() { \
+   		git commit --quiet --no-verify -m \"temp for stash-working\" && \
+           	git stash push \"$@\" && \
+           	git reset --quiet --soft HEAD~1; \
+   	}; f"
+   	checkout-soft = "!f() { \
+   	   hash=$(git hash); \
+   	   git checkout \"$@\"; \
+   	   git reset --soft $hash; \
+   	}; f" # basically the opposite of a soft reset: change all the files but do not change the HEAD reference
+   	graph = "log --graph --oneline --decorate"
+   	fmt = "clang-format"
+   	hash = "rev-parse HEAD"
+   	fmt-last = "!f() { \
+   		hash=$(git hash); \
+   		git reset --soft HEAD^ && \
+   		git fmt; \
+   		git reset --soft $hash; \
+   	}; f"
+   	personal = "config user.email skyler3665@gmail.com"
+   	clicks = "config user.email minion@clicks.codes"
+   	collabora = "config user.email skyler.grey@collabora.com"
+   	# review = "!git-review -T": cannot be set here, set in .zshrc instead
+
+   [init]
+   	defaultBranch = "main"
+
+   [color]
+   	ui = "auto"
+
+   [core]
+   	autocrlf = "input"
+   	splitIndex = true
+   	untrackedCache = true
+   	fsmonitor = true
+   	pager = "delta"
+
+   [pull]
+   	rebase = merges
+
+   [push]
+   	autoSetupRemote = true
+   	useForceIfIncludes = true
+   	gpgSign = if-asked
+
+   [credential]
+   	helper = "store"
+
+   [commit]
+   	gpgsign = true
+
+   [url "ssh://git@github.com/"]
+   	pushInsteadOf = "https://github.com/"
+
+   [interactive]
+   	diffFilter = "delta --color-only"
+
+   [delta]
+   	navigate = true
+   	light = false
+   	line-numbers = true
+   	features = "my-dark-theme zebra-dark"
+
+   [merge]
+   	conflictstyle = "diff3"
+
+   [diff]
+   	colorMoved = "default"
+
+   [trailer]
+   	ifexists = "addIfDifferent"
+*/
diff --git a/modules/home/hyprland/default.nix b/modules/home/hyprland/default.nix
index ce1a300..38d40cd 100644
--- a/modules/home/hyprland/default.nix
+++ b/modules/home/hyprland/default.nix
@@ -89,7 +89,7 @@
             disable_splash_rendering = true;
           };
 
-          exec-once = "${pkgs.hyprpaper}/bin/hyprpaper";
+          exec-once = "${pkgs.hyprpaper}/bin/hyprpaper; hyprctl setcursor ${config.chimera.theme.cursor.name} ${builtins.toString config.chimera.theme.cursor.size}";
 
           monitor = config.chimera.hyprland.monitors ++ [ ",preferred,auto,1" ];
 
diff --git a/modules/home/shell/bash/default.nix b/modules/home/shell/bash/default.nix
new file mode 100644
index 0000000..3eb3bf6
--- /dev/null
+++ b/modules/home/shell/bash/default.nix
@@ -0,0 +1,24 @@
+{ config, lib, ... }:
+{
+  options.chimera.shell.bash = {
+    enable = lib.mkEnableOption "Enable Bash Shell";
+    default = lib.mkOption {
+      type = lib.types.bool;
+      description = "Set as default shell";
+      default = true;
+    };
+    extraAliases = lib.mkOption {
+      type = lib.types.attrsOf lib.types.str;
+      description = "Attrset of extra shell aliases";
+      default = { };
+    };
+  };
+
+  config = lib.mkIf config.chimera.shell.bash.enable {
+    programs.bash = {
+      enable = true;
+
+      shellAliases = config.chimera.shell.bash.extraAliases;
+    };
+  };
+}
diff --git a/modules/home/shell/default.nix b/modules/home/shell/default.nix
new file mode 100644
index 0000000..f03ad77
--- /dev/null
+++ b/modules/home/shell/default.nix
@@ -0,0 +1,67 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+{
+  options.chimera.shell = {
+    rebuildFlakePath = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
+      description = "Full path to where you store your flake locally";
+      default = null;
+    };
+    defaultAliases.enable = lib.mkEnableOption "Use sensible custom aliases";
+    usefulPackages.enable = lib.mkEnableOption "Enable useful shell packages (ripgrep, wget, etc)";
+    replacements = {
+      eza.enable = lib.mkEnableOption "Use eza instead of ls";
+      bfs.enable = lib.mkEnableOption "Use bfs instead of find";
+      ripgrep.enable = lib.mkEnableOption "Use ripgrep instead of grep";
+      htop.enable = lib.mkEnableOption "Use htop instead of top";
+      erdtree.enable = lib.mkEnableOption "Use erdtree instead of tree";
+      dust.enable = lib.mkEnableOption "Use dust instead of du";
+      bat.enable = lib.mkEnableOption "Use bat instead of cat";
+    };
+  };
+
+  config = {
+    home.shellAliases = lib.mkIf config.chimera.shell.defaultAliases.enable {
+      rebuild =
+        lib.mkIf (config.chimera.shell.rebuildFlakePath != null)
+          "sudo nixos-rebuild switch --flake ${config.chimera.shell.rebuildFlakePath}";
+      clr = "clear";
+      edit = config.home.sessionVariables.EDITOR;
+    };
+
+    programs = lib.mkIf config.chimera.shell.usefulPackages.enable {
+      tealdeer = {
+        enable = true;
+        settings.updates.autoupdate = true;
+      };
+      jq.enable = true;
+    };
+
+    home.packages =
+      (
+        if config.chimera.shell.usefulPackages.enable then
+          [
+            pkgs.wget
+            pkgs.curl
+            pkgs.curlie
+            pkgs.pv
+            pkgs.sd
+            pkgs.tokei
+            pkgs.hyperfine
+          ]
+        else
+          [ ]
+      )
+      ++ (if config.chimera.shell.replacements.eza.enable then [ pkgs.eza ] else [ ])
+      ++ (if config.chimera.shell.replacements.bfs.enable then [ pkgs.bfs ] else [ ])
+      ++ (if config.chimera.shell.replacements.ripgrep.enable then [ pkgs.ripgrep ] else [ ])
+      ++ (if config.chimera.shell.replacements.htop.enable then [ pkgs.htop ] else [ ])
+      ++ (if config.chimera.shell.replacements.erdtree.enable then [ pkgs.erdtree ] else [ ])
+      ++ (if config.chimera.shell.replacements.dust.enable then [ pkgs.dust ] else [ ])
+      ++ (if config.chimera.shell.replacements.bat.enable then [ pkgs.bat ] else [ ]);
+  };
+}
diff --git a/modules/home/shell/starship/default.nix b/modules/home/shell/starship/default.nix
new file mode 100644
index 0000000..4a958eb
--- /dev/null
+++ b/modules/home/shell/starship/default.nix
@@ -0,0 +1,13 @@
+{ config, lib, ... }:
+{
+  options.chimera.shell.starship.enable = lib.mkEnableOption "Enable to use starship prompt";
+
+  config = lib.mkIf config.chimera.shell.starship.enable {
+    programs.starship = {
+      enable = true;
+      settings = {
+        format = "$all";
+      };
+    };
+  };
+}
diff --git a/modules/home/shell/zsh/default.nix b/modules/home/shell/zsh/default.nix
new file mode 100644
index 0000000..6b669fd
--- /dev/null
+++ b/modules/home/shell/zsh/default.nix
@@ -0,0 +1,51 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+{
+
+  options.chimera.shell.zsh = {
+    enable = lib.mkEnableOption "Enable ZSH Shell";
+    default = lib.mkOption {
+      type = lib.types.bool;
+      description = "Set as default shell";
+      default = true;
+    };
+    extraAliases = lib.mkOption {
+      type = lib.attrsOf lib.types.str;
+      description = "Attrset of extra shell aliases";
+      default = { };
+    };
+    dirHashes = lib.mkOption {
+      type = lib.attrsOf lib.types.str;
+      description = "Attrset of ~DIR's";
+      default = { };
+    };
+  };
+
+  config = lib.mkIf config.chimera.shell.zsh.enable {
+    programs.zsh = {
+      enable = true;
+      enableAutosuggestions = true;
+      enableCompletion = true;
+      autocd = true;
+      defaultKeymap = "emacs";
+
+      shellAliases = config.chimera.shell.zsh.extraAliases;
+
+      dirHashes = config.chimera.shell.zsh.dirHashes;
+
+      history = {
+        extended = true;
+      };
+      historySubstringSearch.enable = true;
+
+      oh-my-zsh = {
+        enable = true;
+        plugins = [ "git" ];
+      };
+    };
+  };
+}
diff --git a/modules/home/terminal/default.nix b/modules/home/terminal/default.nix
new file mode 100644
index 0000000..2465620
--- /dev/null
+++ b/modules/home/terminal/default.nix
@@ -0,0 +1,35 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+{
+  options.chimera.terminal.kitty = {
+    enable = lib.mkOption {
+      type = lib.types.bool;
+      description = "Use kitty as your terminal";
+      default = true;
+    };
+  };
+
+  config = lib.mkIf config.chimera.terminal.kitty.enable {
+    programs.kitty = {
+      enable = true;
+      theme =
+        if config.chimera.theme.catppuccin.enable then
+          "Catppuccin-${config.chimera.theme.catppuccin.style}"
+        else
+          null;
+      font = config.chimera.theme.font.mono;
+      shellIntegration = {
+        enableZshIntegration = config.chimera.shell.zsh.enable;
+        enableBashIntegration = config.chimera.shell.bash.enable;
+      };
+      settings = {
+        confirm_os_window_close = -1;
+        symbol_map = lib.mkIf config.chimera.theme.font.nerdFontGlyphs.enable "U+23FB-U+23FE,U+2665,U+26A1,U+2B58,U+E000-U+E00A,U+E0A0-U+E0A3,U+E0B0-U+E0D4,U+E200-U+E2A9,U+E300-U+E3E3,U+E5FA-U+E6AA,U+E700-U+E7C5,U+EA60-U+EBEB,U+F000-U+F2E0,U+F300-U+F32F,U+F400-U+F4A9,U+F500-U+F8FF,U+F0001-U+F1AF0 Symbols Nerd Font Mono";
+      };
+    };
+  };
+}
diff --git a/modules/home/theme/default.nix b/modules/home/theme/default.nix
index 5fdb405..11478c8 100644
--- a/modules/home/theme/default.nix
+++ b/modules/home/theme/default.nix
@@ -2,11 +2,87 @@
   pkgs,
   config,
   lib,
+  inputs,
   ...
 }:
 {
   options.chimera.theme = {
-    cursor = null;
+    font = {
+      mono = lib.mkOption {
+        type = inputs.home-manager.lib.hm.types.fontType;
+        description = "Mono width font to use as system default";
+        default = {
+          name = "FiraCode";
+          package = pkgs.fira-code;
+          size = 12;
+        };
+      };
+      variableWidth = {
+        serif = lib.mkOption {
+          type = inputs.home-manager.lib.hm.types.fontType;
+          description = "Serif variable width font to use as system default";
+          default = {
+            name = "Roboto Serif";
+            package = pkgs.roboto-serif;
+            size = 12;
+          };
+        };
+        sansSerif = lib.mkOption {
+          type = inputs.home-manager.lib.hm.types.fontType;
+          description = "Sans serif variable width font to use as system default";
+          default = {
+            name = "Roboto";
+            package = pkgs.roboto;
+            size = 12;
+          };
+        };
+      };
+      emoji = lib.mkOption {
+        type = inputs.home-manager.lib.hm.types.fontType;
+        description = "Emoji's to use as system default";
+        default = {
+          name = "Twitter Color Emoji";
+          package = pkgs.twitter-color-emoji;
+          size = 12;
+        };
+      };
+      nerdFontGlyphs.enable = lib.mkEnableOption "Enable Nerd Font Glyphs";
+      extraFonts = lib.mkOption {
+        type = lib.types.listOf inputs.home-manager.lib.hm.types.fontType;
+        description = "Extra fonts to install";
+        default = [ ];
+      };
+    };
+
+    cursor = lib.mkOption {
+      type = lib.types.nullOr (
+        lib.types.submodule {
+          options = {
+            package = lib.mkOption {
+              type = lib.types.package;
+              example = lib.literalExpression "pkgs.vanilla-dmz";
+              description = "Package providing the cursor theme";
+            };
+
+            name = lib.mkOption {
+              type = lib.types.str;
+              example = "Vanilla-DMZ";
+              description = "The cursor name within the package";
+            };
+
+            size = lib.mkOption {
+              type = lib.types.int;
+              default = 32;
+              example = 64;
+              description = "The cursor size";
+            };
+          };
+        }
+      );
+      description = "Cursor settings";
+      default = null;
+    };
+
     colors =
       let
         themeColor = {
@@ -50,7 +126,35 @@
         Base = lib.mkOption { type = themeColor; };
         Mantle = lib.mkOption { type = themeColor; };
         Crust = lib.mkOption { type = themeColor; };
-        Highlight = lib.mkOption { type = themeColor; };
+        Accent = lib.mkOption { type = themeColor; };
       };
   };
+
+  config = {
+
+    fonts.fontconfig.enable = true;
+
+    home.packages =
+      [
+        config.chimera.theme.font.mono.package
+        config.chimera.theme.font.variableWidth.serif.package
+        config.chimera.theme.font.variableWidth.sansSerif.package
+        config.chimera.theme.font.emoji.package
+      ]
+      ++ (
+        if config.chimera.theme.font.nerdFontGlyphs.enable then
+          [ (pkgs.nerdfonts.override { fonts = [ "NerdFontsSymbolsOnly" ]; }) ]
+        else
+          [ ]
+      )
+      ++ config.chimera.theme.font.extraFonts;
+
+    home.pointerCursor = lib.mkIf (config.chimera.theme.cursor != null) {
+      name = config.chimera.theme.cursor.name;
+      package = config.chimera.theme.cursor.package;
+      size = config.chimera.theme.cursor.size;
+      gtk.enable = true; # TODO: should we factor this out into a gtk module when we come to that?
+      x11.enable = true;
+    };
+  };
 }