summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.envrc8
-rw-r--r--flake.lock48
-rw-r--r--flake.nix7
-rw-r--r--overlays/cgit-pink/default.nix5
-rw-r--r--overlays/cgit-pink/set-default-branch-main.patch (renamed from patches/cgit-pink.patch)0
-rw-r--r--overlays/emacs.nix4
-rw-r--r--overlays/extra-packages.nix36
-rw-r--r--overlays/firefox.nix4
-rw-r--r--overlays/htmlformat/default.nix3
-rw-r--r--overlays/htmlformat/htmlformat.nix (renamed from packages/htmlformat/default.nix)0
-rw-r--r--overlays/rofi.nix7
-rw-r--r--patches/ddclient-noipv4.patch79
-rw-r--r--shell.nix3
-rw-r--r--system/linde.nix7
-rw-r--r--system/mba.nix8
-rwxr-xr-xsystem/nanopi.nix1
-rw-r--r--system/prefect.nix1
-rw-r--r--system/settings/configuration/nix.nix3
-rw-r--r--system/settings/darwin.nix11
-rw-r--r--system/settings/hardware/keyboard-lofree.nix9
-rw-r--r--system/settings/programs/base.nix8
-rw-r--r--system/settings/user-interface.nix9
-rw-r--r--user/emacs/init.el204
-rw-r--r--user/mba.nix1
-rw-r--r--user/modules/tabnine.nix11
-rw-r--r--user/nvim/init.lua3
-rw-r--r--user/overlays/extra-packages.nix12
-rw-r--r--user/prefect.nix4
-rw-r--r--user/settings/base.nix1
-rw-r--r--user/settings/development/base.nix61
-rw-r--r--user/settings/development/golang.nix2
-rw-r--r--user/settings/development/javascript.nix67
-rw-r--r--user/settings/development/lisp.nix1
-rw-r--r--user/settings/development/rust.nix3
-rw-r--r--user/settings/development/web.nix5
-rw-r--r--user/settings/development/zig.nix3
-rw-r--r--user/settings/emacs.nix12
-rw-r--r--user/settings/fish.nix73
-rw-r--r--user/settings/gaming.nix12
-rw-r--r--user/settings/git.nix3
-rw-r--r--user/settings/kitty.nix4
-rw-r--r--user/settings/nix.nix9
-rw-r--r--user/settings/nixos.nix8
-rw-r--r--user/settings/nixpkgs.nix6
-rw-r--r--user/settings/rofi.nix9
-rw-r--r--user/settings/shell.nix12
-rw-r--r--user/settings/tabnine.nix82
-rw-r--r--user/settings/user-interface.nix1
48 files changed, 407 insertions, 463 deletions
diff --git a/.envrc b/.envrc
index 3550a30f..fa82cfc4 100644
--- a/.envrc
+++ b/.envrc
@@ -1 +1,7 @@
-use flake
+if type -P lorri &>/dev/null; then
+	eval "$(lorri direnv)"
+else
+	echo 'while direnv evaluated .envrc, could not find the command "lorri" [https://github.com/nix-community/lorri]'
+	use flake
+fi
+FLAKE=$PWD
diff --git a/flake.lock b/flake.lock
index 2e91d0d3..92a135f9 100644
--- a/flake.lock
+++ b/flake.lock
@@ -10,11 +10,11 @@
         "systems": "systems"
       },
       "locked": {
-        "lastModified": 1712079060,
-        "narHash": "sha256-/JdiT9t+zzjChc5qQiF+jhrVhRt8figYH29rZO7pFe4=",
+        "lastModified": 1714136352,
+        "narHash": "sha256-BtWQ2Th/jamO1SlD+2ASSW5Jaf7JhA/JLpQHk0Goqpg=",
         "owner": "ryantm",
         "repo": "agenix",
-        "rev": "1381a759b205dff7a6818733118d02253340fd5e",
+        "rev": "24a7ea390564ccd5b39b7884f597cfc8d7f6f44e",
         "type": "github"
       },
       "original": {
@@ -52,11 +52,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1711763326,
-        "narHash": "sha256-sXcesZWKXFlEQ8oyGHnfk4xc9f2Ip0X/+YZOq3sKviI=",
+        "lastModified": 1713946171,
+        "narHash": "sha256-lc75rgRQLdp4Dzogv5cfqOg6qYc5Rp83oedF2t0kDp8=",
         "owner": "lnl7",
         "repo": "nix-darwin",
-        "rev": "36524adc31566655f2f4d55ad6b875fb5c1a4083",
+        "rev": "230a197063de9287128e2c68a7a4b0cd7d0b50a7",
         "type": "github"
       },
       "original": {
@@ -95,11 +95,11 @@
         "nixpkgs-stable": "nixpkgs-stable"
       },
       "locked": {
-        "lastModified": 1713027991,
-        "narHash": "sha256-xaHTBJTsG85//PpYxD7fYH93NQEGShXeGuT+Ba7ElTg=",
+        "lastModified": 1714237490,
+        "narHash": "sha256-5cdV7tlOHaQ8M808CRk5TJLBaqi2ANLcCq9Ar5JQG5s=",
         "owner": "nix-community",
         "repo": "emacs-overlay",
-        "rev": "fb0a841062d30d512632144a0b8f429d3d83c9c1",
+        "rev": "aee4d3daa7cb71f903492103d1ea522efcf6f740",
         "type": "github"
       },
       "original": {
@@ -170,11 +170,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1713019815,
-        "narHash": "sha256-jzTo97VeKMNfnKw3xU+uiU5C7wtnLudsbwl/nwPLC7s=",
+        "lastModified": 1714203603,
+        "narHash": "sha256-eT7DENhYy7EPLOqHI9zkIMD9RvMCXcqh6gGqOK5BWYQ=",
         "owner": "nix-community",
         "repo": "home-manager",
-        "rev": "8fdf329526f06886b53b94ddf433848a0d142984",
+        "rev": "c1609d584a6b5e9e6a02010f51bd368cb4782f8e",
         "type": "github"
       },
       "original": {
@@ -190,11 +190,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1712459390,
-        "narHash": "sha256-e12bNDottaGoBgd0AdH/bQvk854xunlWAdZwr/oHO1c=",
+        "lastModified": 1713869268,
+        "narHash": "sha256-o3CMQeu/S8/4zU0pMtYg51rd1FWdJsI2Xohzng1Ysdg=",
         "owner": "Mic92",
         "repo": "nix-index-database",
-        "rev": "4676d72d872459e1e3a248d049609f110c570e9a",
+        "rev": "dcb6ac44922858ce3a5b46f77a36d6030181460c",
         "type": "github"
       },
       "original": {
@@ -205,11 +205,11 @@
     },
     "nixos-hardware": {
       "locked": {
-        "lastModified": 1712909959,
-        "narHash": "sha256-7/5ubuwdEbQ7Z+Vqd4u0mM5L2VMNDsBh54visp27CtQ=",
+        "lastModified": 1714201532,
+        "narHash": "sha256-nk0W4rH7xYdDeS7k1SqqNtBaNrcgIBYNmOVc8P2puEY=",
         "owner": "NixOS",
         "repo": "nixos-hardware",
-        "rev": "f58b25254be441cd2a9b4b444ed83f1e51244f1f",
+        "rev": "53db5e1070d07e750030bf65f1b9963df8f0c678",
         "type": "github"
       },
       "original": {
@@ -236,11 +236,11 @@
     },
     "nixpkgs-stable": {
       "locked": {
-        "lastModified": 1712867921,
-        "narHash": "sha256-edTFV4KldkCMdViC/rmpJa7oLIU8SE/S35lh/ukC7bg=",
+        "lastModified": 1713995372,
+        "narHash": "sha256-fFE3M0vCoiSwCX02z8VF58jXFRj9enYUSTqjyHAjrds=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "51651a540816273b67bc4dedea2d37d116c5f7fe",
+        "rev": "dd37924974b9202f8226ed5d74a252a9785aedf8",
         "type": "github"
       },
       "original": {
@@ -252,11 +252,11 @@
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1712791164,
-        "narHash": "sha256-3sbWO1mbpWsLepZGbWaMovSO7ndZeFqDSdX0hZ9nVyw=",
+        "lastModified": 1714076141,
+        "narHash": "sha256-Drmja/f5MRHZCskS6mvzFqxEaZMeciScCTFxWVLqWEY=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "1042fd8b148a9105f3c0aca3a6177fd1d9360ba5",
+        "rev": "7bb2ccd8cdc44c91edba16c48d2c8f331fb3d856",
         "type": "github"
       },
       "original": {
diff --git a/flake.nix b/flake.nix
index 341e3514..ed8ccc47 100644
--- a/flake.nix
+++ b/flake.nix
@@ -50,11 +50,7 @@
       };
     in
     {
-      overlays.default = final: prev: {
-        self = {
-          htmlformat = final.callPackage ./packages/htmlformat { };
-        };
-      };
+      overlays.default = import ./overlays/htmlformat;
 
       nixosConfigurations.prefect = nixpkgs.lib.nixosSystem {
         system = utils.lib.system.x86_64-linux;
@@ -135,6 +131,7 @@
       deploy = {
         remoteBuild = true;
         nodes.linde = {
+          remoteBuild = true;
           hostname = "linde";
           profiles.system = {
             user = "root";
diff --git a/overlays/cgit-pink/default.nix b/overlays/cgit-pink/default.nix
new file mode 100644
index 00000000..ba62b718
--- /dev/null
+++ b/overlays/cgit-pink/default.nix
@@ -0,0 +1,5 @@
+self: super: {
+  cgit-pink = super.cgit-pink.overrideAttrs (old: {
+    patches = [ ./cgit-pink.patch ];
+  });
+}
diff --git a/patches/cgit-pink.patch b/overlays/cgit-pink/set-default-branch-main.patch
index 0e91525e..0e91525e 100644
--- a/patches/cgit-pink.patch
+++ b/overlays/cgit-pink/set-default-branch-main.patch
diff --git a/overlays/emacs.nix b/overlays/emacs.nix
new file mode 100644
index 00000000..679e9a1d
--- /dev/null
+++ b/overlays/emacs.nix
@@ -0,0 +1,4 @@
+let
+  sources = import ../nix/sources.nix;
+in
+import sources.emacs-overlay
diff --git a/overlays/extra-packages.nix b/overlays/extra-packages.nix
new file mode 100644
index 00000000..d0717756
--- /dev/null
+++ b/overlays/extra-packages.nix
@@ -0,0 +1,36 @@
+self: super: {
+  emacsPackagesFor = emacs: (
+    (super.emacsPackagesFor emacs).overrideScope (
+      eself: esuper:
+        esuper // {
+          tabnine-capf = super.callPackage ../packages/tabnine-capf.nix {
+            inherit eself;
+          };
+        }
+    )
+  );
+  vimPlugins = super.vimPlugins.extend (final: prev: {
+    coc-tabnine =
+      let
+        inherit (super) tabnine;
+      in
+      prev.coc-tabnine.overrideAttrs {
+        buildInputs = [ tabnine ];
+
+        postFixup = ''
+          mkdir -p $target/binaries/${tabnine.version}
+          ln -s ${tabnine}/bin/ $target/binaries/${tabnine.version}/${tabnine.passthru.platform}
+        '';
+      };
+  });
+  enchant = super.enchant.overrideAttrs (old: {
+    configureFlags = old.configureFlags ++ [ "--without-hspell" ]
+      # builtins.filter (c: c != "--with-hspell") old.configureFlags
+      ++ self.lib.optional super.stdenv.isDarwin "--with-applespell"
+    ;
+    buildInputs =
+      builtins.filter (c: c.name != "hspell") old.buildInputs
+      ++ self.lib.optionals super.stdenv.isDarwin (with super.darwin.apple_sdk.frameworks; [ Cocoa ]);
+    propagatedBuildInputs = builtins.filter (c: c.name != "hspell") old.propagatedBuildInputs;
+  });
+}
diff --git a/overlays/firefox.nix b/overlays/firefox.nix
new file mode 100644
index 00000000..b3b346bf
--- /dev/null
+++ b/overlays/firefox.nix
@@ -0,0 +1,4 @@
+self: super: {
+  firefox-bin-unwrapped = super.firefox-bin-unwrapped.override { systemLocale = "en-GB"; };
+  firefox-devedition-bin-unwrapped = super.firefox-devedition-bin-unwrapped.override { systemLocale = "en-GB"; };
+}
diff --git a/overlays/htmlformat/default.nix b/overlays/htmlformat/default.nix
new file mode 100644
index 00000000..93292c76
--- /dev/null
+++ b/overlays/htmlformat/default.nix
@@ -0,0 +1,3 @@
+self: super: {
+  htmlformat = super.callPackage ./htmlformat.nix { };
+}
diff --git a/packages/htmlformat/default.nix b/overlays/htmlformat/htmlformat.nix
index aa124ee5..aa124ee5 100644
--- a/packages/htmlformat/default.nix
+++ b/overlays/htmlformat/htmlformat.nix
diff --git a/overlays/rofi.nix b/overlays/rofi.nix
new file mode 100644
index 00000000..53efd0f8
--- /dev/null
+++ b/overlays/rofi.nix
@@ -0,0 +1,7 @@
+self: super: {
+  rofi = super.rofi.overrideAttrs (oldAttrs: rec {
+    postInstall = ''
+      ln $out/bin/rofi $out/bin/dmenu
+    '';
+  });
+}
diff --git a/patches/ddclient-noipv4.patch b/patches/ddclient-noipv4.patch
deleted file mode 100644
index 09afd601..00000000
--- a/patches/ddclient-noipv4.patch
+++ /dev/null
@@ -1,79 +0,0 @@
-diff --git a/ddclient.in b/ddclient.in
-index 5e4759e..dd2fb58 100755
---- a/ddclient.in
-+++ b/ddclient.in
-@@ -431,7 +431,8 @@ my %variables = (
-         'proxy'               => setv(T_FQDNP, 0, 0, undef,                undef),
-         'protocol'            => setv(T_PROTO, 0, 0, 'dyndns2',            undef),
- 
--        'use'                 => setv(T_USE,   0, 0, 'ip',                 undef),
-+        'use'                 => setv(T_USE,   0, 0, 'disabled',           undef),
-+
-         'usev4'               => setv(T_USEV4, 0, 0, 'disabled',           undef),
-         'usev6'               => setv(T_USEV6, 0, 0, 'disabled',           undef),
-         'ip'                  => setv(T_IP,    0, 0, undef,                undef),
-@@ -489,7 +490,7 @@ my %variables = (
-         'password'            => setv(T_PASSWD,1, 0, '',                   undef),
-         'host'                => setv(T_STRING,1, 1, '',                   undef),
- 
--        'use'                 => setv(T_USE,   0, 0, 'ip',                 undef),
-+        'use'                 => setv(T_USE,   0, 0, 'disabled',           undef),
-         'if'                  => setv(T_IF,    0, 0, 'ppp0',               undef),
-         'web'                 => setv(T_STRING,0, 0, 'dyndns',             undef),
-         'web-skip'            => setv(T_STRING,0, 0, '',                   undef),
-@@ -1075,6 +1076,8 @@ sub main {
-         read_cache(opt('cache'), \%cache);
-         print_info() if opt('debug') && opt('verbose');
- 
-+        fatal("invalid argument '-use %s'; possible values are:\n%s", $opt{'use'}, join("\n", ip_strategies_usage()))
-+            unless exists $ip_strategies{lc opt('use')};
-         fatal("invalid argument '-use %s'; possible values are:\n%s", $opt{'use'}, join("\n", ip_strategies_usage()))
-             unless exists $ip_strategies{lc opt('use')};
-         if (defined($opt{'usev6'})) {
-@@ -1154,11 +1157,9 @@ sub update_nics {
-             next if $config{$h}{'protocol'} ne lc($s);
-             $examined{$h} = 1;
-             # we only do this once per 'use' and argument combination
--            my $use       = opt('use',   $h) // 'disabled';
--            my $usev4     = opt('usev4', $h) // 'disabled';
-+            my $use       = 'disabled';
-+            my $usev4     = 'disabled';
-             my $usev6     = opt('usev6', $h) // 'disabled';
--            $use          = 'disabled' if ($use eq 'no'); # backward compatibility
--            $usev6        = 'disabled' if ($usev6 eq 'no'); # backward compatibility
-             my $arg_ip    = opt('ip',    $h) // '';
-             my $arg_ipv4  = opt('ipv4',  $h) // '';
-             my $arg_ipv6  = opt('ipv6',  $h) // '';
-@@ -1592,18 +1593,6 @@ sub init_config {
-     ##
-     $opt{'quiet'} = 0 if opt('verbose');
- 
--    ## infer the IP strategy if possible
--    if (!$opt{'use'}) {
--        $opt{'use'} = 'web' if ($opt{'web'});
--        $opt{'use'} = 'if'  if ($opt{'if'});
--        $opt{'use'} = 'ip'  if ($opt{'ip'});
--    }
--    ## infer the IPv4 strategy if possible
--    if (!$opt{'usev4'}) {
--        $opt{'usev4'} = 'webv4' if ($opt{'webv4'});
--        $opt{'usev4'} = 'ifv4'  if ($opt{'ifv4'});
--        $opt{'usev4'} = 'ipv4'  if ($opt{'ipv4'});
--    }
-     ## infer the IPv6 strategy if possible
-     if (!$opt{'usev6'}) {
-         $opt{'usev6'} = 'webv6' if ($opt{'webv6'});
-@@ -5813,11 +5802,12 @@ sub nic_nsupdate_update {
-         ## nsupdate requires a port number to be separated by whitepace, not colon
-         $server =~ s/:/ /;
-         my $zone       = $config{$h}{'zone'};
--        my $ip         = $config{$h}{'wantip'};
-+        my $ip         = $config{$h}{'wantipv6'};
-         my $recordtype = '';
-         if (is_ipv6($ip)) {
-             $recordtype = 'AAAA';
-         } else {
-+            next;
-             $recordtype = 'A';
-         }
-         delete $config{$_}{'wantip'} foreach @hosts;
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 00000000..d2c4c458
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,3 @@
+{ system ? builtins.currentSystem }:
+
+(builtins.getFlake (toString ./.)).devShells.${system}.default
diff --git a/system/linde.nix b/system/linde.nix
index 96ff92f8..7afdca9c 100644
--- a/system/linde.nix
+++ b/system/linde.nix
@@ -242,13 +242,6 @@ in
 
   nixpkgs = {
     config.allowUnfree = true;
-    overlays = [
-      (self: super: {
-        cgit-pink = super.cgit-pink.overrideAttrs (old: {
-          patches = [ ../patches/cgit-pink.patch ];
-        });
-      })
-    ];
   };
 
   programs.fish = {
diff --git a/system/mba.nix b/system/mba.nix
index 43599eed..b49fe705 100644
--- a/system/mba.nix
+++ b/system/mba.nix
@@ -1,4 +1,4 @@
-{ inputs, ... }: {
+{ ... }: {
   imports = [
     ./settings/darwin.nix
     ./settings/programs/base.nix
@@ -39,7 +39,7 @@
 
   nix.linux-builder = {
     maxJobs = 4;
-    config = {
+    config = { pkgs, ... }: {
       virtualisation = {
         darwin-builder = {
           diskSize = 60 * 1024;
@@ -52,9 +52,7 @@
         ./settings/configuration/user.nix
         ./settings/programs/shell.nix
       ];
-      environment.systemPackages = with (import inputs.nixpkgs {
-        system = "aarch64-linux";
-      }); [
+      environment.systemPackages = with pkgs; [
         kitty.terminfo
         hello
       ];
diff --git a/system/nanopi.nix b/system/nanopi.nix
index 2d3551a4..3c4b4a0f 100755
--- a/system/nanopi.nix
+++ b/system/nanopi.nix
@@ -615,7 +615,6 @@ in
     };
   };
   nixpkgs.config.allowUnfree = true;
-  nixpkgs.overlays = [ ];
   system.autoUpgrade = {
     enable = false;
     dates = "01:00";
diff --git a/system/prefect.nix b/system/prefect.nix
index f4c542a3..47a497b6 100644
--- a/system/prefect.nix
+++ b/system/prefect.nix
@@ -15,6 +15,7 @@
     ./settings/hardware/systemd-boot.nix
     ./settings/hardware/nvidia-gpu.nix
     ./settings/hardware/keyboard.nix
+    ./settings/hardware/keyboard-lofree.nix
     ./settings/services/syncthing.nix
     ./settings/services/zeroconf.nix
     ./settings/user-interface.nix
diff --git a/system/settings/configuration/nix.nix b/system/settings/configuration/nix.nix
index 6b6d51b3..ff870540 100644
--- a/system/settings/configuration/nix.nix
+++ b/system/settings/configuration/nix.nix
@@ -1,4 +1,5 @@
 { config
+, lib
 , pkgs
 , ...
 }: {
@@ -22,7 +23,7 @@
     '';
 
     gc = {
-      automatic = true;
+      automatic = lib.mkDefault true;
       options = "--delete-older-than 14d";
     };
   };
diff --git a/system/settings/darwin.nix b/system/settings/darwin.nix
index 460d47bd..323b00d6 100644
--- a/system/settings/darwin.nix
+++ b/system/settings/darwin.nix
@@ -32,6 +32,17 @@
     allowUnfree = true;
   };
 
+  launchd.user.agents.lorri = lib.mkIf config.services.lorri.enable {
+    serviceConfig = {
+      RunAtLoad = lib.mkForce false;
+      Sockets = {
+        daemon = {
+          SockPathName = "${(builtins.getEnv "HOME")}/Library/Caches/com.github.target.lorri.lorri.lorri/daemon.socket";
+        };
+      };
+    };
+  };
+
   environment.launchDaemons = {
     "limit.maxfiles.plist" = {
       text = ''
diff --git a/system/settings/hardware/keyboard-lofree.nix b/system/settings/hardware/keyboard-lofree.nix
new file mode 100644
index 00000000..e342acc6
--- /dev/null
+++ b/system/settings/hardware/keyboard-lofree.nix
@@ -0,0 +1,9 @@
+{ ... }: {
+  systemd.tmpfiles.settings."fix-lofree-keyboard" = {
+    "/sys/module/hid_apple/parameters/fnmode" = {
+      w = {
+        argument = "2";
+      };
+    };
+  };
+}
diff --git a/system/settings/programs/base.nix b/system/settings/programs/base.nix
index efde273d..bfc81312 100644
--- a/system/settings/programs/base.nix
+++ b/system/settings/programs/base.nix
@@ -1,13 +1,13 @@
 { pkgs, ... }: {
+  services.lorri.enable = true;
   environment.systemPackages = with pkgs; [
-    nixpkgs-review
-    nix-output-monitor
-    cachix
     home-manager
     lzma
     lzop
     zstd
-  ];
+  ] ++ (lib.optionals (stdenv.isLinux) [
+    psmisc
+  ]);
   nix.settings = {
     substituters = [
       "https://nix-community.cachix.org"
diff --git a/system/settings/user-interface.nix b/system/settings/user-interface.nix
index 915c3ec4..e2784743 100644
--- a/system/settings/user-interface.nix
+++ b/system/settings/user-interface.nix
@@ -61,6 +61,15 @@
 
   programs.dconf.enable = true;
 
+  programs.nh = {
+    enable = true;
+    clean = {
+      enable = true;
+      extraArgs = "--keep-since 14d";
+    };
+  };
+  nix.gc.automatic = ! config.programs.nh.enable;
+
   imports = [
     ./services/xserver.nix
   ];
diff --git a/user/emacs/init.el b/user/emacs/init.el
index 22a9094e..966a2e74 100644
--- a/user/emacs/init.el
+++ b/user/emacs/init.el
@@ -27,7 +27,7 @@
 
 (defmacro quietly (&rest body)
   `(let ((inhibit-message t))
-		 ,@body))
+     ,@body))
 (defun quiet (original-function &rest args)
   (quietly (apply original-function args)))
 
@@ -244,12 +244,15 @@ With two prefix arguments, write out the day and month name."
       read-buffer-completion-ignore-case t
       read-file-name-completion-ignore-case t
       completion-styles '(flex substring basic)
-			completion-category-defaults nil
-			completion-category-overrides '((file (styles basic partial-completion))))
+      completion-category-defaults nil
+      completion-category-overrides '((file (styles basic partial-completion))))
 
 (use-package orderless
   :config (progn
-            (add-to-list 'completion-styles 'orderless)))
+            (add-to-list 'completion-styles 'orderless)
+            (setq orderless-matching-styles '(orderless-literal-prefix
+                                              orderless-prefixes
+                                              orderless-regexp))))
 
 (use-package consult
   :general ([remap isearch-forward] #'consult-line
@@ -435,9 +438,9 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
   :after evil
   :defer 2
   :config (progn
-            (add-hook 'js-ts-mode-hook (lambda ()
-                                         (define-and-bind-quoted-text-object "slash" "/" "\\/" "\\/")
-                                         (push '(?\/ . ("/" . "/")) evil-surround-pairs-alist)))
+            (add-hook 'js-base-mode-hook (lambda ()
+                                           (define-and-bind-quoted-text-object "slash" "/" "\\/" "\\/")
+                                           (push '(?\/ . ("/" . "/")) evil-surround-pairs-alist)))
             (add-hook 'emacs-lisp-mode-hook (lambda ()
                                               (push '(?` . ("`" . "'")) evil-surround-pairs-alist)))
             (global-evil-surround-mode +1)))
@@ -447,7 +450,7 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
   :after evil-surround
   :ghook ('LaTex-mode-hook #'embrace-LaTeX-mode-hook)
   :ghook ('org-mode-hook #'embrace-org-mode-hook)
-  :ghook ('ruby-ts-mode-hook #'embrace-ruby-mode-hook)
+  :ghook ('ruby-base-mode-hook #'embrace-ruby-mode-hook)
   :ghook ('emacs-lisp-mode-hook #'embrace-emacs-lisp-mode-hook)
   :config (progn
             (setq evil-embrace-show-help-p nil)
@@ -555,7 +558,9 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
 (use-package tabnine
   :config (progn
             (setq tabnine-binaries-folder "~/.local/tabnine")
-            (global-tabnine-mode)
+            (with-demoted-errors "TabNine error: %s"
+              (when (tabnine--executable-path)
+                (global-tabnine-mode)))
 
             (define-key tabnine-completion-map (kbd "TAB") #'tabnine-accept-completion)
             (define-key tabnine-completion-map (kbd "<tab>") #'tabnine-accept-completion)
@@ -714,9 +719,9 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
 
 ;;; Editing
 
-(setq-default indent-tabs-mode nil
-              tab-width 2
-              tab-always-indent 'complete)
+(setq-default tab-always-indent 'complete
+              indent-tabs-mode nil
+              tab-width 4)
 
 (electric-pair-mode +1)
 
@@ -737,22 +742,13 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
 
 ;;; Major modes
 
-(setq major-mode-remap-alist '((c-mode . c-ts-mode)
-                               (c++-mode . c++-ts-mode)
-                               (c-or-c++-mode . c-or-c++-ts-mode)
-                               (cmake-mode . cmake-ts-mode)
-                               (csharp-mode . csharp-ts-mode)
-                               (dockerfile-mode . dockerfile-ts-mode)
-                               (go-mode . go-ts-mode)
-                               (java-mode . java-ts-mode)
-                               (python-mode . python-ts-mode)
-                               (ruby-mode . ruby-ts-mode)
-                               (toml-mode . toml-ts-mode)
-                               (yaml-mode . yaml-ts-mode)))
+;;;; tree-sitter
+(use-package treesit-auto
+  :config (progn
+            (global-treesit-auto-mode)
+            (treesit-auto-add-to-auto-mode-alist)))
 
 ;;;; golang
-(with-eval-after-load 'go-ts-mode
-  (setq go-ts-mode-indent-offset tab-width))
 (with-eval-after-load 'project
   (add-to-list 'project-vc-extra-root-markers "go.mod"))
 
@@ -763,29 +759,10 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
             (add-to-list 'eglot-server-programs
                          '(nim-mode "nimlsp"))))
 
-;;;; rust
-(use-package rustic
-  :mode (("\\.rs\\'" . rustic-mode))
-  :if (package-installed-p 'rustic)
-  :config (progn
-            (setq rustic-format-on-save t)
-            (with-eval-after-load 'flycheck
-              (add-to-list 'flycheck-checkers 'rustic-clippy))))
-(add-to-list 'major-mode-remap-alist '(rust-mode . rust-ts-mode))
-
 ;;;; js
-(setq js-indent-level 2
-      js-enabled-frameworks '(javascript))
-(add-to-list 'major-mode-remap-alist '(js-mode . js-ts-mode))
-(add-to-list 'major-mode-remap-alist '(json-mode . json-ts-mode))
+(setq js-enabled-frameworks '(javascript))
 
 ;;;; typescript
-(use-package typescript-mode
-  :mode (("\\.tsx\\'" . tsx-ts-mode))
-  :config (progn
-            (setq typescript-indent-level 2
-                  typescript-ts-mode-indent-offset 2)))
-(add-to-list 'major-mode-remap-alist '(typescript-mode . typescript-ts-mode))
 
 (use-package astro-ts-mode
   :mode (("\\.astro\\'" . astro-ts-mode)))
@@ -805,8 +782,7 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
 (add-to-list 'auto-mode-alist '("\\.zsh\\'" . shell-script-mode))
 (add-to-list 'auto-mode-alist '("zshenv\\'" . shell-script-mode))
 (add-to-list 'auto-mode-alist '("zshrc\\'"  . shell-script-mode))
-(setq sh-shell-file "/usr/bin/env zsh"
-      sh-basic-offset 2)
+(setq sh-shell-file "/usr/bin/env zsh")
 
 (add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)
 
@@ -818,16 +794,14 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
   :config (progn
             (setq fish-enable-auto-indent t)))
 
-;;;; make
-(general-add-hook 'makefile-mode-hook
-                  (lambda ()
-                    (setq-local indent-tabs-mode t)))
-
 ;;;; nix
 (with-eval-after-load 'nix-mode
   (setq nix-mode-use-smie t
         nix-indent-function #'smie-indent-line))
 
+(use-package nix-ts-mode
+  :mode (("\\.nix\\'" . nix-ts-mode)))
+
 (use-package nix-update
   :commands (nix-update-fetch))
 
@@ -858,11 +832,6 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
   :ghook '(clojure-mode-hook
            emacs-lisp-mode-hook))
 
-(use-package lispy
-  :ghook '(emacs-lisp-mode-hook
-           clojure-mode-hook
-           racket-mode-hook))
-
 (use-package lispyville
   :ghook '(emacs-lisp-mode-hook
            clojure-mode-hook
@@ -880,20 +849,15 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
 ;;;; web modes (html)
 
 (use-package css-mode
-  :defer t
-  :config (progn
-            (setq css-indent-offset 2)))
-(add-to-list 'major-mode-remap-alist '(css-mode . css-ts-mode))
+  :defer t)
 
 (use-package web-mode
-  :mode (("\\.html?.erb\\'" . web-mode))
+  :mode (("\\.html?.erb\\'" . web-mode)
+         ("\\.gotmpl\\'" . web-mode))
   :config (setq web-mode-enable-auto-pairing nil
-                web-mode-code-indent-offset 2
-                web-mode-markup-indent-offset 2
-                web-mode-css-indent-offset 2
                 web-mode-style-padding 2
                 web-mode-script-padding 2
-                web-mode-engines-alist '(("go" . "\\.html?\\'"))))
+                web-mode-engines-alist '(("go" . "\\.gotmpl\\'"))))
 
 (use-package emmet-mode
   :ghook '(web-mode-hook sgml-mode-hook))
@@ -948,21 +912,6 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
               (evil-ex-define-cmd "pb" #'project-switch-to-buffer)
               (evil-ex-define-cmd "psw[itch]" #'project-switch-project))))
 
-(use-package ibuffer-project
-  :config (progn
-            (defun ibuffer-project-set-filter-groups ()
-              (setq ibuffer-filter-groups (ibuffer-project-generate-filter-groups))
-              (unless (eq ibuffer-sorting-mode 'project-file-relative)
-                (ibuffer-do-sort-by-project-file-relative)))
-            (add-hook 'ibuffer-hook #'ibuffer-project-set-filter-groups)
-            (add-to-list 'ibuffer-project-root-functions '(file-remote-p . "Remote"))
-            (setq ibuffer-formats '((mark modified read-only locked " "
-                                          (name 18 18 :left :elide)
-                                          " "
-                                          (size 9 -1 :right)
-                                          " "
-                                          (mode 16 16 :left :elide)
-                                          " " project-file-relative)))))
 (use-package consult-ghq
   :defer 5
   :general (:keymaps 'project-prefix-map
@@ -974,13 +923,12 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
 (use-package envrc
   :defer 2
   :config (progn
+            (setq envrc-show-summary-in-minibuffer nil)
             (envrc-global-mode)))
 
 (use-package magit
   :defer 5
   :commands (magit-status magit-dispatch)
-  :init (progn
-          (customize-set-value 'magit-auto-revert-mode nil))
   :general ([remap project-vc-dir] #'magit-project-status)
   (:keymaps 'project-prefix-map "m" #'magit-project-status)
   :init (progn
@@ -988,7 +936,8 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
             (add-to-list 'project-switch-commands '(magit-project-status "Magit") t)))
   :config (progn
             (setq magit-section-visibility-indicator nil
-                  magit-diff-refine-hunk 'all
+                  magit-diff-refine-hunk t
+                  magit-auto-revert-immediately t
                   magit-display-buffer-function #'magit-display-buffer-fullcolumn-most-v1)
             (remove-hook 'magit-status-sections-hook 'magit-insert-tags-header)
             (remove-hook 'magit-section-highlight-hook 'magit-section-highlight)
@@ -996,10 +945,6 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
             (remove-hook 'magit-section-highlight-hook 'magit-diff-highlight)
             (require 'magit-extras)))
 
-(use-package magit-filenotify
-  :after magit
-  :ghook '(magit-status-mode-hook))
-
 (use-package git-gutter-fringe
   :defer 5
   :config (progn
@@ -1037,7 +982,11 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
             conf-mode-hook))
   :general ([remap ispell-word] #'jinx-correct-word
             [remap evil-prev-flyspell-error] #'jinx-previous
-            [remap evil-next-flyspell-error] #'jinx-next))
+            [remap evil-next-flyspell-error] #'jinx-next)
+  :config (progn
+            (advice-add 'jinx--load-dicts :after (lambda ()
+                                                   (unless jinx--dicts
+                                                     (global-jinx-mode -1))))))
 
 (use-package feature-mode
   :defer t
@@ -1049,32 +998,57 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
   :config (progn
             (setq treemacs-no-png-images t)))
 
+(if (boundp 'typescript-mode-hook)
+    (defvaralias 'typescript-ts-mode-hook 'typescript-mode-hook))
+
+(if (boundp 'dockerfile-mode-hook)
+    (defvaralias 'dockerfile-ts-mode-hook 'dockerfile-mode-hook))
+
+(if (boundp 'yaml-mode-hook)
+    (defvaralias 'yaml-ts-mode-hook 'yaml-mode-hook))
+
+(if (boundp 'go-mode-hook)
+    (defvaralias 'go-ts-mode-hook 'go-mode-hook))
+
+(if (boundp 'nix-mode-hook)
+    (defvaralias 'nix-ts-mode-hook 'nix-mode-hook))
+
 (use-package eglot
   :defer 3
   :general (:states 'normal :keymaps 'eglot-mode-map
                     "gd" #'xref-find-definitions
                     "gr" #'xref-find-references
                     "C-t" #'xref-pop-marker-stack)
-  :ghook ('(typescript-ts-mode-hook
-            dockerfile-ts-mode-hook
-            yaml-ts-mode-hook
-            js-ts-mode-hook
-            css-ts-mode-hook
-            go-ts-mode-hook
+  :ghook ('(typescript-mode-hook
+            dockerfile-mode-hook
+            yaml-mode-hook
+            js-base-mode-hook
+            css-base-mode-hook
+            go-mode-hook
             lua-mode-hook
             nim-mode-hook
-            scss-mode-hook
             html-mode-hook
             nix-mode-hook
             haskell-mode-hook)
           #'eglot-ensure)
   :config (progn
+            (when (assoc 'nix-mode eglot-server-programs)
+              (setf (car (assoc 'nix-mode eglot-server-programs)) '(nix-mode nix-ts-mode)))
+            (advice-add 'eglot--message :before-while (lambda (formatstring &rest rest)
+                                                        (s-starts-with-p "Connected!" formatstring)))
             (defun my/setup-eglot-eldoc ()
               (push 'flymake-eldoc-function eldoc-documentation-functions))
             (add-hook 'eglot-managed-mode-hook 'my/setup-eglot-eldoc)
+            (setf (alist-get '(go-mode go-dot-mod-mode go-dot-work-mode go-ts-mode go-mod-ts-mode)
+                             eglot-server-programs
+                             nil nil #'equal)
+                  (eglot-alternatives '("golangci-lint-langserver"
+                                        "gopls" )))
             (setq-default eglot-workspace-configuration
-                          '(:yaml (:keyOrdering nil)
-                                  :nix (:autoArchive t))
+                          '( :yaml (:keyOrdering nil)
+                             :nix (:autoArchive t)
+                             :gopls ( :staticcheck t
+                                      :usePlaceholders t))
                           eglot-ignored-server-capabilities '(:documentHighlightProvider))
             (defun my/eglot-capf ()
               (setq-local completion-at-point-functions
@@ -1098,35 +1072,38 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
 
 (use-package add-node-modules-path
   :config (setq add-node-modules-max-depth 6)
-  :ghook ('(feature-mode-hook js2-mode-hook json-ts-mode-hook typescript-ts-mode-hook) #'add-node-modules-path))
+  :ghook ('(feature-mode-hook
+            js-base-mode-hook
+            json-ts-mode-hook
+            typescript-ts-mode-hook)
+          #'add-node-modules-path))
 
 ;;;; Reformat on save
 
 (use-package format-all
   :defer 10
-  :ghook ('(clojure-mode-hook
-            dockerfile-ts-mode-hook
-            emacs-lisp-mode-hook
-            json-ts-mode-hook
-            markdown-mode-hook
-            sql-mode-hook
-            toml-mode-hook))
+  :ghook ('prog-mode-hook)
   :gfhook #'format-all-ensure-formatter
   :init (progn
           (advice-add 'format-all-ensure-formatter
                       :around #'quiet)
           (defun turn-off-format-all-mode ()
-            (format-all-mode -1)))
+            (when format-all-mode
+              (format-all-mode -1))))
   :config (progn
-            (setq format-all-show-errors 'never)))
+            (setq format-all-show-errors nil)))
 
 (use-package apheleia
-  :defer 10
+  :defer 11                             ; load after format-all for hook ordering?
+  :ghook 'prog-mode-hook
   :config (progn
             (setf (alist-get 'shfmt apheleia-formatters)
                   '("shfmt"))
-            (setf (alist-get 'nixfmt apheleia-formatters)
-                  '("nixpkgs-fmt"))
+            (setq apheleia-formatters (append apheleia-formatters '((nixpkgs-fmt "nixpkgs-fmt"))))
+            (setf (alist-get 'go-ts-mode apheleia-mode-alist)
+                  '(goimports))
+            (setq apheleia-mode-alist (append apheleia-mode-alist '((nix-ts-mode . nixpkgs-fmt)
+                                                                    (nix-mode . nixpkgs-fmt))))
             (add-hook 'apheleia-mode-hook #'turn-off-format-all-mode))
   :init (progn
           (apheleia-global-mode +1)))
@@ -1157,7 +1134,7 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
   "fs" #'save-buffer
   "ff" #'find-file
   "fw" #'write-file
-  "fd" #'delete-file
+  "fd" #'crux-delete-file-and-buffer
   "fr" #'crux-rename-file-and-buffer
   "gs" #'magit-status
   "gm" #'vc-msg-show
@@ -1169,7 +1146,6 @@ _C-k_: prev  _u_pper              _=_: upper/lower       _s_mart resolve
   "go" #'git-gutter:revert-hunk
   "gt" #'git-timemachine
   "gl" #'magit-log-buffer-file
-  "bi" #'ibuffer
   "bz" #'bury-buffer
   "iu" #'insert-char
   "xe" #'eval-last-sexp
diff --git a/user/mba.nix b/user/mba.nix
index 5c6248c2..a205fea4 100644
--- a/user/mba.nix
+++ b/user/mba.nix
@@ -5,7 +5,6 @@
     ./settings/development/javascript.nix
     ./settings/development/golang.nix
     ./settings/development/lisp.nix
-    ./settings/development/nim.nix
     ./settings/development/web.nix
     ./settings/darwin.nix
     ./settings/emacs.nix
diff --git a/user/modules/tabnine.nix b/user/modules/tabnine.nix
index a702cf29..3eee4834 100644
--- a/user/modules/tabnine.nix
+++ b/user/modules/tabnine.nix
@@ -5,6 +5,7 @@
 }:
 with lib; let
   inherit (pkgs) stdenv;
+  tomlFormat = pkgs.formats.toml { };
   cfg = config.programs.tabnine;
   lspConfigFile = config:
     pkgs.runCommand "TabNine.toml"
@@ -52,7 +53,7 @@ in
     };
 
     lspConfig = mkOption {
-      type = types.attrs;
+      type = tomlFormat.type;
       default = { };
       description = ''
         LSP Server configuration written to
@@ -64,7 +65,7 @@ in
 
   config = mkIf cfg.enable {
     home.file."${cfg.configDir}/TabNine.toml" = {
-      source = lspConfigFile cfg.lspConfig;
+      source = (tomlFormat.generate "TabNine.toml" cfg.lspConfig);
     };
     home.file."${cfg.configDir}/tabnine_config.json" = {
       source = pkgs.writeText "tabnine_config.json" (builtins.toJSON cfg.config);
@@ -84,10 +85,10 @@ in
       epkgs.tabnine
     ];
     programs.emacs.extraConfig = ''
+      (defun my/override-tabnine-exe-path (&rest args)
+        "${pkgs.tabnine}/bin/TabNine")
       (with-eval-after-load 'tabnine
-        (advice-add 'tabnine--executable-path :around
-          (lambda (original-function &rest args)
-            "${pkgs.tabnine}/bin/TabNine")))
+        (advice-add 'tabnine--executable-path :override #'my/override-tabnine-exe-path))
     '';
   };
 }
diff --git a/user/nvim/init.lua b/user/nvim/init.lua
index faf6ca5b..f7bb020a 100644
--- a/user/nvim/init.lua
+++ b/user/nvim/init.lua
@@ -1,9 +1,6 @@
 vim.opt.autoindent = true
 
 vim.opt.background = "light"
-vim.opt.shiftwidth = 2
-vim.opt.tabstop = 2
-vim.opt.expandtab = false
 vim.opt.number = true
 
 vim.g.mapleader = ","
diff --git a/user/overlays/extra-packages.nix b/user/overlays/extra-packages.nix
deleted file mode 100644
index 19490dca..00000000
--- a/user/overlays/extra-packages.nix
+++ /dev/null
@@ -1,12 +0,0 @@
-self: super: {
-  emacsPackagesFor = emacs: (
-    (super.emacsPackagesFor emacs).overrideScope (
-      eself: esuper:
-        esuper // {
-          tabnine-capf = super.callPackage ../packages/tabnine-capf.nix {
-            inherit eself;
-          };
-        }
-    )
-  );
-}
diff --git a/user/prefect.nix b/user/prefect.nix
index 181d0590..b5c4789e 100644
--- a/user/prefect.nix
+++ b/user/prefect.nix
@@ -7,15 +7,11 @@
     ./settings/dunst.nix
     ./settings/emacs.nix
     ./settings/development/base.nix
-    ./settings/development/clojure.nix
     ./settings/development/lisp.nix
     ./settings/development/golang.nix
     ./settings/development/javascript.nix
-    ./settings/development/nim.nix
-    ./settings/development/rust.nix
     ./settings/development/web.nix
     ./settings/fish.nix
-    ./settings/gaming.nix
     ./settings/git.nix
     ./settings/gnupg.nix
     ./settings/i3.nix
diff --git a/user/settings/base.nix b/user/settings/base.nix
index 7baeed1e..6725b6db 100644
--- a/user/settings/base.nix
+++ b/user/settings/base.nix
@@ -72,6 +72,7 @@
     ];
     config = {
       theme = "ansi";
+      style = "header-filename,header-filesize,grid,rule";
     };
   };
   programs.nix-index-database.comma.enable = true;
diff --git a/user/settings/development/base.nix b/user/settings/development/base.nix
index dcbf370f..0630a5a6 100644
--- a/user/settings/development/base.nix
+++ b/user/settings/development/base.nix
@@ -9,13 +9,10 @@
     [
       shellcheck
       shfmt
-      python3Packages.yamllint
       nodePackages.dockerfile-language-server-nodejs
       nodePackages.vscode-json-languageserver
       nodePackages.yaml-language-server
       lua-language-server
-      rubyPackages.solargraph
-      multimarkdown
 
       license-cli
       just
@@ -49,6 +46,32 @@
     LIMA_INSTANCE = "nixos";
   };
 
+  editorconfig = {
+    enable = true;
+    settings = {
+      "*" = {
+        charset = "utf-8";
+        end_of_line = "lf";
+        trim_trailing_whitespace = true;
+        insert_final_newline = true;
+        indent_style = "space";
+        indent_size = 2;
+        tab_width = 4;
+      };
+      justfile = {
+        indent_style = "tab";
+        tab_width = 4;
+      };
+      Makefile = {
+        indent_style = "tab";
+        tab_width = 4;
+      };
+      "*.{yaml,yml}" = {
+        indent_size = 4;
+      };
+    };
+  };
+
   home.shellAliases = {
     er = "direnv reload";
     ea = "direnv allow";
@@ -60,15 +83,27 @@
     nix-direnv = {
       enable = true;
     };
+    config = {
+      global = {
+        disable_stdin = true;
+        strict_env = true;
+        hide_env_diff = true;
+      };
+      whitelist = {
+        prefix = with config.home; [
+          "${homeDirectory}/projects/alanpearce.eu"
+        ];
+      };
+    };
+    stdlib = ''
+      declare -A direnv_layout_dirs
+      direnv_layout_dir() {
+        echo "''${direnv_layout_dirs[$PWD]:=$(
+          local hash="$(${pkgs.coreutils}/bin/sha256sum - <<<"''${PWD}" | cut -c-7)"
+      		local path="''${PWD//[^a-zA-Z0-9]/-}"
+          echo "${config.xdg.cacheHome}/direnv/layouts/''${hash}''${path}"
+        )}"
+      }
+    '';
   };
-  xdg.configFile."direnv/direnvrc".text = ''
-    declare -A direnv_layout_dirs
-    direnv_layout_dir() {
-      echo "''${direnv_layout_dirs[$PWD]:=$(
-        local hash="$(${pkgs.coreutils}/bin/sha256sum - <<<"''${PWD}" | cut -c-7)"
-    		local path="''${PWD//[^a-zA-Z0-9]/-}"
-        echo "${config.xdg.cacheHome}/direnv/layouts/''${hash}''${path}"
-      )}"
-    }
-  '';
 }
diff --git a/user/settings/development/golang.nix b/user/settings/development/golang.nix
index b554bd5c..e5cd9199 100644
--- a/user/settings/development/golang.nix
+++ b/user/settings/development/golang.nix
@@ -4,6 +4,8 @@
     gopls
     gotools
     golines
+    golangci-lint
+    golangci-lint-langserver
   ];
   programs.emacs.extraPackages = epkgs: (with epkgs; [
     go-eldoc
diff --git a/user/settings/development/javascript.nix b/user/settings/development/javascript.nix
index bea1f02c..4d196cb4 100644
--- a/user/settings/development/javascript.nix
+++ b/user/settings/development/javascript.nix
@@ -3,21 +3,11 @@
 , ...
 }:
 {
-  home.packages =
-    (with pkgs; [
-      pnpm-shell-completion
-      bunyan-rs
-    ])
-    ++ (with pkgs.nodePackages; [
-      node2nix
-      nodemon
-      javascript-typescript-langserver
-      typescript-language-server
-      eslint_d
-      typescript
-      pnpm
-      npm-merge-driver
-    ]);
+  home.packages = with pkgs.nodePackages; [
+    node2nix
+    javascript-typescript-langserver
+    typescript-language-server
+  ];
 
   home.sessionVariables = {
     NO_UPDATE_NOTIFIER = "1"; # stop npm update-notifier
@@ -35,55 +25,9 @@
 
   programs.emacs.extraPackages = epkgs: (with epkgs; [
     add-node-modules-path
-    js2-mode
-    rjsx-mode
-    tide
-    typescript-mode
   ]);
 
   home.shellAliases = {
-    ava = "bunx ava";
-    avt = "bunx ava --tap";
-    avat = "bunx ava --tap";
-    avaw = "bunx ava --watch";
-    avaf = "bunx ava --fail-fast";
-    avafw = "bunx ava --fail-fast --watch";
-    avawf = "bunx ava --fail-fast --watch";
-    pino = "bunyan";
-    mocha = "bunx mocha";
-    standard = "bunx standard";
-    tsc = "bunx tsc";
-    tslint = "bunx tslint";
-    tsnode = "bunx ts-node";
-
-    p = "pnpm";
-    pi = "pnpm install --filter=.";
-    pit = "pnpm install-test --filter=.";
-    pl = "pnpm ls";
-    pr = "pnpm run";
-    pb = "pnpm run build";
-    prb = "pnpm run build";
-    pbd = "pnpm multi run build --filter={.}...";
-    pmi = "pnpm multi install";
-    pmx = "pnpm multi exec "; # expand command aliases
-    pmr = "pnpm multi run";
-    pa = "pnpm add";
-    pad = "pnpm add --save-dev";
-    pd = "pnpm uninstall";
-    pou = "pnpm outdated";
-    pt = "pnpm test";
-    pmt = "pnpm multi test";
-    pmd = "pnpm multi uninstall";
-    pmit = "pnpm multi install-test";
-    pup = "pnpm update";
-    pupl = "pnpm update --latest";
-    ppr = "pnpm prune";
-    pprp = "pnpm prune --production";
-    pli = "pnpm link";
-    pdi = "pnpm dislink";
-    pul = "pnpm unlink";
-    px = "pnpx";
-
     bn = "bun";
     bni = "bun install";
     bna = "bun add";
@@ -130,7 +74,6 @@
   xdg.configFile."npm/config".text = ''
     prefix=''${HOME}/.local
     cache=${config.xdg.cacheHome}/npm/
-    store-dir=${config.xdg.cacheHome}/pnpm/
     always-auth=true
     sign-git-tag=true
     rebuild-bundle=false
diff --git a/user/settings/development/lisp.nix b/user/settings/development/lisp.nix
index 757a77ef..ec083cfc 100644
--- a/user/settings/development/lisp.nix
+++ b/user/settings/development/lisp.nix
@@ -3,6 +3,7 @@
 , ...
 }: {
   home.packages = with pkgs; [
+    clisp
     sbcl
     lispPackages.quicklisp
     asdf
diff --git a/user/settings/development/rust.nix b/user/settings/development/rust.nix
index 46f3f4f1..c1b1a9df 100644
--- a/user/settings/development/rust.nix
+++ b/user/settings/development/rust.nix
@@ -10,7 +10,4 @@
     rust-analyzer
     clippy
   ];
-  programs.emacs.extraPackages = epkgs: (with epkgs; [
-    rustic
-  ]);
 }
diff --git a/user/settings/development/web.nix b/user/settings/development/web.nix
index 7570cadb..d7d0c2eb 100644
--- a/user/settings/development/web.nix
+++ b/user/settings/development/web.nix
@@ -10,7 +10,7 @@
     prettier
   ] ++ (with pkgs; [
     flyctl
-    self.htmlformat
+    htmlformat
   ]);
   home.shellAliases = {
     # 0.2.25 current completion command only affects `flyctl`, although `fly` is a link to `flyctl`
@@ -18,11 +18,8 @@
   };
   programs.emacs.extraPackages = epkgs: (with epkgs; [
     caddyfile-mode
-    company-web
     emmet-mode
     nginx-mode
-    restclient
-    scss-mode
     web-mode
   ]);
   programs.neovim.plugins = with pkgs.vimPlugins; [
diff --git a/user/settings/development/zig.nix b/user/settings/development/zig.nix
index e5fab030..ac21267f 100644
--- a/user/settings/development/zig.nix
+++ b/user/settings/development/zig.nix
@@ -2,6 +2,9 @@
 , pkgs
 , ...
 }: {
+  home.packages = with pkgs; [
+    zls
+  ];
   programs.emacs.extraPackages = epkgs: (with epkgs; [
     zig-mode
   ]);
diff --git a/user/settings/emacs.nix b/user/settings/emacs.nix
index 8ce0c7d6..9c980848 100644
--- a/user/settings/emacs.nix
+++ b/user/settings/emacs.nix
@@ -31,7 +31,7 @@ in
     "*.el diff=elisp"
   ];
   programs.git.extraConfig."diff.elisp" = {
-    xfuncname = "^\\((((def\\S+)|use-package)\\s+\\S+)";
+    xfuncname = "^(((;;;+ )|\\(|([ \t]+\\(((cl-|el-patch-)?def(un|var|macro|method|custom)|gb/))).*)$";
   };
 
   programs.emacs = {
@@ -83,7 +83,6 @@ in
         crux
         dired-git-info
         docker-compose-mode
-        dockerfile-mode
         dtrt-indent
         envrc
         editorconfig
@@ -122,20 +121,17 @@ in
         git-timemachine
         goto-chg
         helpful
-        ibuffer-project
         jinx
         just-mode
         justl
-        json-mode
         kind-icon
         lua-mode
-        lispy
         lispyville
         magit
-        magit-filenotify
         markdown-mode
         marginalia
         nerd-icons
+        nix-ts-mode
         orderless
         doom-modeline
         php-mode
@@ -149,15 +145,14 @@ in
         tempel
         tempel-collection
         eglot-tempel
-        toml-mode
         treesit-grammars.with-all-grammars
+        treesit-auto
         vc-msg
         vertico
         vertico-prescient
         wgrep-ag
         ws-butler
         which-key
-        yaml-mode
       ]);
     extraConfig = ''
       (with-eval-after-load 'editorconfig
@@ -175,6 +170,7 @@ in
   };
   home.packages = with pkgs; [
     editorScript
+    enchant
   ];
   xdg.configFile."raycast/scripts/Emacs" = {
     executable = true;
diff --git a/user/settings/fish.nix b/user/settings/fish.nix
index 8ed80e3e..a487418c 100644
--- a/user/settings/fish.nix
+++ b/user/settings/fish.nix
@@ -4,38 +4,32 @@
 }: {
   programs.fish = {
     enable = true;
-    plugins = [
-      {
-        name = "tide";
-        src = pkgs.fetchFromGitHub {
-          # https://github.com/IlanCosman/tide
-          owner = "IlanCosman";
-          repo = "tide";
-          rev = "a3426e157f94b8a9cb5bcf96946b1e55625a1948";
-          sha256 = "1fwqmsrd6bpf67rgj6f362abjmpk6q8yynyskc4niwg3g15diqq5";
-        };
-      }
-      {
-        name = "fzf";
-        src = pkgs.fetchFromGitHub {
-          owner = "PatrickF1";
-          repo = "fzf.fish";
-          rev = "6d00ecc6e5b2b1313cfcb25515941ecfd5342b30";
-          sha256 = "1sd5f6707hys6dibs1zb6f1imlkspqad5i24j4gf7lk9cby0zh6i";
-        };
-      }
-      {
-        name = "ghq";
-        src = pkgs.fetchFromGitHub {
-          owner = "decors";
-          repo = "fish-ghq";
-          rev = "cafaaabe63c124bf0714f89ec715cfe9ece87fa2";
-          sha256 = "0cv7jpvdfdha4hrnjr887jv1pc6vcrxv2ahy7z6x562y7fd77gg9";
-        };
-      }
-    ];
+    plugins =
+      let
+        fromNixpkgs = pkg: { name = pkg.name; src = pkg.src; };
+      in
+      with pkgs.fishPlugins; [
+        (fromNixpkgs tide)
+        (fromNixpkgs fzf-fish)
+        (fromNixpkgs autopair)
+        {
+          name = "ghq";
+          src = pkgs.fetchFromGitHub {
+            owner = "decors";
+            repo = "fish-ghq";
+            sha256 = "0cv7jpvdfdha4hrnjr887jv1pc6vcrxv2ahy7z6x562y7fd77gg9";
+            # date = "2021-07-16T13:17:09+09:00";
+            rev = "cafaaabe63c124bf0714f89ec715cfe9ece87fa2";
+          };
+        }
+      ];
+    # TODO: pre-generate nix-your-shell
     interactiveShellInit = ''
+      ${pkgs.nix-your-shell}/bin/nix-your-shell --nom fish env | source
       bind \es __ghq_repository_search
+      # don't bind ctrl-t, it does nice things on macOS/BSD
+      set FZF_CTRL_T_COMMAND
+      set --export FZF_DEFAULT_OPTS '--cycle --layout=reverse --border --height=90% --preview-window=wrap --marker="*"'
       fzf_configure_bindings --directory=\cx\cf
     '';
     shellAliases = {
@@ -51,7 +45,24 @@
     functions = {
       ds = "du -hd1 $argv[1] | sort -h";
       last_history_item = "echo $history[1]";
-    };
+    } // (lib.attrsets.optionalAttrs pkgs.stdenv.isLinux {
+      open = ''
+        argparse h/help a/application -- $argv
+        or return
+
+        if set -ql _flag_help
+           echo "open [-h|--help] [-a application] [arguments...]"
+           return 1
+        end
+
+        if set -ql _flag_application
+           # TODO: support reverse-domain- named files (e.g. org.kde.kate.desktop)
+           ${pkgs.gtk3}/bin/gtk-launch $argv[1]
+        else
+          xdg-open $argv
+        end
+      '';
+    });
   };
   xdg.configFile."fish/completions" = {
     recursive = true;
diff --git a/user/settings/gaming.nix b/user/settings/gaming.nix
deleted file mode 100644
index 745c1a3e..00000000
--- a/user/settings/gaming.nix
+++ /dev/null
@@ -1,12 +0,0 @@
-{ config
-, pkgs
-, ...
-}: {
-  home.packages = with pkgs; [
-    wineWowPackages.stable
-    # winetricks
-
-    lutris
-    (discord.override { withOpenASAR = true; })
-  ];
-}
diff --git a/user/settings/git.nix b/user/settings/git.nix
index f53d33a9..e2965724 100644
--- a/user/settings/git.nix
+++ b/user/settings/git.nix
@@ -41,9 +41,6 @@
         algorithm = "patience";
         colorMoved = "default";
       };
-      "difftool.sopsdiffer" = {
-        textconf = "${pkgs.sops}/bin/sops -d";
-      };
       remote = {
         autoSetupMerge = true;
       };
diff --git a/user/settings/kitty.nix b/user/settings/kitty.nix
index 814ce54c..c1de50d8 100644
--- a/user/settings/kitty.nix
+++ b/user/settings/kitty.nix
@@ -12,6 +12,10 @@
     shellIntegration = {
       mode = "no-cursor";
     };
+    keybindings = {
+      "ctrl+shift+t" = "new_tab_with_cwd !neighbor";
+      "cmd+t" = "new_tab_with_cwd !neighbor";
+    };
     settings = {
       macos_option_as_alt = "left";
     };
diff --git a/user/settings/nix.nix b/user/settings/nix.nix
index ad31a47e..13ca21a2 100644
--- a/user/settings/nix.nix
+++ b/user/settings/nix.nix
@@ -10,21 +10,24 @@ in
     ../../pin.nix
   ];
   nixpkgs.config = import ../config.nix;
+
   home.packages = with pkgs; [
     nil
     nix-prefetch-scripts
     nix-init
     nix-update
+    nix-tree
     common-updater-scripts
     nixpkgs-fmt
+    nixpkgs-lint
+    nixpkgs-review
+    nix-output-monitor
+    cachix
   ];
   xdg.configFile."nix-init/config.toml".source = toml.generate "config.toml" {
     maintainers = [ "alanpearce" ];
     nixpkgs = "builtins.getFlake \"nixpkgs\"";
   };
-  nixpkgs.overlays = [
-    (import ../overlays/extra-packages.nix)
-  ];
   programs.emacs.extraPackages = epkgs: (with epkgs; [
     nix-mode
     nix-update
diff --git a/user/settings/nixos.nix b/user/settings/nixos.nix
index bae37c56..d30d6a3d 100644
--- a/user/settings/nixos.nix
+++ b/user/settings/nixos.nix
@@ -5,9 +5,9 @@
   ];
 
   home.shellAliases = {
-    srb = "sudo nixos-rebuild";
-    rbs = "sudo nixos-rebuild switch --fast";
-    rbb = "sudo nixos-rebuild boot";
-    rbr = "sudo nixos-rebuild switch --rollback";
+    srb = "nh os";
+    rbs = "nh os switch --fast";
+    rbb = "nh os boot";
+    rbr = "nh os switch --rollback";
   };
 }
diff --git a/user/settings/nixpkgs.nix b/user/settings/nixpkgs.nix
index 9f8af5c8..992f6742 100644
--- a/user/settings/nixpkgs.nix
+++ b/user/settings/nixpkgs.nix
@@ -10,10 +10,4 @@ in
   imports = [
     ./nix.nix
   ];
-  nixpkgs.overlays = [
-    (self: super: {
-      firefox-bin-unwrapped = super.firefox-bin-unwrapped.override { systemLocale = "en-GB"; };
-      firefox-devedition-bin-unwrapped = super.firefox-devedition-bin-unwrapped.override { systemLocale = "en-GB"; };
-    })
-  ];
 }
diff --git a/user/settings/rofi.nix b/user/settings/rofi.nix
index c0c6990d..35d50a91 100644
--- a/user/settings/rofi.nix
+++ b/user/settings/rofi.nix
@@ -12,15 +12,6 @@
     gui_if_available = false
   '';
 
-  nixpkgs.overlays = [
-    (self: super: {
-      rofi = super.rofi.overrideAttrs (oldAttrs: rec {
-        postInstall = ''
-          ln $out/bin/rofi $out/bin/dmenu
-        '';
-      });
-    })
-  ];
   programs.rofi = {
     enable = true;
     theme = "Arc";
diff --git a/user/settings/shell.nix b/user/settings/shell.nix
index 6542636a..3b4bb1f4 100644
--- a/user/settings/shell.nix
+++ b/user/settings/shell.nix
@@ -118,7 +118,7 @@ in
 
       ho = "home-manager";
       hob = "home-manager build";
-      hos = "home-manager switch";
+      hos = "home-manager switch -b hm_bak_$(date +%Y%m%d%H%M)";
       hon = "home-manager news";
       hoh = "home-manager help";
       hop = "home-manager packages";
@@ -141,9 +141,17 @@ in
       sngc = "sudo nix-collect-garbage --delete-older-than 30d";
     };
   };
+  programs.gh = {
+    enable = true;
+    settings = {
+      git_protocol = "ssh";
+      aliases = {
+        fork = "repo fork --remote --remote-name fork --default-branch-only";
+      };
+    };
+  };
   home.packages = with pkgs; [
     fzf
-    gh
     ghq
     delta
     git
diff --git a/user/settings/tabnine.nix b/user/settings/tabnine.nix
index 4cb1be3b..377b8217 100644
--- a/user/settings/tabnine.nix
+++ b/user/settings/tabnine.nix
@@ -10,10 +10,36 @@
     config = {
       version = pkgs.tabnine.version;
 
-      hide_promotional_message = true;
+      api_base_url = null;
+      api_key = config.programs.tabnine.registrationKey;
       beta_enabled = "No";
-      ignore_all_lsp = false;
+      binary_update_interval_seconds = 365 * 24 * 3600;
+      cloud_whitelist = [ ];
       creation_time = "2020-12-28T21:42:35.732522096Z";
+      deep_completions_work_mode = "LocalOnly";
+      disable_auto_update = true;
+      disable_local_when_using_battery = false;
+      enable_power_saving_mode = false;
+      enable_telemetry = false;
+      force_local_hub = true;
+      generation = 0;
+      hide_deep_information_message = false;
+      hide_promotional_message = true;
+      hosted_deep_completions_enabled = "Disabled";
+      ignore_all_lsp = false;
+      inline_suggestions_mode = true;
+      line_suggestions = true;
+      local_enabled = "Yes";
+      local_indexing = null;
+      local_model_size = null;
+      num_of_suggestions = 5;
+      onboarding = {
+        model_type = null;
+        skipped_login = true;
+        completed = true;
+      };
+      rate_limit_amount = null;
+      rate_limit_interval_seconds = null;
       semantic_status = {
         css = "Enabled";
         dockerfile = "Enabled";
@@ -21,81 +47,63 @@
         haskell = "Enabled";
         html = "Enabled";
         javascript = "Enabled";
-        ruby = "Enabled";
         nix = "Enabled";
+        ruby = "Enabled";
         scss = "Enabled";
         typescript = "Enabled";
         yaml = "Enabled";
       };
-      disable_auto_update = true;
-      binary_update_interval_seconds = 365 * 24 * 3600;
-      deep_completions_work_mode = "LocalOnly";
-      hosted_deep_completions_enabled = "Disabled";
+      snippets_enabled_v2 = true;
       tabnine_cloud_certificate_domain = null;
       tabnine_cloud_host = null;
       tabnine_cloud_port = null;
-      cloud_whitelist = [ ];
-      api_key = null;
-      api_key_service_level = null;
-      api_base_url = null;
-      local_enabled = "Yes";
-      local_indexing = null;
-      local_model_size = null;
-      disable_local_when_using_battery = false;
-      hide_deep_information_message = false;
-      enable_power_saving_mode = false;
-      enable_telemetry = false;
-      generation = "0";
-      rate_limit_interval_seconds = null;
-      rate_limit_amount = null;
+      use_specialized_model_if_available = true;
     };
-    lspConfig = {
-      "language.typescript" = {
+    lspConfig.language = {
+      typescript = {
         command = "typescript-language-server";
         args = [ "--stdio" ];
       };
-      "language.javascript" = {
+      javascript = {
         command = "javascript-typescript-stdio";
         args = [ "--stdio" ];
       };
-      "language.css" = {
+      css = {
         command = "css-languageserver";
         args = [ "--stdio" ];
       };
-      "language.scss" = {
+      scss = {
         command = "css-languageserver";
         args = [ "--stdio" ];
       };
-      "language.html" = {
+      html = {
         command = "html-languageserver";
         args = [ "--stdio" ];
       };
-      "language.nix" = {
+      nix = {
         command = "nil";
         args = [ "--stdio" ];
       };
-      "language.dockerfile" = {
+      dockerfile = {
         command = "docker-langserver";
         args = [ "--stdio" ];
       };
-      "language.ruby" = {
+      ruby = {
         command = "solargraph";
         args = [ "stdio" ];
       };
-      "language.yaml" = {
+      yaml = {
         command = "yaml-language-server";
         args = [ "--stdio" ];
       };
-      "language.haskell" = {
+      haskell = {
         command = "hie";
         args = [ "--stdio" ];
       };
-      "language.go" = {
-        command = "go-langserver";
+      go = {
+        command = "gopls";
         args = [
-          "-mode"
-          "stdio"
-          "-gocodecompletion"
+          "serve"
         ];
       };
     };
diff --git a/user/settings/user-interface.nix b/user/settings/user-interface.nix
index 469bdde4..05b4c90c 100644
--- a/user/settings/user-interface.nix
+++ b/user/settings/user-interface.nix
@@ -49,6 +49,7 @@ in
     ]
     ++ lib.optionals (!stdenv.isDarwin) (with pkgs; [
       logseq
+      (discord.override { withOpenASAR = true; })
 
       falkon
       mu