about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--users/glittershark/system/.gitignore1
-rw-r--r--users/glittershark/system/home/common/legacy-dotfiles.nix8
-rw-r--r--users/glittershark/system/home/common/solarized.nix18
-rw-r--r--users/glittershark/system/home/home.nix20
-rw-r--r--users/glittershark/system/home/machines/chupacabra.nix45
-rw-r--r--users/glittershark/system/home/machines/dobharchu.nix17
-rw-r--r--users/glittershark/system/home/modules/alacritty.nix49
-rw-r--r--users/glittershark/system/home/modules/alsi.nix60
-rw-r--r--users/glittershark/system/home/modules/common.nix49
-rw-r--r--users/glittershark/system/home/modules/development.nix169
-rw-r--r--users/glittershark/system/home/modules/development/agda.nix61
-rw-r--r--users/glittershark/system/home/modules/development/kube.nix37
-rw-r--r--users/glittershark/system/home/modules/development/urbint.nix55
-rw-r--r--users/glittershark/system/home/modules/emacs.nix82
-rw-r--r--users/glittershark/system/home/modules/email.nix54
-rw-r--r--users/glittershark/system/home/modules/firefox.nix22
-rw-r--r--users/glittershark/system/home/modules/games.nix58
-rw-r--r--users/glittershark/system/home/modules/i3.nix324
-rw-r--r--users/glittershark/system/home/modules/lib/cloneRepo.nix67
-rw-r--r--users/glittershark/system/home/modules/lib/zshFunctions.nix21
-rw-r--r--users/glittershark/system/home/modules/nixos-logo.txt26
-rw-r--r--users/glittershark/system/home/modules/obs.nix66
-rwxr-xr-xusers/glittershark/system/home/modules/pure.zsh-theme151
-rw-r--r--users/glittershark/system/home/modules/rtlsdr.nix21
-rw-r--r--users/glittershark/system/home/modules/shell.nix181
-rw-r--r--users/glittershark/system/home/modules/tarsnap.nix64
-rw-r--r--users/glittershark/system/home/modules/twitter.nix23
-rw-r--r--users/glittershark/system/home/modules/vim.nix47
-rw-r--r--users/glittershark/system/home/modules/vimrc1121
-rw-r--r--users/glittershark/system/home/modules/zshrc306
-rw-r--r--users/glittershark/system/home/platforms/darwin.nix24
-rw-r--r--users/glittershark/system/home/platforms/linux.nix89
-rwxr-xr-xusers/glittershark/system/install35
-rw-r--r--users/glittershark/system/pkgs/alsi/default.nix22
-rw-r--r--users/glittershark/system/pkgs/argocd.nix1
-rw-r--r--users/glittershark/system/pkgs/clang-tools.nix15
-rw-r--r--users/glittershark/system/pkgs/clang-tools/default.nix24
-rw-r--r--users/glittershark/system/pkgs/clang-tools/wrapper20
-rw-r--r--users/glittershark/system/system/configuration.nix11
-rw-r--r--users/glittershark/system/system/machines/bumblebee.nix23
-rw-r--r--users/glittershark/system/system/machines/chupacabra.nix50
-rw-r--r--users/glittershark/system/system/modules/common.nix142
-rw-r--r--users/glittershark/system/system/modules/fonts.nix12
-rw-r--r--users/glittershark/system/system/modules/kernel.nix28
-rw-r--r--users/glittershark/system/system/modules/reusable/README.org2
-rw-r--r--users/glittershark/system/system/modules/reusable/battery.nix32
-rw-r--r--users/glittershark/system/system/modules/rtlsdr.nix17
-rw-r--r--users/glittershark/system/system/modules/sound.nix14
-rw-r--r--users/glittershark/system/system/modules/xserver.nix18
49 files changed, 3802 insertions, 0 deletions
diff --git a/users/glittershark/system/.gitignore b/users/glittershark/system/.gitignore
new file mode 100644
index 000000000000..41fbeb02c47d
--- /dev/null
+++ b/users/glittershark/system/.gitignore
@@ -0,0 +1 @@
+**/result
diff --git a/users/glittershark/system/home/common/legacy-dotfiles.nix b/users/glittershark/system/home/common/legacy-dotfiles.nix
new file mode 100644
index 000000000000..33d9581e6a61
--- /dev/null
+++ b/users/glittershark/system/home/common/legacy-dotfiles.nix
@@ -0,0 +1,8 @@
+with import <nixpkgs> {};
+fetchgit {
+  url = "https://github.com/glittershark/dotfiles.git";
+  rev = "e0c7f2592fbc2f9942763d2146d362a1314630e9";
+  # date = "2020-03-25T20:38:51-04:00";
+  sha256 = "126zy4ff6nl2vma2s74waksim7j5h3n6qpaxnnn17vkc1cq0fcd9";
+  fetchSubmodules = false;
+}
diff --git a/users/glittershark/system/home/common/solarized.nix b/users/glittershark/system/home/common/solarized.nix
new file mode 100644
index 000000000000..e94693edc566
--- /dev/null
+++ b/users/glittershark/system/home/common/solarized.nix
@@ -0,0 +1,18 @@
+rec {
+  base03  = "#002B36";
+  base02  = "#073642";
+  base01  = "#586e75";
+  base00  = "#657b83";
+  base0   = "#839496";
+  base1   = "#93a1a1";
+  base2   = "#eee8d5";
+  base3   = "#fdf6e3";
+  yellow  = "#b58900";
+  orange  = "#cb4b16";
+  red     = "#dc322f";
+  magenta = "#d33682";
+  violet  = "#6c71c4";
+  blue    = "#268bd2";
+  cyan    = "#2aa198";
+  green   = "#859900";
+}
diff --git a/users/glittershark/system/home/home.nix b/users/glittershark/system/home/home.nix
new file mode 100644
index 000000000000..39045c147d76
--- /dev/null
+++ b/users/glittershark/system/home/home.nix
@@ -0,0 +1,20 @@
+{ config, pkgs, ... }:
+
+{
+  imports = [
+    (throw "Pick a machine from ./machines")
+  ];
+
+  # Let Home Manager install and manage itself.
+  programs.home-manager.enable = true;
+
+  # This value determines the Home Manager release that your
+  # configuration is compatible with. This helps avoid breakage
+  # when a new Home Manager release introduces backwards
+  # incompatible changes.
+  #
+  # You can update Home Manager without changing this value. See
+  # the Home Manager release notes for a list of state version
+  # changes in each release.
+  home.stateVersion = "19.09";
+}
diff --git a/users/glittershark/system/home/machines/chupacabra.nix b/users/glittershark/system/home/machines/chupacabra.nix
new file mode 100644
index 000000000000..06b0d21567bb
--- /dev/null
+++ b/users/glittershark/system/home/machines/chupacabra.nix
@@ -0,0 +1,45 @@
+{ pkgs, ... }:
+let
+  laptopKeyboardId = "25";
+in {
+  imports = [
+    ../platforms/linux.nix
+    ../modules/common.nix
+    ../modules/games.nix
+    ../modules/rtlsdr.nix
+
+    ~/code/urb/urbos/home
+  ];
+
+  # for when hacking
+  programs.home-manager.path = "/home/grfn/code/home-manager";
+
+  system.machine = {
+    wirelessInterface = "wlp59s0";
+    i3FontSize = 9;
+  };
+
+  systemd.user.services.laptop-keyboard = {
+    Unit = {
+      Description = "Swap caps+escape and alt+super, but only on the built-in laptop keyboard";
+      After = [ "graphical-session-pre.target" ];
+      PartOf = [ "graphical-session.target" ];
+    };
+
+    Install = { WantedBy = [ "graphical-session.target" ]; };
+
+    Service = {
+      Type = "oneshot";
+      RemainAfterExit = true;
+      ExecStart = (
+        "${pkgs.xorg.setxkbmap}/bin/setxkbmap "
+          + "-device ${laptopKeyboardId} "
+          + "-option caps:swapescape "
+          + "-option compose:ralt "
+          + "-option altwin:swap_alt_win"
+      );
+    };
+  };
+
+  urbint.projectPath = "code/urb";
+}
diff --git a/users/glittershark/system/home/machines/dobharchu.nix b/users/glittershark/system/home/machines/dobharchu.nix
new file mode 100644
index 000000000000..0b8503a00e98
--- /dev/null
+++ b/users/glittershark/system/home/machines/dobharchu.nix
@@ -0,0 +1,17 @@
+{ config, lib, pkgs, ... }:
+
+{
+  imports = [
+    ../platforms/darwin.nix
+    ../modules/common.nix
+    ../modules/games.nix
+  ];
+
+  home.packages = with pkgs; [
+    coreutils
+    gnupg
+    nix-prefetch-github
+    pass
+    pinentry_mac
+  ];
+}
diff --git a/users/glittershark/system/home/modules/alacritty.nix b/users/glittershark/system/home/modules/alacritty.nix
new file mode 100644
index 000000000000..34ccf47f18e4
--- /dev/null
+++ b/users/glittershark/system/home/modules/alacritty.nix
@@ -0,0 +1,49 @@
+{ config, lib, pkgs, ... }:
+{
+  home.packages = with pkgs; [
+    alacritty 
+  ];
+
+  programs.alacritty = {
+    enable = true;
+    settings = {
+      font.size = 6;
+      font.normal.family = "Meslo LGSDZ Nerd Font";
+
+      draw_bold_text_with_bright_colors = false;
+
+      colors = with import ../common/solarized.nix; rec {
+        # Default colors
+        primary = {
+          background = base3;
+          foreground = base00;
+        };
+
+        cursor = {
+          text = base3;
+          cursor = base00;
+        };
+
+        # Normal colors
+        normal = {
+          inherit red green yellow blue magenta cyan;
+          black = base02;
+          white = base2;
+        };
+
+        # Bright colors
+        # bright = normal;
+        bright = {
+          black = base03;
+          red = orange;
+          green = base01;
+          yellow = base00;
+          blue = base0;
+          magenta = violet;
+          cyan = base1;
+          white = base3;
+        };
+      };
+    };
+  };
+}
diff --git a/users/glittershark/system/home/modules/alsi.nix b/users/glittershark/system/home/modules/alsi.nix
new file mode 100644
index 000000000000..e42524bb8884
--- /dev/null
+++ b/users/glittershark/system/home/modules/alsi.nix
@@ -0,0 +1,60 @@
+{ config, lib, pkgs, ... }:
+let alsi = pkgs.callPackage ~/code/system/pkgs/alsi {};
+in
+{
+  home.packages = [ alsi ];
+
+  xdg.configFile."alsi/alsi.logo" = {
+    source = ./nixos-logo.txt;
+    force = true;
+  };
+
+  xdg.configFile."alsi/alsi.conf" = {
+    force = true;
+    text = ''
+    #!${pkgs.perl}/bin/perl
+
+    scalar {
+      ALSI_VERSION         => "0.4.8",
+      COLORS_FILE          => "/${config.home.homeDirectory}/.config/alsi/alsi.colors",
+      DE_FILE              => "/${config.home.homeDirectory}/.config/alsi/alsi.de",
+      DEFAULT_COLOR_BOLD   => "blue",
+      DEFAULT_COLOR_NORMAL => "blue",
+      DF_COMMAND           => "df -Th -x sys -x tmpfs -x devtmpfs &>/dev/stdout",
+      GTK2_RC_FILE         => "/${config.home.homeDirectory}/.gtkrc-2.0",
+      GTK3_RC_FILE         => "/${config.home.homeDirectory}/.config/gtk-3.0/settings.ini",
+      LOGO_FILE            => "/${config.home.homeDirectory}/.config/alsi/alsi.logo",
+      OUTPUT_FILE          => "/${config.home.homeDirectory}/.config/alsi/alsi.output",
+      # PACKAGES_PATH        => "/var/lib/pacman/local/",
+      PS_COMMAND           => "ps -A",
+      USAGE_COLORS         => 0,
+      USAGE_COLORS_BOLD    => 0,
+      USAGE_PRECENT_GREEN  => 50,
+      USAGE_PRECENT_RED    => 100,
+      USAGE_PRECENT_YELLOW => 85,
+      USE_LOGO_FROM_FILE   => 1,
+      USE_VALUES_COLOR     => 0,
+      WM_FILE              => "/${config.home.homeDirectory}/.config/alsi/alsi.wm",
+    }
+    '';
+  };
+
+  xdg.configFile."alsi/alsi.colors".text = ''
+    #!${pkgs.perl}/bin/perl
+
+    # Colors for alsi
+
+    scalar {
+       black   => {normal => "\e[0;30m", bold => "\e[1;30m"},
+       red     => {normal => "\e[0;31m", bold => "\e[1;31m"},
+       green   => {normal => "\e[0;32m", bold => "\e[1;32m"},
+       yellow  => {normal => "\e[0;33m", bold => "\e[1;33m"},
+       default => {normal => "\e[0;34m", bold => "\e[1;34m"},
+       blue    => {normal => "\e[0;34m", bold => "\e[1;34m"},
+       purple  => {normal => "\e[0;35m", bold => "\e[1;35m"},
+       cyan    => {normal => "\e[0;36m", bold => "\e[1;36m"},
+       white   => {normal => "\e[0;37m", bold => "\e[1;37m"},
+       reset   => "\e[0m",
+    }
+  '';
+}
diff --git a/users/glittershark/system/home/modules/common.nix b/users/glittershark/system/home/modules/common.nix
new file mode 100644
index 000000000000..ed7a729a7975
--- /dev/null
+++ b/users/glittershark/system/home/modules/common.nix
@@ -0,0 +1,49 @@
+{ config, lib, pkgs, ... }:
+
+# Everything in here needs to work on linux or darwin
+
+{
+  imports = [
+    ../modules/shell.nix
+    ../modules/development.nix
+    ../modules/emacs.nix
+    ../modules/vim.nix
+    ../modules/tarsnap.nix
+    ../modules/twitter.nix
+    ../modules/lib/cloneRepo.nix
+  ];
+
+  nixpkgs.config.allowUnfree = true;
+
+  programs.password-store.enable = true;
+
+  grfn.impure.clonedRepos.passwordStore = {
+    github = "glittershark/pass";
+    path = ".local/share/password-store";
+  };
+
+  urbint.projectPath = "code/urb";
+
+  home.packages = with pkgs; [
+    # System utilities
+    bat
+    htop
+    killall
+    bind
+    zip unzip
+    tree
+    ncat
+    bc
+
+    # Security
+    gnupg
+    keybase
+    openssl
+
+    # Nix things
+    nixfmt
+    nix-prefetch-github
+    nix-review
+    cachix
+  ];
+}
diff --git a/users/glittershark/system/home/modules/development.nix b/users/glittershark/system/home/modules/development.nix
new file mode 100644
index 000000000000..39e964d1da3e
--- /dev/null
+++ b/users/glittershark/system/home/modules/development.nix
@@ -0,0 +1,169 @@
+{ config, lib, pkgs, ... }:
+
+let
+
+  clj2nix = pkgs.callPackage (pkgs.fetchFromGitHub {
+    owner = "hlolli";
+    repo = "clj2nix";
+    rev = "3ab3480a25e850b35d1f532a5e4e7b3202232383";
+    sha256 = "1lry026mlpxp1j563qs13nhxf37i2zpl7lh0lgfdwc44afybqka6";
+  }) {};
+
+  pg-dump-upsert = pkgs.buildGoModule rec {
+    pname = "pg-dump-upsert";
+    version = "165258deaebded5e9b88f7a0acf3a4b7350e7bf4";
+
+    src = pkgs.fetchFromGitHub {
+      owner = "tomyl";
+      repo = "pg-dump-upsert";
+      rev = version;
+      sha256 = "1an4h8jjbj3r618ykjwk9brii4h9cxjqy47c4c8rivnvhimgf4wm";
+    };
+
+    modSha256 = "07ci2726nrn8qjvwcypk6nf8zqmfnmvch8l28bmgj7hpfrbyb424";
+  };
+
+in
+
+with lib;
+
+{
+  imports = [
+    ./lib/zshFunctions.nix
+    ./development/kube.nix
+    ./development/urbint.nix
+    ./development/agda.nix
+  ];
+
+  home.packages = with pkgs; [
+    jq
+    yq
+    gitAndTools.hub
+    gitAndTools.tig
+    shellcheck
+    httpie
+    entr
+    gnumake
+    inetutils
+    loc
+
+    clj2nix
+
+    pg-dump-upsert
+
+    (import ../pkgs/clang-tools { inherit pkgs; })
+  ] ++ optional (stdenv.isLinux) julia;
+
+  programs.git = {
+    enable = true;
+    package = pkgs.gitFull;
+    userEmail = "root@gws.fyi";
+    userName  = "Griffin Smith";
+    ignores = [
+      "*.sw*"
+      ".classpath"
+      ".project"
+      ".settings/"
+      ".dir-locals.el"
+      ".stack-work-profiling"
+      ".projectile"
+    ];
+    extraConfig = {
+      github.user = "glittershark";
+      merge.conflictstyle = "diff3";
+    };
+
+    delta = {
+      enable = true;
+      options = [
+        "--theme 'Solarized (light)'"
+        "--hunk-style" "plain"
+        "--commit-style" "box"
+      ];
+    };
+  };
+
+  home.file.".psqlrc".text = ''
+    \set QUIET 1
+    \timing
+    \set ON_ERROR_ROLLBACK interactive
+    \set VERBOSITY verbose
+    \x auto
+    \set PROMPT1 '%[%033[1m%]%M/%/%R%[%033[0m%]%# '
+    \set PROMPT2 '...%# '
+    \set HISTFILE ~/.psql_history- :DBNAME
+    \set HISTCONTROL ignoredups
+    \pset null [null]
+    \unset QUIET
+  '';
+
+  programs.readline = {
+    enable = true;
+    extraConfig = ''
+      set editing-mode vi
+    '';
+  };
+
+  programs.zsh = {
+    shellAliases = {
+      # Git
+      "gwip" = "git add . && git commit -am wip";
+      "gpr" = "g pull-request";
+      "gcl" = "git clone";
+      "grs" = "gr --soft";
+      "grhh" = "grh HEAD";
+      "grh" = "gr --hard";
+      "gr" = "git reset";
+      "gcb" = "gc -b";
+      "gco" = "gc";
+      "gcd" = "gc development";
+      "gcm" = "gc master";
+      "gc" = "git checkout";
+      "gbg" = "git branch | grep";
+      "gba" = "git branch -a";
+      "gb" = "git branch";
+      "gcv" = "git commit --verbose";
+      "gci" = "git commit";
+      "gm" = "git merge";
+      "gdc" = "gd --cached";
+      "gd" = "git diff";
+      "gsl" = "git stash list";
+      "gss" = "git show stash";
+      "gsad" = "git stash drop";
+      "gsa" = "git stash";
+      "gst" = "gs";
+      "gs" = "git status";
+      "gg" = "gl --decorate --oneline --graph --date-order --all";
+      "gl" = "git log";
+      "gf" = "git fetch";
+      "gur" = "gu --rebase";
+      "gu" = "git pull";
+      "gpf" = "gp -f";
+      "gpa" = "gp --all";
+      "gpu" = "git push -u origin \"$(git symbolic-ref --short HEAD)\"";
+      "gp" = "git push";
+      "ganw" = "git diff -w --no-color | git apply --cached --ignore-whitespace";
+      "ga" = "git add";
+      "gnp" = "git --no-pager";
+      "g" = "git";
+      "git" = "hub";
+      "grim" = "git fetch && git rebase -i origin/master";
+      "grc" = "git rebase --continue";
+      "gcan" = "git commit --amend --no-edit";
+      "grl" = "git reflog";
+
+      # Haskell
+      "cnb" = "cabal new-build";
+      "cob" = "cabal old-build";
+      "cnr" = "cabal new-run";
+      "cor" = "cabal old-run";
+      "ho" = "hoogle";
+    };
+
+    functions = {
+      gdelmerged = ''
+      git branch --merged | egrep -v 'master' | tr -d '+ ' | xargs git branch -d
+      '';
+    };
+  };
+}
diff --git a/users/glittershark/system/home/modules/development/agda.nix b/users/glittershark/system/home/modules/development/agda.nix
new file mode 100644
index 000000000000..7a197e907f3c
--- /dev/null
+++ b/users/glittershark/system/home/modules/development/agda.nix
@@ -0,0 +1,61 @@
+{ config, lib, pkgs, ... }:
+
+let
+
+  nixpkgs-unstable = import <nixpkgs-unstable> {};
+
+  agda-categories = with nixpkgs-unstable.agdaPackages; mkDerivation rec {
+    pname = "agda-categories";
+    version = "2128fab";
+    src = pkgs.fetchFromGitHub {
+      owner = "agda";
+      repo = "agda-categories";
+      rev = version;
+      sha256 = "08mc20qaz9vp5rhi60rh8wvjkg5aby3bgwwdhfnxha1663qf1q24";
+    };
+
+    buildInputs = [ standard-library ];
+  };
+
+in
+
+{
+  imports = [
+    ../lib/cloneRepo.nix
+  ];
+
+  home.packages = with pkgs; [
+    (nixpkgs-unstable.agda.withPackages
+      (p: with p; [
+        p.standard-library
+
+      ]))
+  ];
+
+  grfn.impure.clonedRepos = {
+    agda-stdlib = {
+      github = "agda/agda-stdlib";
+      path = "code/agda-stdlib";
+    };
+
+    agda-categories = {
+      github = "agda/agda-categories";
+      path = "code/agda-categories";
+    };
+
+    categories-examples = {
+      github = "agda/categories-examples";
+      path = "code/categories-examples";
+    };
+  };
+
+  home.file.".agda/defaults".text = ''
+    standard-library
+  '';
+
+  home.file.".agda/libraries".text = ''
+    ${config.home.homeDirectory}/code/agda-stdlib/standard-library.agda-lib
+    ${config.home.homeDirectory}/code/agda-categories/agda-categories.agda-lib
+  '';
+
+}
diff --git a/users/glittershark/system/home/modules/development/kube.nix b/users/glittershark/system/home/modules/development/kube.nix
new file mode 100644
index 000000000000..346dd57dee7e
--- /dev/null
+++ b/users/glittershark/system/home/modules/development/kube.nix
@@ -0,0 +1,37 @@
+{ config, lib, pkgs, ... }:
+let
+  pkgs-unstable = import <nixpkgs-unstable> {};
+in
+{
+  home.packages = with pkgs; [
+    kubectl
+    kubetail
+    sops
+    pkgs-unstable.kubie
+    # pkgs-unstable.argocd # provided by urbos
+  ];
+
+  programs.zsh.shellAliases = {
+    "kc" = "kubectl";
+    "kg" = "kc get";
+    "kga" = "kc get --all-namespaces";
+    "kpd" = "kubectl get pods";
+    "kpa" = "kubectl get pods --all-namespaces";
+    "klf" = "kubectl logs -f";
+    "kdep" = "kubectl get deployments";
+    "ked" =  "kubectl edit deployment";
+    "kpw" = "kubectl get pods -w";
+    "kew" = "kubectl get events -w";
+    "kdel" = "kubectl delete";
+    "knw" = "kubectl get nodes -w";
+    "kev" = "kubectl get events --sort-by='.metadata.creationTimestamp'";
+
+    "arsy" = "argocd app sync --prune";
+  };
+
+  home.file.".kube/kubie.yaml".text = ''
+    shell: zsh
+    prompt:
+      zsh_use_rps1: true
+  '';
+}
diff --git a/users/glittershark/system/home/modules/development/urbint.nix b/users/glittershark/system/home/modules/development/urbint.nix
new file mode 100644
index 000000000000..63f92bf50d4e
--- /dev/null
+++ b/users/glittershark/system/home/modules/development/urbint.nix
@@ -0,0 +1,55 @@
+# urbint-only dev stuff
+{ config, lib, pkgs, ... }:
+
+let
+
+  yarn2nix = (import (pkgs.fetchFromGitHub {
+    owner = "moretea";
+    repo = "yarn2nix";
+    rev = "9e7279edde2a4e0f5ec04c53f5cd64440a27a1ae";
+    sha256 = "0zz2lrwn3y3rb8gzaiwxgz02dvy3s552zc70zvfqc0zh5dhydgn7";
+  }) { inherit pkgs; }).yarn2nix;
+
+in
+
+{
+  home.packages = with pkgs; [
+    yarn2nix
+    python36
+    python36Packages.ipython
+  ];
+
+  programs.zsh = {
+    shellAliases = {
+      ipy = "ipython";
+      amerge = "alembic merge heads";
+    };
+
+    functions = {
+      aup = "alembic upgrade \${1:-head}";
+      adown = "alembic downgrade \${1:--1}";
+    };
+  };
+
+  programs.git = {
+    extraConfig.filter.black100to80 =
+      let inherit (pkgs.python36Packages) black; in {
+        clean = "${black}/bin/black --target-version py36 -l 100 -";
+        smudge = "${black}/bin/black --target-version py36 -l 80 -";
+      };
+
+
+    includes = [{
+      condition = "gitdir:~/code/urb/";
+      contents = {
+        user.email = "grfn@urbint.com";
+      };
+    }];
+  };
+
+  home.file.".ipython/profile_default/ipython_config.py".text = ''
+    c.InteractiveShellApp.exec_lines = ['%autoreload 2']
+    c.InteractiveShellApp.extensions = ['autoreload']
+    c.TerminalInteractiveShell.editing_mode = 'vi'
+  '';
+}
diff --git a/users/glittershark/system/home/modules/emacs.nix b/users/glittershark/system/home/modules/emacs.nix
new file mode 100644
index 000000000000..3f82880d2bd6
--- /dev/null
+++ b/users/glittershark/system/home/modules/emacs.nix
@@ -0,0 +1,82 @@
+{ pkgs, lib, ... }:
+
+with lib;
+
+let
+ # doom-emacs = pkgs.callPackage (builtins.fetchTarball {
+ #   url = https://github.com/vlaci/nix-doom-emacs/archive/master.tar.gz;
+ # }) {
+ #   doomPrivateDir = ./doom.d;  # Directory containing your config.el init.el
+ #                               # and packages.el files
+ # };
+in {
+  imports = [ ./lib/cloneRepo.nix ];
+
+  # home.packages = [ doom-emacs ];
+  # home.file.".emacs.d/init.el".text = ''
+  #     (load "default.el")
+  # '';
+  #
+
+  config = mkMerge [
+    {
+      home.packages = with pkgs; [
+        # LaTeX (for org export)
+        (pkgs.texlive.combine {
+          inherit (pkgs.texlive)
+          scheme-basic collection-fontsrecommended ulem
+          fncychap titlesec tabulary varwidth framed fancyvrb float parskip
+          wrapfig upquote capt-of needspace;
+        })
+
+        ispell
+
+        ripgrep
+        coreutils
+        fd
+        clang
+        gnutls
+      ];
+
+      nixpkgs.overlays = [
+        (import (builtins.fetchTarball {
+          url = "https://github.com/nix-community/emacs-overlay/archive/54afb061bdd12c61bbfcc13bad98b7a3aab7d8d3.tar.gz";
+          sha256 = "0hrbg65d5h0cb0nky7a46md7vlvhajq1hf0328l2f7ln9hznqz6j";
+        }))
+      ];
+
+      programs.emacs = {
+        enable = true;
+        package = pkgs.emacsUnstable;
+      };
+
+      grfn.impure.clonedRepos = {
+        orgClubhouse = {
+          github = "glittershark/org-clubhouse";
+          path = "code/org-clubhouse";
+        };
+
+        doomEmacs = {
+          github = "hlissner/doom-emacs";
+          path = ".emacs.d";
+          after = ["emacs.d"];
+          onClone = "bin/doom install";
+        };
+
+        "emacs.d" = {
+          github = "glittershark/emacs.d";
+          path = ".doom.d";
+          after = ["orgClubhouse"];
+        };
+      };
+
+    }
+    (mkIf pkgs.stdenv.isLinux {
+      # Notes
+      services.syncthing = {
+        enable = true;
+        tray = true;
+      };
+    })
+  ];
+}
diff --git a/users/glittershark/system/home/modules/email.nix b/users/glittershark/system/home/modules/email.nix
new file mode 100644
index 000000000000..80c5385e69ae
--- /dev/null
+++ b/users/glittershark/system/home/modules/email.nix
@@ -0,0 +1,54 @@
+{ pkgs, ... }:
+{
+  # programs.mbsync.enable = true;
+  programs.lieer.enable = true;
+  programs.notmuch.enable = true;
+  services.lieer.enable = true;
+  programs.msmtp.enable = true;
+
+  home.packages = with pkgs; [
+    mu
+    msmtp
+  ];
+
+  accounts.email.maildirBasePath = "mail";
+  accounts.email.accounts =
+    let
+      mkAccount = params@{ passEntry, ... }: {
+        realName = "Griffin Smith";
+        passwordCommand = "pass ${passEntry}";
+
+        flavor = "gmail.com";
+
+        imapnotify = {
+          enable = true;
+          boxes = [ "Inbox" ];
+        };
+
+        gpg = {
+          key = "0F11A989879E8BBBFDC1E23644EF5B5E861C09A7";
+          signByDefault = true;
+        };
+
+        # mbsync.enable = true;
+        notmuch.enable = true;
+        lieer = {
+          enable = true;
+          sync.enable = true;
+        };
+        msmtp.enable = true;
+      } // builtins.removeAttrs params ["passEntry"];
+    in {
+      work = mkAccount {
+        primary = true;
+        address = "griffin@urbint.com";
+        aliases = [ "grfn@urbint.com" ];
+        passEntry = "urbint/msmtp-app-password";
+      };
+
+      personal = mkAccount {
+        address = "root@gws.fyi";
+        passEntry = "root-gws-msmtp";
+      };
+    };
+}
diff --git a/users/glittershark/system/home/modules/firefox.nix b/users/glittershark/system/home/modules/firefox.nix
new file mode 100644
index 000000000000..c7e78685a5a3
--- /dev/null
+++ b/users/glittershark/system/home/modules/firefox.nix
@@ -0,0 +1,22 @@
+{ config, lib, pkgs, ... }:
+
+{
+
+  xdg.mimeApps = rec {
+    enable = true;
+    defaultApplications = {
+      "text/html" = [ "firefox.desktop" ];
+      "x-scheme-handler/http" = [ "firefox.desktop" ];
+      "x-scheme-handler/https" = [ "firefox.desktop" ];
+      "x-scheme-handler/ftp" = [ "firefox.desktop" ];
+      "x-scheme-handler/chrome" = [ "firefox.desktop" ];
+      "application/x-extension-htm" = [ "firefox.desktop" ];
+      "application/x-extension-html" = [ "firefox.desktop" ];
+      "application/x-extension-shtml" = [ "firefox.desktop" ];
+      "application/xhtml+xml" = [ "firefox.desktop" ];
+      "application/x-extension-xhtml" = [ "firefox.desktop" ];
+      "application/x-extension-xht" = [ "firefox.desktop" ];
+    };
+    associations.added = defaultApplications;
+  };
+}
diff --git a/users/glittershark/system/home/modules/games.nix b/users/glittershark/system/home/modules/games.nix
new file mode 100644
index 000000000000..a9adf9c91036
--- /dev/null
+++ b/users/glittershark/system/home/modules/games.nix
@@ -0,0 +1,58 @@
+{ config, lib, pkgs, ... }:
+
+with pkgs;
+with lib;
+
+let
+
+  df-orig = dwarf-fortress-packages.dwarf-fortress-original;
+
+  df-full = (dwarf-fortress-packages.dwarf-fortress-full.override {
+    theme = null;
+    enableIntro = false;
+    enableFPS = true;
+  });
+
+  init = runCommand "init.txt" {} ''
+    substitute "${df-orig}/data/init/init.txt" $out \
+      --replace "[INTRO:YES]" "[INTRO:NO]" \
+      --replace "[VOLUME:255]" "[VOLUME:0]" \
+      --replace "[FPS:NO]" "[FPS:YES]"
+  '';
+
+  d_init = runCommand "d_init.txt" {} ''
+    substitute "${df-orig}/data/init/d_init.txt" $out \
+      --replace "[AUTOSAVE:NONE]" "[AUTOSAVE:SEASONAL]" \
+      --replace "[AUTOSAVE_PAUSE:NO]" "[AUTOSAVE_PAUSE:YES]" \
+      --replace "[INITIAL_SAVE:NO]" "[INITIAL_SAVE:YES]" \
+      --replace "[EMBARK_WARNING_ALWAYS:NO]" "[EMBARK_WARNING_ALWAYS:YES]" \
+      --replace "[VARIED_GROUND_TILES:YES]" "[VARIED_GROUND_TILES:NO]" \
+      --replace "[SHOW_FLOW_AMOUNTS:NO]" "[SHOW_FLOW_AMOUNTS:YES]"
+  '';
+
+  df = runCommand "dwarf-fortress" {} ''
+    mkdir -p $out/bin
+    sed \
+      -e '4icp -f ${init} "$DF_DIR/data/init/init.txt"' \
+      -e '4icp -f ${d_init} "$DF_DIR/data/init/d_init.txt"' \
+      < "${df-full}/bin/dwarf-fortress" >"$out/bin/dwarf-fortress"
+
+    shopt -s extglob
+    ln -s ${df-full}/bin/!(dwarf-fortress) $out/bin
+
+    chmod +x $out/bin/dwarf-fortress
+  '';
+
+in mkMerge [
+  {
+    home.packages = [
+      crawl
+    ];
+  }
+  (mkIf stdenv.isLinux {
+    home.packages = [
+      df
+    ];
+  })
+]
+
diff --git a/users/glittershark/system/home/modules/i3.nix b/users/glittershark/system/home/modules/i3.nix
new file mode 100644
index 000000000000..36f2d450edd5
--- /dev/null
+++ b/users/glittershark/system/home/modules/i3.nix
@@ -0,0 +1,324 @@
+{ config, lib, pkgs, ... }:
+let
+  mod = "Mod4";
+  solarized = import ../common/solarized.nix;
+  # TODO pull this out into lib
+  emacsclient = eval: pkgs.writeShellScript "emacsclient-eval" ''
+    msg=$(emacsclient --eval '${eval}' 2>&1)
+    echo "''${msg:1:-1}"
+  '';
+  screenlayout = {
+    home = pkgs.writeShellScript "screenlayout_home.sh" ''
+      xrandr \
+        --output eDP1 --mode 3840x2160 --pos 0x0 --rotate normal \
+        --output DP1 --primary --mode 3840x2160 --pos 0x2160 --rotate normal \
+        --output DP2 --off --output DP3 --off --output VIRTUAL1 --off
+    '';
+  };
+in {
+  options = with lib; {
+    system.machine.wirelessInterface = mkOption {
+      description = ''
+        Name of the primary wireless interface. Used by i3status, etc.
+      '';
+      default = "wlp3s0";
+      type = types.str;
+    };
+
+    system.machine.i3FontSize = mkOption {
+      description = "Font size to use in i3 window decorations etc.";
+      default = 6;
+      type = types.int;
+    };
+  };
+
+  config =
+    let decorationFont = "MesloLGSDZ ${toString config.system.machine.i3FontSize}"; in
+    {
+      home.packages = with pkgs; [
+        rofi
+        rofi-pass
+        python38Packages.py3status
+        i3lock
+        dconf # for gtk
+
+        # Screenshots
+        maim
+
+        # GIFs
+        picom
+        peek
+      ];
+
+      xsession.scriptPath = ".hm-xsession";
+      xsession.windowManager.i3 = {
+        enable = true;
+        config = {
+          modifier = mod;
+          keybindings = lib.mkOptionDefault rec {
+            "${mod}+h" = "focus left";
+            "${mod}+j" = "focus down";
+            "${mod}+k" = "focus up";
+            "${mod}+l" = "focus right";
+            "${mod}+semicolon" = "focus parent";
+
+            "${mod}+Shift+h" = "move left";
+            "${mod}+Shift+j" = "move down";
+            "${mod}+Shift+k" = "move up";
+            "${mod}+Shift+l" = "move right";
+
+            "${mod}+Shift+x" = "kill";
+
+            "${mod}+Return" = "exec alacritty";
+
+            "${mod}+Shift+s" = "split h";
+            "${mod}+Shift+v" = "split v";
+
+            "${mod}+f" = "fullscreen";
+
+            "${mod}+Shift+r" = "restart";
+
+            "${mod}+r" = "mode resize";
+
+            # Marks
+            "${mod}+Shift+m" = ''exec i3-input -F "mark %s" -l 1 -P 'Mark: ' '';
+            "${mod}+m" = ''exec i3-input -F '[con_mark="%s"] focus' -l 1 -P 'Go to: ' '';
+
+            # Screenshots
+            "${mod}+q" = "exec \"maim | xclip -selection clipboard -t image/png\"";
+            "${mod}+Shift+q" = "exec \"maim -s | xclip -selection clipboard -t image/png\"";
+            "${mod}+Ctrl+q" = "exec ${pkgs.writeShellScript "peek.sh" ''
+            picom &
+            picom_pid=$!
+            peek || true
+            kill -SIGINT $picom_pid
+            ''}";
+
+            # Launching applications
+            "${mod}+u" = "exec ${pkgs.writeShellScript "rofi" ''
+              rofi \
+                -modi 'combi' \
+                -combi-modi "window,drun,ssh,run" \
+                -font '${decorationFont}' \
+                -show combi
+            ''}";
+
+            # Passwords
+            "${mod}+p" = "exec rofi-pass -font '${decorationFont}'";
+
+            # Media
+            "XF86AudioPlay" = "exec playerctl play-pause";
+            "XF86AudioNext" = "exec playerctl next";
+            "XF86AudioPrev" = "exec playerctl previous";
+            "XF86AudioRaiseVolume" = "exec pulseaudio-ctl up";
+            "XF86AudioLowerVolume" = "exec pulseaudio-ctl down";
+            "XF86AudioMute" = "exec pulseaudio-ctl mute";
+
+            # Lock
+            Pause = "exec \"sh -c 'playerctl pause; ${pkgs.i3lock}/bin/i3lock -c 222222'\"";
+            F7 = Pause;
+
+            # Screen Layout
+            "${mod}+Shift+t" = "exec xrandr --auto";
+            "${mod}+t" = "exec ${screenlayout.home}";
+            "${mod}+Ctrl+t" = "exec ${pkgs.writeShellScript "fix_term.sh" ''
+              xrandr --output eDP-1 --off && ${screenlayout.home}
+            ''}";
+
+            # Notifications
+            "${mod}+Shift+n" = "exec killall -SIGUSR1 .dunst-wrapped";
+            "${mod}+n" = "exec killall -SIGUSR2 .dunst-wrapped";
+          };
+
+          fonts = [ decorationFont ];
+
+          colors = with solarized; rec {
+            focused = {
+              border = base01;
+              background = base01;
+              text = base3;
+              indicator = red;
+              childBorder = base02;
+            };
+            focusedInactive = focused // {
+              border = base03;
+              background = base03;
+              # text = base1;
+            };
+            unfocused = focusedInactive;
+            background = base03;
+          };
+
+          modes.resize = {
+            l = "resize shrink width 5 px or 5 ppt";
+            k = "resize grow height 5 px or 5 ppt";
+            j = "resize shrink height 5 px or 5 ppt";
+            h = "resize grow width 5 px or 5 ppt";
+
+            Return = "mode \"default\"";
+          };
+
+          bars = [{
+            statusCommand =
+              let i3status-conf = pkgs.writeText "i3status.conf" ''
+              general {
+                  output_format = i3bar
+                  colors = true
+                  color_good = "#859900"
+
+                  interval = 1
+              }
+
+              order += "external_script current_task"
+              order += "external_script inbox"
+              order += "spotify"
+              order += "wireless ${config.system.machine.wirelessInterface}"
+              # order += "ethernet enp3s0f0"
+              order += "cpu_usage"
+              order += "battery 0"
+              # order += "volume master"
+              order += "time"
+
+              mpd {
+                  format = "%artist - %album - %title"
+              }
+
+              wireless ${config.system.machine.wirelessInterface} {
+                  format_up = "W: (%quality - %essid - %bitrate) %ip"
+                  format_down = "W: -"
+              }
+
+              ethernet enp3s0f0 {
+                  format_up = "E: %ip"
+                  format_down = "E: -"
+              }
+
+              battery 0 {
+                  format = "%status %percentage"
+                  path = "/sys/class/power_supply/BAT%d/uevent"
+                  low_threshold = 10
+              }
+
+              cpu_usage {
+                  format = "CPU: %usage"
+              }
+
+              load {
+                  format = "%5min"
+              }
+
+              time {
+                  format = "    %a %h %d ⌚   %I:%M     "
+              }
+
+              spotify {
+                  color_playing = "#fdf6e3"
+                  color_paused = "#93a1a1"
+                  format_stopped = ""
+                  format_down = ""
+                  format = "{title} - {artist} ({album})"
+              }
+
+              external_script inbox {
+                  script_path = '${emacsclient "(grfn/num-inbox-items-message)"}'
+                  format = 'Inbox: {output}'
+                  cache_timeout = 120
+                  color = "#93a1a1"
+              }
+
+              external_script current_task {
+                  script_path = '${emacsclient "(grfn/org-current-clocked-in-task-message)"}'
+                  # format = '{output}'
+                  cache_timeout = 60
+                  color = "#93a1a1"
+              }
+
+
+              # volume master {
+              #     format = "☊ %volume"
+              #     format_muted = "☊ X"
+              #     device = "default"
+              #     mixer_idx = 0
+              # }
+            '';
+              in "py3status -c ${i3status-conf}";
+            fonts = [ decorationFont ];
+            position = "top";
+            colors = with solarized; rec {
+              background = base03;
+              statusline = base3;
+              separator = base1;
+              activeWorkspace = {
+                border = base03;
+                background = base1;
+                text = base3;
+              };
+              focusedWorkspace = activeWorkspace;
+              inactiveWorkspace = activeWorkspace // {
+                background = base01;
+              };
+              urgentWorkspace = activeWorkspace // {
+                background = red;
+              };
+            };
+          }];
+        };
+      };
+
+      services.dunst = {
+        enable = true;
+        settings = with solarized; {
+          global = {
+            font = "MesloLGSDZ ${toString (config.system.machine.i3FontSize * 1.5)}";
+            allow_markup = true;
+            format = "<b>%s</b>\n%b";
+            sort = true;
+            alignment = "left";
+            geometry = "600x15-40+40";
+            idle_threshold = 120;
+            separator_color = "frame";
+            separator_height = 1;
+            word_wrap = true;
+            padding = 8;
+            horizontal_padding = 8;
+          };
+
+          frame = {
+            width = 0;
+            color = "#aaaaaa";
+          };
+
+          shortcuts = {
+            close = "ctrl+space";
+            close_all = "ctrl+shift+space";
+            history = "ctrl+grave";
+            context = "ctrl+shift+period";
+          };
+
+          urgency_low = {
+            background = base03;
+            foreground = base3;
+            timeout = 5;
+          };
+
+          urgency_normal = {
+            background = base02;
+            foreground = base3;
+            timeout = 7;
+          };
+
+          urgency_critical = {
+            background = red;
+            foreground = base3;
+            timeout = 0;
+          };
+        };
+      };
+
+      gtk = {
+        enable = true;
+        iconTheme.name = "Adwaita";
+        theme.name = "Adwaita";
+      };
+  };
+}
diff --git a/users/glittershark/system/home/modules/lib/cloneRepo.nix b/users/glittershark/system/home/modules/lib/cloneRepo.nix
new file mode 100644
index 000000000000..dc487dc6bd05
--- /dev/null
+++ b/users/glittershark/system/home/modules/lib/cloneRepo.nix
@@ -0,0 +1,67 @@
+{ lib, config, ... }:
+with lib;
+{
+  options = {
+    grfn.impure.clonedRepos = mkOption {
+      description = "Repositories to clone";
+      default = {};
+      type = with types; loaOf (
+        let sm = submodule {
+          options = {
+            url = mkOption {
+              type = nullOr str;
+              description = "URL of repository to clone";
+              default = null;
+            };
+
+            github = mkOption {
+              type = nullOr str;
+              description = "Github owner/repo of repository to clone";
+              default = null;
+            };
+
+            path = mkOption {
+              type = str;
+              description = "Path to clone to";
+            };
+
+            onClone = mkOption {
+              type = str;
+              description = ''
+                Shell command to run after cloning the repo for the first time.
+                Runs inside the repo itself.
+              '';
+              default = "";
+            };
+
+            after = mkOption {
+              type = listOf str;
+              description = "Activation hooks that this repository must be cloned after";
+              default = [];
+            };
+          };
+        };
+        in addCheck sm (cr: (! isNull cr.url || ! isNull cr.github))
+      );
+    };
+  };
+
+  config = {
+    home.activation =
+      mapAttrs
+      (_: {
+        url, path, github, onClone, after, ...
+      }:
+        let repoURL = if isNull url then "git@github.com:${github}" else url;
+        in hm.dag.entryAfter (["writeBoundary"] ++ after) ''
+          $DRY_RUN_CMD mkdir -p $(dirname "${path}")
+          if [[ ! -d ${path} ]]; then
+            $DRY_RUN_CMD git clone "${repoURL}" "${path}"
+            pushd ${path}
+            $DRY_RUN_CMD ${onClone}
+            popd
+          fi
+        '')
+      config.grfn.impure.clonedRepos;
+  };
+}
diff --git a/users/glittershark/system/home/modules/lib/zshFunctions.nix b/users/glittershark/system/home/modules/lib/zshFunctions.nix
new file mode 100644
index 000000000000..7c39b3478cfd
--- /dev/null
+++ b/users/glittershark/system/home/modules/lib/zshFunctions.nix
@@ -0,0 +1,21 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  options = {
+    programs.zsh.functions = mkOption {
+      description = "An attribute set that maps function names to their source";
+      default = {};
+      type = with types; attrsOf (either str path);
+    };
+  };
+
+  config.programs.zsh.initExtra = concatStringsSep "\n" (
+    mapAttrsToList (name: funSrc: ''
+      function ${name}() {
+        ${funSrc}
+      }
+    '') config.programs.zsh.functions
+  );
+}
diff --git a/users/glittershark/system/home/modules/nixos-logo.txt b/users/glittershark/system/home/modules/nixos-logo.txt
new file mode 100644
index 000000000000..d4b16b44f0bf
--- /dev/null
+++ b/users/glittershark/system/home/modules/nixos-logo.txt
@@ -0,0 +1,26 @@
+                 ((((((          ###%######       ##%###/
+               ,(((((((/(          #%#%#%#%#    .#%#%#%#%#
+                 ((((((///          %#######%. #####%###/
+                  (((((/(//,         /##%###%###%######
+                    (((//////          #####%########(
+         .(((((((((((((((///////////////#%%%########          ((
+        (((((((((((((((///////////////////#########         .((((
+       ((((((((((((((((/(//////////////////##########      ((((((((
+                   (#########                #########    (((((((((
+                  #########                   #########/((((((((((
+                *#########                     .#######(((((((((
+ ###%###################                         ####(//((((((((((((((((
+####%##################                           .#////////((((((((((((((
+%%%%%%%%%%%%%%#######((                           ////////////((((((((((((
+ ###%#######%#######////.                        ///////////////////((((
+         ###%###%#///////(                      /////////
+       .####%#### /////////                   /////////,
+      %#%#%#%#%*   /////////(                /////////
+      .#####%#       ////////(######################%#######%#####,
+        %####         (////////#####################%###%###%###%
+         .#          (//////(//((###################%#######%##%
+                    (//(((((((((((          #####%%%%(
+                  //(/((((((((((((((          ######%##
+                 (((((((((  (((((((((          #####%###/
+                (((((((((    /(((((((((         .###%####%
+                 ((((((        (((((((((          %#%#%#/
diff --git a/users/glittershark/system/home/modules/obs.nix b/users/glittershark/system/home/modules/obs.nix
new file mode 100644
index 000000000000..d1dade477ccc
--- /dev/null
+++ b/users/glittershark/system/home/modules/obs.nix
@@ -0,0 +1,66 @@
+{ config, lib, pkgs, ... }:
+
+with pkgs;
+
+let
+  libuiohook = stdenv.mkDerivation rec {
+    pname = "libuiohook";
+    version = "1.1";
+    src = fetchFromGitHub {
+      owner = "kwhat";
+      repo = "libuiohook";
+      rev = version;
+      sha256 = "1isfxn3cfrdqq22d3mlz2lzm4asf9gprs7ww2xy9c3j3srk9kd7r";
+    };
+
+    preConfigure = ''
+      ./bootstrap.sh
+    '';
+
+    nativeBuildInputs = [ pkg-config ];
+    buildInputs = [
+      libtool autoconf automake
+      x11
+      xorg.libXtst
+      xorg.libXinerama
+      xorg.libxkbfile
+      libxkbcommon
+    ];
+  };
+
+  obs-input-overlay = stdenv.mkDerivation rec {
+    pname = "obs-input-overlay";
+    version = "4.8";
+    src = fetchFromGitHub {
+      owner = "univrsal";
+      repo = "input-overlay";
+      rev = "v${version}";
+      sha256 = "1dklg0dx9ijwyhgwcaqz859rbpaivmqxqvh9w3h4byrh5pnkz8bf";
+      fetchSubmodules = true;
+    };
+
+    nativeBuildInputs = [ cmake ];
+    buildInputs = [ obs-studio libuiohook ];
+
+    postPatch = ''
+      sed -i CMakeLists.txt \
+        -e '2iinclude(${obs-studio.src}/cmake/Modules/ObsHelpers.cmake)' \
+        -e '2ifind_package(LibObs REQUIRED)'
+    '';
+
+    cmakeFlags = [
+      "-Wno-dev"
+    ];
+  };
+in
+{
+  home.packages = [
+    obs-studio
+    obs-input-overlay
+  ];
+
+  xdg.configFile."obs-studio/plugins/input-overlay/bin/64bit/input-overlay.so".source =
+    "${obs-input-overlay}/lib/obs-plugins/input-overlay.so";
+  xdg.configFile."obs-studio/plugins/input-overlay/data".source =
+    "${obs-input-overlay}/share/obs/obs-plugins/input-overlay";
+}
diff --git a/users/glittershark/system/home/modules/pure.zsh-theme b/users/glittershark/system/home/modules/pure.zsh-theme
new file mode 100755
index 000000000000..b4776e81596d
--- /dev/null
+++ b/users/glittershark/system/home/modules/pure.zsh-theme
@@ -0,0 +1,151 @@
+#!/bin/zsh -f
+# vim: ft=zsh:
+# MIT License
+# For my own and others sanity
+# git:
+# %b => current branch
+# %a => current action (rebase/merge)
+# prompt:
+# %F => color dict
+# %f => reset color
+# %~ => current path
+# %* => time
+# %n => username
+# %m => shortname host
+# %(?..) => prompt conditional - %(condition.true.false)
+
+# turns seconds into human readable time
+# 165392 => 1d 21h 56m 32s
+prompt_pure_human_time() {
+	local tmp=$1
+	local days=$(( tmp / 60 / 60 / 24 ))
+	local hours=$(( tmp / 60 / 60 % 24 ))
+	local minutes=$(( tmp / 60 % 60 ))
+	local seconds=$(( tmp % 60 ))
+	(( $days > 0 )) && echo -n "${days}d "
+	(( $hours > 0 )) && echo -n "${hours}h "
+	(( $minutes > 0 )) && echo -n "${minutes}m "
+	echo "${seconds}s"
+}
+
+is_git_repo() {
+	command git rev-parse --is-inside-work-tree &>/dev/null
+	return $?
+}
+
+# fastest possible way to check if repo is dirty
+prompt_pure_git_dirty() {
+	# check if we're in a git repo
+	is_git_repo || return
+	# check if it's dirty
+	[[ "$PURE_GIT_UNTRACKED_DIRTY" == 0 ]] && local umode="-uno" || local umode="-unormal"
+	command test -n "$(git status --porcelain --ignore-submodules ${umode})"
+
+	(($? == 0)) && echo '*'
+}
+
+prompt_pure_git_wip() {
+	is_git_repo || return
+	local subject="$(command git show --pretty=%s --quiet HEAD 2>/dev/null)"
+	[ "$subject" == 'wip' ] && echo '[WIP]'
+}
+
+# displays the exec time of the last command if set threshold was exceeded
+prompt_pure_cmd_exec_time() {
+	local stop=$EPOCHSECONDS
+	local start=${cmd_timestamp:-$stop}
+	integer elapsed=$stop-$start
+	(($elapsed > ${PURE_CMD_MAX_EXEC_TIME:=5})) && prompt_pure_human_time $elapsed
+}
+
+prompt_pure_preexec() {
+	cmd_timestamp=$EPOCHSECONDS
+
+	# shows the current dir and executed command in the title when a process is active
+	print -Pn "\e]0;"
+	echo -nE "$PWD:t: $2"
+	print -Pn "\a"
+}
+
+# string length ignoring ansi escapes
+prompt_pure_string_length() {
+	echo ${#${(S%%)1//(\%([KF1]|)\{*\}|\%[Bbkf])}}
+}
+
+prompt_pure_nix_info() {
+	local packages_info=''
+	if [[ -z $NIX_SHELL_PACKAGES ]]; then
+		packages_info='[nix-shell]'
+	else
+		packages_info="{ $NIX_SHELL_PACKAGES }"
+	fi
+
+	case $IN_NIX_SHELL in
+		'pure')
+			echo "$fg_bold[green][nix-shell] "
+			;;
+		'impure')
+			echo "$fg_bold[magenta][nix-shell] "
+			;;
+		*) ;;
+	esac
+}
+
+prompt_pure_precmd() {
+	# shows the full path in the title
+	print -Pn '\e]0;%~\a'
+
+	# git info
+	vcs_info
+
+	local prompt_pure_preprompt="\n$(prompt_pure_nix_info)$fg_bold[green]$prompt_pure_username%F{blue}%~%F{yellow}$vcs_info_msg_0_`prompt_pure_git_dirty` $fg_no_bold[red]`prompt_pure_git_wip`%f %F{yellow}`prompt_pure_cmd_exec_time`%f "
+	print -P $prompt_pure_preprompt
+
+	# check async if there is anything to pull
+	# (( ${PURE_GIT_PULL:-1} )) && {
+	# 	# check if we're in a git repo
+	# 	command git rev-parse --is-inside-work-tree &>/dev/null &&
+	# 	# make sure working tree is not $HOME
+	# 	[[ "$(command git rev-parse --show-toplevel)" != "$HOME" ]] &&
+	# 	# check check if there is anything to pull
+	# 	command git fetch &>/dev/null &&
+	# 	# check if there is an upstream configured for this branch
+	# 	command git rev-parse --abbrev-ref @'{u}' &>/dev/null && {
+	# 		local arrows=''
+	# 		(( $(command git rev-list --right-only --count HEAD...@'{u}' 2>/dev/null) > 0 )) && arrows='⇣'
+	# 		(( $(command git rev-list --left-only --count HEAD...@'{u}' 2>/dev/null) > 0 )) && arrows+='⇡'
+	# 		print -Pn "\e7\e[A\e[1G\e[`prompt_pure_string_length $prompt_pure_preprompt`C%F{cyan}${arrows}%f\e8"
+	# 	}
+	# } &!
+
+	# reset value since `preexec` isn't always triggered
+	unset cmd_timestamp
+}
+
+
+prompt_pure_setup() {
+	# prevent percentage showing up
+	# if output doesn't end with a newline
+	export PROMPT_EOL_MARK=''
+
+	prompt_opts=(cr subst percent)
+
+	zmodload zsh/datetime
+	autoload -Uz add-zsh-hook
+	autoload -Uz vcs_info
+
+	add-zsh-hook precmd prompt_pure_precmd
+	add-zsh-hook preexec prompt_pure_preexec
+
+	zstyle ':vcs_info:*' enable git
+	zstyle ':vcs_info:git*' formats ' %b'
+	zstyle ':vcs_info:git*' actionformats ' %b|%a'
+
+	# show username@host if logged in through SSH
+	[[ "$SSH_CONNECTION" != '' ]] && prompt_pure_username='%n@%m '
+
+	# prompt turns red if the previous command didn't exit with 0
+	PROMPT='%(?.%F{green}.%F{red})❯%f '
+}
+
+prompt_pure_setup "$@"
diff --git a/users/glittershark/system/home/modules/rtlsdr.nix b/users/glittershark/system/home/modules/rtlsdr.nix
new file mode 100644
index 000000000000..a1c717617a62
--- /dev/null
+++ b/users/glittershark/system/home/modules/rtlsdr.nix
@@ -0,0 +1,21 @@
+{ config, lib, pkgs, ... }:
+
+let
+
+  nixpkgs-gnuradio = import (pkgs.fetchFromGitHub {
+    owner = "doronbehar";
+    repo = "nixpkgs";
+    rev = "712561aa5f10bfe6112a1726a912585612a70d1f";
+    sha256 = "04yqflbwjcfl9vlplphpj82csqqz9k6m3nj1ybhwgmsc4by7vivl";
+  }) {};
+
+in
+
+{
+  home.packages = with pkgs; [
+    rtl-sdr
+    nixpkgs-gnuradio.gnuradio
+    nixpkgs-gnuradio.gnuradio.plugins.osmosdr
+    nixpkgs-gnuradio.gqrx
+  ];
+}
diff --git a/users/glittershark/system/home/modules/shell.nix b/users/glittershark/system/home/modules/shell.nix
new file mode 100644
index 000000000000..71e607063fe2
--- /dev/null
+++ b/users/glittershark/system/home/modules/shell.nix
@@ -0,0 +1,181 @@
+{ config, lib, pkgs, ... }:
+let
+  shellAliases = rec {
+    # NixOS stuff
+    hms = "home-manager switch";
+    nor = "sudo nixos-rebuild switch";
+    nrs = nor;
+    nrb = "sudo nixos-rebuild boot";
+    ncg = "nix-collect-garbage";
+    vihome = "vim ~/.config/nixpkgs/home.nix && home-manager switch";
+    virc = "vim ~/code/system/home/modules/shell.nix && home-manager switch && source ~/.zshrc";
+    visystem = "sudo vim /etc/nixos/configuration.nix && sudo nixos-rebuild switch";
+
+    # Nix
+    ns = "nix-shell";
+    nb = "nix build -f .";
+    nc = "nix copy --to https://nix.urbinternal.com";
+    "nc." = "nix copy -f . --to https://nix.urbinternal.com";
+
+    # Docker and friends
+    "dcu" = "docker-compose up";
+    "dcud" = "docker-compose up -d";
+    "dc" = "docker-compose";
+    "dcr" = "docker-compose restart";
+    "dclf" = "docker-compose logs -f";
+    "dck" = "docker";
+    "dockerclean" = "dockercleancontainers && dockercleanimages";
+    "dockercleanimages" = "docker images -a --no-trunc | grep none | awk '{print \$$3}' | xargs -L 1 -r docker rmi";
+    "dockercleancontainers" = "docker ps -a --no-trunc| grep 'Exit' | awk '{print \$$1}' | xargs -L 1 -r docker rm";
+
+    # Directories
+    stck = "dirs -v";
+    b= "cd ~1";
+    ".." = "cd ..";
+    "..." = "cd ../..";
+    "...." = "cd ../../..";
+    "....." = "cd ../../../..";
+
+    # Aliases from old config
+    "http" = "http --style solarized";
+    "grep" = "grep $GREP_OPTIONS";
+    "bak" = "~/bin/backup.sh";
+    "xmm" = "xmodmap ~/.Xmodmap";
+    "asdflkj" = "asdf";
+    "asdf" = "asdfghjkl";
+    "asdfghjkl" = "echo \"Having some trouble?\"";
+    "ift" = "sudo iftop -i wlp3s0";
+    "first" = "awk '{print \$$1}'";
+    "cmt" = "git log --oneline | fzf-tmux | awk '{print \$$1}'";
+    "workmon" = "xrandr --output DP-2 --pos 1440x900 --primary";
+    "vi" = "vim";
+    "adbdev" = "adb devices";
+    "adbcon" = "adb connect $GNEX_IP";
+    "mpalb" = "mpc search album";
+    "mpart" = "mpc search artist";
+    "mps" = "mpc search";
+    "mpa" = "mpc add";
+    "mpt" = "mpc toggle";
+    "mpl" = "mpc playlist";
+    "dsstore" = "find . -name '*.DS_Store' -type f -ls -delete";
+    "df" = "df -h";
+    "fs" = "stat -f '%z bytes'";
+    "ll" = "ls -al";
+    "la" = "ls -a";
+  };
+in {
+  home.packages = with pkgs; [
+    zsh
+    autojump
+  ];
+
+  home.sessionVariables = {
+    EDITOR = "vim";
+    LS_COLORS = "no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.ogg=01;35:*.mp3=01;35:*.wav=01;35:";
+    BROWSER = "firefox";
+    BAT_THEME = "ansi-light";
+  };
+
+  programs.bash = {
+    enable = true;
+    inherit shellAliases;
+  };
+
+  programs.zsh = {
+    enable = true;
+    enableAutosuggestions = true;
+    autocd = true;
+
+    inherit shellAliases;
+
+    history = rec {
+      save = 100000;
+      size = save;
+    };
+
+    oh-my-zsh = {
+      enable = true;
+
+      plugins = [
+        "battery"
+        "colorize"
+        "command-not-found"
+        "github"
+        "gitignore"
+        "postgres"
+        "systemd"
+        "themes"
+        "vi-mode"
+      ];
+
+      custom = "${pkgs.stdenv.mkDerivation {
+        name = "oh-my-zsh-custom";
+        unpackPhase = ":";
+        installPhase = ''
+          mkdir -p $out/themes
+          mkdir -p $out/custom/plugins
+          ln -s ${./pure.zsh-theme} $out/themes/pure.zsh-theme
+        '';
+      }}";
+
+      theme = "pure";
+    };
+
+    plugins = [{
+      name = "pure-theme";
+      src = pkgs.fetchFromGitHub {
+        owner = "sindresorhus";
+        repo = "pure";
+        rev = "0a92b02dd4172f6c64fdc9b81fe6cd4bddb0a23b";
+        sha256 = "0l8jqhmmjn7p32hdjnv121xsjnqd2c0plhzgydv2yzrmqgyvx7cc";
+      };
+    }];
+
+    initExtraBeforeCompInit = ''
+      zstyle ':completion:*' completer _complete _ignored _correct _approximate
+      zstyle ':completion:*' matcher-list \'\' 'm:{[:lower:]}={[:upper:]} m:{[:lower:][:upper:]}={[:upper:][:lower:]} r:|[._- :]=** r:|=**' 'l:|=* r:|=*'
+      zstyle ':completion:*' max-errors 5
+      zstyle ':completion:*' use-cache yes
+      zstyle ':completion::complete:grunt::options:' expire 1
+      zstyle ':completion:*' prompt '%e errors'
+      # zstyle :compinstall filename '~/.zshrc'
+      autoload -Uz compinit
+    '';
+
+    initExtra = ''
+      source ${./zshrc}
+      source ${pkgs.fetchFromGitHub {
+        owner = "zsh-users";
+        repo = "zsh-syntax-highlighting";
+        rev = "7678a8a22780141617f809002eeccf054bf8f448";
+        sha256 = "0xh4fbd54kvwwpqvabk8lpw7m80phxdzrd75q3y874jw0xx1a9q6";
+      }}/zsh-syntax-highlighting.zsh
+      source ${pkgs.autojump}/share/autojump/autojump.zsh
+      source ${pkgs.fetchFromGitHub {
+        owner = "chisui";
+        repo = "zsh-nix-shell";
+        rev = "a65382a353eaee5a98f068c330947c032a1263bb";
+        sha256 = "0l41ac5b7p8yyjvpfp438kw7zl9dblrpd7icjg1v3ig3xy87zv0n";
+      }}/nix-shell.plugin.zsh
+
+      export RPS1=""
+      autoload -U promptinit; promptinit
+      prompt pure
+
+      if [[ "$TERM" == "dumb" ]]; then
+        unsetopt zle
+        unsetopt prompt_cr
+        unsetopt prompt_subst
+        unfunction precmd
+        unfunction preexec
+        export PS1='$ '
+      fi
+    '';
+  };
+
+  programs.fzf = {
+    enable = true;
+    enableBashIntegration = true;
+    enableZshIntegration = true;
+  };
+}
diff --git a/users/glittershark/system/home/modules/tarsnap.nix b/users/glittershark/system/home/modules/tarsnap.nix
new file mode 100644
index 000000000000..4bff19910f05
--- /dev/null
+++ b/users/glittershark/system/home/modules/tarsnap.nix
@@ -0,0 +1,64 @@
+{ config, lib, pkgs, ... }:
+
+{
+  home.packages = with pkgs; [
+    tarsnap
+  ];
+
+  home.file.".tarsnaprc".text = ''
+  ### Recommended options
+
+  # Tarsnap cache directory
+  cachedir /home/grfn/.cache/tarsnap
+
+  # Tarsnap key file
+  keyfile /home/grfn/.private/tarsnap.key
+
+  # Don't archive files which have the nodump flag set.
+  nodump
+
+  # Print statistics when creating or deleting archives.
+  print-stats
+
+  # Create a checkpoint once per GB of uploaded data.
+  checkpoint-bytes 1G
+
+  ### Commonly useful options
+
+  # Use SI prefixes to make numbers printed by --print-stats more readable.
+  humanize-numbers
+
+  ### Other options, not applicable to most systems
+
+  # Aggressive network behaviour: Use multiple TCP connections when
+  # writing archives.  Use of this option is recommended only in
+  # cases where TCP congestion control is known to be the limiting
+  # factor in upload performance.
+  #aggressive-networking
+
+  # Exclude files and directories matching specified patterns.
+  # Only one file or directory per command; multiple "exclude"
+  # commands may be given.
+  #exclude
+
+  # Include only files and directories matching specified patterns.
+  # Only one file or directory per command; multiple "include"
+  # commands may be given.
+  #include
+
+  # Attempt to reduce tarsnap memory consumption.  This option
+  # will slow down the process of creating archives, but may help
+  # on systems where the average size of files being backed up is
+  # less than 1 MB.
+  #lowmem
+
+  # Try even harder to reduce tarsnap memory consumption.  This can
+  # significantly slow down tarsnap, but reduces its memory usage
+  # by an additional factor of 2 beyond what the lowmem option does.
+  #verylowmem
+
+  # Snapshot time.  Use this option if you are backing up files
+  # from a filesystem snapshot rather than from a "live" filesystem.
+  #snaptime <file>
+  '';
+}
diff --git a/users/glittershark/system/home/modules/twitter.nix b/users/glittershark/system/home/modules/twitter.nix
new file mode 100644
index 000000000000..3cb2e90adc34
--- /dev/null
+++ b/users/glittershark/system/home/modules/twitter.nix
@@ -0,0 +1,23 @@
+{ pkgs, lib, ... }:
+
+{
+  home.packages = with pkgs; [
+    t
+  ];
+
+  home.sessionVariables = {
+    TWITTER_WHOAMI = "glittershark1";
+  };
+
+  programs.zsh = {
+    shellAliases = {
+      "mytl" = "t tl $TWITTER_WHOAMI";
+    };
+
+    functions = {
+      favelast = "t fave $(t tl -l $1 | head -n1 | cut -d' ' -f1)";
+      rtlast = "t rt $(t tl -l $1 | head -n1 | cut -d' ' -f1)";
+      tthread = "t reply $(t tl -l $TWITTER_WHOAMI | head -n1 | cut -d' ' -f1) $@";
+    };
+  };
+}
diff --git a/users/glittershark/system/home/modules/vim.nix b/users/glittershark/system/home/modules/vim.nix
new file mode 100644
index 000000000000..87d4309333dd
--- /dev/null
+++ b/users/glittershark/system/home/modules/vim.nix
@@ -0,0 +1,47 @@
+{ config, pkgs, ... }:
+{
+  programs.neovim = {
+    enable = true;
+    viAlias = true;
+    vimAlias = true;
+    plugins = with pkgs.vimPlugins; [
+      ctrlp
+      deoplete-nvim
+      syntastic
+      vim-abolish
+      vim-airline
+      vim-airline-themes
+      vim-bufferline
+      vim-closetag
+      # vim-colors-solarized
+      # solarized
+      (pkgs.vimUtils.buildVimPlugin {
+        name = "vim-colors-solarized";
+        src = pkgs.fetchFromGitHub {
+          owner = "glittershark";
+          repo = "vim-colors-solarized";
+          rev = "4857c3221ec3f2693a45855154cb61a2cefb514d";
+          sha256 = "0kqp5w14g7adaiinmixm7z3x4w74lv1lcgbqjbirx760f0wivf9y";
+        };
+      })
+      vim-commentary
+      vim-dispatch
+      vim-endwise
+      vim-repeat
+      vim-fugitive
+      vim-markdown
+      vim-nix
+      vim-rhubarb
+      vim-sexp
+      vim-sexp-mappings-for-regular-people
+      vim-sleuth
+      vim-startify
+      vim-surround
+      vim-unimpaired
+      vinegar
+    ];
+    extraConfig = ''
+      source ${./vimrc}
+    '';
+  };
+}
diff --git a/users/glittershark/system/home/modules/vimrc b/users/glittershark/system/home/modules/vimrc
new file mode 100644
index 000000000000..3e33b5e2bee7
--- /dev/null
+++ b/users/glittershark/system/home/modules/vimrc
@@ -0,0 +1,1121 @@
+" vim:set fdm=marker fmr={{{,}}} ts=2 sts=2 sw=2 expandtab:
+
+
+" Basic Options {{{
+set nocompatible
+set modeline
+set modelines=10
+syntax enable
+filetype plugin indent on
+set ruler
+set showcmd
+set number
+set incsearch
+set smartcase
+set ignorecase
+set scrolloff=10
+set tabstop=4
+set shiftwidth=4
+set softtabstop=4
+set nosmartindent
+set expandtab
+set noerrorbells visualbell t_vb=
+set laststatus=2
+set hidden
+let mapleader = ','
+let maplocalleader = '\'
+set undofile
+" set undodir=~/.vim/undo
+set wildignore=*.pyc,*.o,.git
+set clipboard=unnamedplus
+" set backupdir=$HOME/.vim/backup
+" set directory=$HOME/.vim/tmp
+set foldmarker={{{,}}}
+set colorcolumn=+1
+set concealcursor=
+set formatoptions+=j
+set wildmenu
+set wildmode=longest,list:full
+set noincsearch
+" }}}
+
+" GUI options {{{
+set go-=m
+set go-=T
+set go-=r
+set go-=L
+set go-=e
+set guifont=Meslo\ LG\ S\ DZ\ 9
+" }}}
+
+" Colors {{{
+" set t_Co=256
+
+fu! ReverseBackground()
+  if &bg=="light"
+    se bg=dark
+  else
+    se bg=light
+  endif
+endf
+com! BgToggle call ReverseBackground()
+nm <F12> :BgToggle<CR>
+
+set background=light
+colorscheme solarized
+" }}}
+
+" ---------------------------------------------------------------------------
+
+" CtrlP {{{
+let g:ctrlp_custom_ignore = {
+      \ 'dir': '(node_modules|target)'
+      \ }
+let g:ctrlp_max_files = 0
+let g:ctrlp_max_depth = 100
+" }}}
+
+" YouCompleteMe {{{
+let g:ycm_semantic_triggers =  {
+      \   'c' : ['->', '.'],
+      \   'objc' : ['->', '.'],
+      \   'ocaml' : ['.', '#'],
+      \   'cpp,objcpp' : ['->', '.', '::'],
+      \   'perl' : ['->'],
+      \   'php' : ['->', '::'],
+      \   'cs,java,javascript,d,python,perl6,scala,vb,elixir,go' : ['.'],
+      \   'vim' : ['re![_a-zA-Z]+[_\w]*\.'],
+      \   'lua' : ['.', ':'],
+      \   'erlang' : [':'],
+      \   'clojure' : [],
+      \   'haskell' : ['re!.*', '.', ' ', '(']
+      \ }
+      " \   'haskell' : ['.', '(', ' ']
+      " \   'ruby' : ['.', '::'],
+      " \   'clojure' : ['(', '.', '/', '[']
+" }}}
+
+" Neocomplete {{{
+if !has('nvim')
+  " Use neocomplete.
+  let g:neocomplete#enable_at_startup = 1
+  " Use smartcase.
+  let g:neocomplete#enable_smart_case = 1
+  " Set minimum syntax keyword length.
+  let g:neocomplete#sources#syntax#min_keyword_length = 3
+  let g:neocomplete#lock_buffer_name_pattern = '\*ku\*'
+
+  " Define dictionary.
+  " let g:neocomplete#sources#dictionary#dictionaries = {
+  "     \ 'default' : '',
+  "     \ 'vimshell' : $HOME.'/.vimshell_hist',
+  "     \ 'scheme' : $HOME.'/.gosh_completions'
+  "     \ }
+
+  " Define keyword.
+  if !exists('g:neocomplete#keyword_patterns')
+      let g:neocomplete#keyword_patterns = {}
+  endif
+  let g:neocomplete#keyword_patterns['default'] = '\h\w*'
+
+  " Plugin key-mappings.
+  inoremap <expr><C-g>     neocomplete#undo_completion()
+  inoremap <expr><C-l>     neocomplete#complete_common_string()
+
+  " Recommended key-mappings.
+  " <CR>: close popup and save indent.
+  inoremap <silent> <CR> <C-r>=<SID>my_cr_function()<CR>
+  function! s:my_cr_function()
+    return (pumvisible() ? "\<C-y>" : "" ) . "\<CR>"
+    " For no inserting <CR> key.
+    "return pumvisible() ? "\<C-y>" : "\<CR>"
+  endfunction
+  " <TAB>: completion.
+  inoremap <expr><TAB>  pumvisible() ? "\<C-n>" : "\<TAB>"
+  " <C-h>, <BS>: close popup and delete backword char.
+  inoremap <expr><C-h> neocomplete#smart_close_popup()."\<C-h>"
+  inoremap <expr><BS> neocomplete#smart_close_popup()."\<C-h>"
+  " Close popup by <Space>.
+  "inoremap <expr><Space> pumvisible() ? "\<C-y>" : "\<Space>"
+
+  " AutoComplPop like behavior.
+  "let g:neocomplete#enable_auto_select = 1
+
+  " Shell like behavior(not recommended).
+  "set completeopt+=longest
+  "let g:neocomplete#enable_auto_select = 1
+  "let g:neocomplete#disable_auto_complete = 1
+  "inoremap <expr><TAB>  pumvisible() ? "\<Down>" : "\<C-x>\<C-u>"
+
+  " Enable omni completion.
+  " autocmd FileType css setlocal omnifunc=csscomplete#CompleteCSS
+  " autocmd FileType html,markdown setlocal omnifunc=htmlcomplete#CompleteTags
+  " autocmd FileType javascript setlocal omnifunc=javascriptcomplete#CompleteJS
+  " autocmd FileType python setlocal omnifunc=pythoncomplete#Complete
+  " autocmd FileType xml setlocal omnifunc=xmlcomplete#CompleteTags
+
+  " Enable heavy omni completion.
+  if !exists('g:neocomplete#sources#omni#input_patterns')
+    let g:neocomplete#sources#omni#input_patterns = {}
+  endif
+endif
+" }}}
+
+" Deoplete {{{
+if has('nvim')
+  let g:deoplete#enable_at_startup = 1
+
+  inoremap <silent> <CR> <C-r>=<SID>my_cr_function()<CR>
+  function! s:my_cr_function()
+    return (pumvisible() ? "\<C-y>" : "" ) . "\<CR>"
+    " For no inserting <CR> key.
+    "return pumvisible() ? "\<C-y>" : "\<CR>"
+  endfunction
+  " <TAB>: completion.
+  inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"
+  inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<TAB>"
+endif
+" }}}
+
+" Neovim Terminal mode {{{
+if has('nvim')
+  tnoremap <Esc> <C-\><C-n>
+  nnoremap \\ :tabedit term://zsh<CR>
+  nnoremap q\ :call <SID>OpenRepl()<CR>
+
+  if !exists('g:repl_size')
+    let g:repl_size=9
+  endif
+
+  function! s:OpenRepl() " {{{
+    " Check if buffer exists and is open
+    if exists('s:repl_bufname') && bufexists(s:repl_bufname) && bufwinnr(s:repl_bufname) >=? 0
+      " If so, just switch to it
+      execute bufwinnr(s:repl_bufname) . 'wincmd' 'w'
+      norm i
+      return
+    endif
+
+    if !exists('b:console')
+      let b:console=$SHELL
+    endif
+
+    let l:console_cmd = b:console
+
+    execute 'bot' g:repl_size . 'new'
+    set winfixheight nobuflisted
+    call termopen(l:console_cmd)
+    let s:repl_bufname = bufname('%')
+    norm i
+  endfunction " }}}
+endif
+" }}}
+
+" Tagbar options {{{
+let g:tagbar_autoclose = 1
+let g:tagbar_autofocus = 1
+let g:tagbar_compact = 1
+" }}}
+
+" delimitMate options {{{
+let g:delimitMate_expand_cr = 1
+" }}}
+
+" UltiSnips options {{{
+let g:UltiSnipsExpandTrigger = '<c-j>'
+   "g:UltiSnipsJumpForwardTrigger          <c-j>
+   "g:UltiSnipsJumpBackwardTrigger         <c-k>
+" }}}
+
+" VDebug Options {{{
+let g:vdebug_options = {'server': '192.168.56.1'}
+" }}}
+
+" Statusline {{{
+let g:airline_powerline_fonts=1
+
+if !exists('g:airline_symbols')
+  let g:airline_symbols = {}
+endif
+let g:airline_symbols.space = "\ua0"
+
+let g:airline#extensions#tagbar#flags = 'f'
+let g:airline#extensions#tabline#enabled = 1
+let g:airline#extensions#tabline#show_buffers = 0
+let g:airline#extensions#tabline#show_tabs = 1
+let g:airline#extensions#tabline#tab_min_count = 2
+let g:airline#extensions#tmuxline#enabled = 0
+
+let g:tmuxline_theme = 'airline'
+let g:tmuxline_preset = 'full'
+
+"set statusline=
+"set statusline+=%2*[%n%H%M%R%W]%*\              " flags and buf no
+"set statusline+=%-40f%<\                        " path
+"set statusline+=%=%40{fugitive#statusline()}\   " Vim status
+"set statusline+=%1*%y%*%*\                      " file type
+"set statusline+=%10((%l,%c)%)\                  " line and column
+"set statusline+=%P                              " percentage of file
+" }}}
+
+" Code review mode {{{
+fun! GetFontName()
+  return substitute(&guifont, '^\(.\{-}\)[0-9]*$', '\1', '')
+endfun
+
+fun! <SID>CodeReviewMode()
+  let &guifont = GetFontName() . ' 15'
+endfun
+com! CodeReviewMode call <SID>CodeReviewMode()
+" }}}
+
+" Syntastic {{{
+let g:syntastic_enable_signs = 0
+
+" Python {{{
+let g:syntastic_python_checkers = ['flake8']
+let g:syntastic_python_flake8_post_args = "--ignore=E101,E223,E224,E301,E302,E303,E501,E701,W,F401,E111,E261"
+
+" }}}
+" Javascript {{{
+let g:syntastic_javascript_checkers = ['eslint']
+let g:flow#autoclose = 1
+let g:flow#enable = 1
+
+" augroup syntastic_javascript_jsx
+"   autocmd!
+"   autocmd BufReadPre,BufNewFile *.js
+"   autocmd BufReadPre,BufNewFile *.jsx
+"         \ let g:syntastic_javascript_checkers = ['jsxhint']
+" augroup END
+
+" }}}
+" Haml {{{
+let g:syntastic_haml_checkers = ['haml_lint']
+
+" }}}
+" Html {{{
+let g:syntastic_html_checkers = []
+
+" }}}
+" Ruby {{{
+let g:syntastic_ruby_checkers = ['rubocop']
+" }}}
+" SASS/SCSS {{{
+let g:syntastic_scss_checkers = ['scss_lint']
+" }}}
+" Haskell {{{
+" let g:syntastic_haskell_checkers = ['ghc-mod']
+" }}}
+" Elixir {{{
+let g:syntastic_elixir_checkers = ['elixir']
+let g:syntastic_enable_elixir_checker = 1
+" }}}
+" }}}
+
+" Bufferline {{{
+let g:bufferline_echo=0
+" }}}
+
+" Eclim {{{
+let g:EclimCompletionMethod = 'omnifunc'
+augroup eclim
+  au!
+  au FileType java call <SID>JavaSetup()
+  au FileType java set textwidth=120
+augroup END
+
+function! s:JavaSetup() abort
+  noremap <C-I> :JavaImport<CR>
+  nnoremap K :JavaDocPreview<CR>
+  nnoremap ]d :JavaSearchContext<CR>
+  nnoremap [d :JavaSearchContext<CR>
+  nnoremap g<CR> :JUnit<CR>
+  nnoremap g\ :Mvn test<CR>
+endfunction
+" }}}
+
+" Signify options {{{
+let g:signify_mapping_next_hunk = ']h'
+let g:signify_mapping_prev_hunk = '[h'
+let g:signify_vcs_list          = ['git']
+let g:signify_sign_change       = '~'
+let g:signify_sign_delete       = '-'
+" }}}
+
+" Simplenote {{{
+let g:SimplenoteFiletype = 'markdown'
+let g:SimplenoteSortOrder = 'pinned,modifydate,tagged,createdate'
+let g:SimplenoteVertical = 1
+
+nnoremap <Leader>nn :Simplenote -n<CR>
+nnoremap <Leader>nl :Simplenote -l<CR>
+nnoremap <Leader>nw :Simplenote -l work<CR>
+nnoremap <Leader>nt :Simplenote -t<CR>
+" }}}
+
+" Emmet {{{
+" Expand abbreviation
+let g:user_emmet_leader_key = '<C-y>'
+" }}}
+
+" Startify {{{
+let g:startify_bookmarks=[ '~/.vimrc',  '~/.zshrc' ]
+" }}}
+
+" Abolish {{{
+let g:abolish_save_file = expand('~/.vim/after/plugin/abolish.vim')
+" }}}
+
+" Rails projections {{{
+
+if !exists('g:rails_projections')
+  let g:rails_projections = {}
+endif
+
+call extend(g:rails_projections, {
+      \ "config/routes.rb": { "command": "routes" },
+      \ "config/structure.sql": { "command": "structure" }
+      \ }, 'keep')
+
+if !exists('g:rails_gem_projections')
+  let g:rails_gem_projections = {}
+endif
+
+call extend(g:rails_gem_projections, {
+      \ "active_model_serializers": {
+      \   "app/serializers/*_serializer.rb": {
+      \     "command": "serializer",
+      \     "template": "class %SSerializer < ActiveModel::Serializer\nend",
+      \     "affinity": "model"}},
+      \ "react-rails": {
+      \   "app/assets/javascripts/components/*.jsx": {
+      \     "command": "component",
+      \     "template": "var %S = window.%S = React.createClass({\n  render: function() {\n  }\n});",
+      \     "alternate": "spec/javascripts/components/%s_spec.jsx" },
+      \   "spec/javascripts/components/*_spec.jsx": {
+      \     "alternate": "app/assets/javascripts/components/{}.jsx" }},
+      \ "rspec": {
+      \    "spec/**/support/*.rb": {
+      \      "command": "support"}},
+      \ "cucumber": {
+      \   "features/*.feature": {
+      \     "command": "feature",
+      \     "template": "Feature: %h"},
+      \   "features/support/*.rb": {
+      \     "command": "support"},
+      \   "features/support/env.rb": {
+      \     "command": "support"},
+      \   "features/step_definitions/*_steps.rb": {
+      \     "command": "steps"}},
+      \ "carrierwave": {
+      \   "app/uploaders/*_uploader.rb": {
+      \     "command": "uploader",
+      \     "template": "class %SUploader < CarrierWave::Uploader::Base\nend"}},
+      \ "draper": {
+      \   "app/decorators/*_decorator.rb": {
+      \     "command": "decorator",
+      \     "affinity": "model",
+      \     "template": "class %SDecorator < Draper::Decorator\nend"}},
+      \ "fabrication": {
+      \   "spec/fabricators/*_fabricator.rb": {
+      \     "command": ["fabricator", "factory"],
+      \     "alternate": "app/models/%s.rb",
+      \     "related": "db/schema.rb#%p",
+      \     "test": "spec/models/%s_spec.rb",
+      \     "template": "Fabricator :%s do\nend",
+      \     "affinity": "model"}},
+      \ "factory_girl": {
+      \   "spec/factories/*.rb": {
+      \     "command": "factory",
+      \     "alternate": "app/models/%i.rb",
+      \     "related": "db/structure.sql#%s",
+      \     "test": "spec/models/%s_spec.rb",
+      \     "template": "FactoryGirl.define do\n  factory :%i do\n  end\nend",
+      \     "affinity": "model"},
+      \   "spec/factories.rb": {
+      \      "command": "factory"},
+      \   "test/factories.rb": {
+      \      "command": "factory"}}
+      \ }, 'keep')
+" }}}
+
+" Other projections {{{
+let g:projectionist_heuristics = {
+      \ "config.ru&docker-compose.yml&app/&config/&OWNERS": {
+      \   "app/jobs/*.rb": {
+      \     "type": "job",
+      \     "alternate": "spec/jobs/{}_spec.rb"
+      \   },
+      \   "app/models/*.rb": {
+      \     "type": "model",
+      \     "alternate": "spec/models/{}_spec.rb"
+      \   },
+      \   "app/resources/*_resource.rb": {
+      \     "type": "resource",
+      \     "alternate": "spec/resources/{}_resource_spec.rb"
+      \   },
+      \   "config/*.yml": {
+      \     "type": "config"
+      \   },
+      \   "spec/*_spec.rb": {
+      \     "type": "spec",
+      \     "alternate": "app/{}.rb"
+      \   },
+      \   "spec/factories/*.rb": {
+      \     "type": "factory",
+      \   }
+      \ },
+      \ "svc-gateway.cabal": {
+      \   "src/*.hs": {
+      \     "type": "src",
+      \     "alternate": "test/{}Spec.hs"
+      \  },
+      \   "test/*Spec.hs": {
+      \     "type": "spec",
+      \     "alternate": "src/{}.hs",
+      \     "template": [
+      \       "module Gateway.Resource.HierarchySpec (main, spec) where",
+      \       "",
+      \       "import Prelude",
+      \       "import Test.Hspec",
+      \       "import Data.Aeson",
+      \       "",
+      \       "import Gateway.Resource.Hierarchy",
+      \       "",
+      \       "main :: IO ()",
+      \       "main = hspec spec",
+      \       "",
+      \       "spec :: Spec",
+      \       "spec = do",
+      \       "    describe \"something\" $ undefined"
+      \    ]
+      \  },
+      \  "svc-gateway.cabal": {
+      \    "type": "cabal"
+      \  }
+      \ },
+      \ "package.json&.flowconfig": {
+      \   "src/*.*": {
+      \     "type": "src",
+      \     "alternate": "test/{}_spec.js"
+      \   }
+      \ },
+      \ "pom.xml&src/main/clj/|src/main/cljs": {
+      \   "*": {
+      \     "start": "USE_NREPL=1 bin/run -m elephant.dev-system" ,
+      \     "connect": "nrepl://localhost:5554",
+      \     "piggieback": "(figwheel-sidecar.repl-api/repl-env)"
+      \   },
+      \   "pom.xml": { "type": "pom" },
+      \   "src/main/clj/*.clj": {
+      \     "alternate": "src/test/clj/{}_test.clj",
+      \     "template": ["(ns {dot|hyphenate})"]
+      \   },
+      \   "src/test/clj/*_test.clj": {
+      \     "alternate": "src/main/clj/{}.clj",
+      \     "dispatch": ":RunTests {dot|hyphenate}-test",
+      \     "template": ["(ns {dot|hyphenate}-test",
+      \                  "  (:require [clojure.test :refer :all]))"]
+      \   },
+      \   "src/main/cljs/*.cljs": {
+      \     "alternate": "src/test/cljs/{}_test.cljs"
+      \   },
+      \   "src/main/cljs/*_test.cljs": {
+      \     "alternate": "src/main/cljs/{}.cljs",
+      \     "dispatch": ":RunTests {dot|hyphenate}-test"
+      \   },
+      \   "src/main/clj/*.cljc": {
+      \     "alternate": "src/test/clj/{}_test.cljc"
+      \   },
+      \   "src/main/clj/*_test.cljc": {
+      \     "alternate": "src/test/clj/{}.cljc",
+      \     "dispatch": ":RunTests {dot|hyphenate}-test"
+      \   }
+      \ }}
+" }}}
+
+" AutoPairs {{{
+let g:AutoPairsCenterLine = 0
+" }}}
+
+" Filetypes {{{
+
+" Python {{{
+aug Python
+  au!
+  au FileType python set tabstop=4 shiftwidth=4 softtabstop=4 expandtab
+aug END
+let g:python_highlight_all=1
+" }}}
+
+" PHP {{{
+aug PHP
+  au!
+  "au FileType php setlocal fdm=marker fmr={{{,}}}
+aug END " }}}
+
+" Mail {{{
+aug Mail
+  au FileType mail setlocal spell
+aug END " }}}
+
+" Haskell {{{
+let g:haskell_conceal_wide = 1
+let g:haskellmode_completion_ghc = 0
+let g:necoghc_enable_detailed_browse = 1
+
+augroup Haskell
+  autocmd!
+  autocmd FileType haskell setlocal textwidth=110 shiftwidth=2
+  autocmd FileType haskell setlocal omnifunc=necoghc#omnifunc
+  autocmd FileType haskell call <SID>HaskellSetup()
+  autocmd FileType haskell setlocal keywordprg=hoogle\ -cie
+augroup END
+
+function! s:HaskellSetup()
+  set sw=4
+  " compiler cabal
+  " let b:start='cabal run'
+  " let b:console='cabal repl'
+  " let b:dispatch='cabal test'
+  compiler stack
+  let b:start='stack run'
+  let b:console='stack ghci'
+  let b:dispatch='stack test'
+  nnoremap <buffer> gy :HdevtoolsType<CR>
+  nnoremap <buffer> yu :HdevtoolsClear<CR>
+endfunction
+" }}}
+
+" Ruby {{{
+
+function! s:RSpecSyntax()
+  syn keyword rspecMethod describe context it its specify shared_context
+        \ shared_examples shared_examples_for shared_context include_examples
+        \ include_context it_should_behave_like it_behaves_like before after
+        \ around fixtures controller_name helper_name scenario feature
+        \ background given described_class
+  syn match rspecMethod '\<let\>!\='
+  syn match rspecMethod '\<subject\>!\='
+  syn keyword rspecMethod violated pending expect expect_any_instance_of allow
+        \ allow_any_instance_of double instance_double mock mock_model
+        \ stub_model xit
+  syn match rspecMethod '\.\@<!\<stub\>!\@!'
+
+  call s:RSpecHiDefaults()
+endfunction
+
+function! s:RSpecHiDefaults()
+  hi def link rspecMethod rubyFunction
+endfunction
+
+augroup Ruby
+  au!
+  " au FileType ruby let b:surround_114 = "\\(module|class,def,if,unless,case,while,until,begin,do) \r end"
+  " au FileType ruby set fdm=syntax
+  au FileType ruby set tw=110
+  au FileType ruby set omnifunc=
+  au FileType ruby nnoremap <buffer> gy orequire 'pry'; binding.pry<ESC>^
+  au FileType ruby nnoremap <buffer> gY Orequire 'pry'; binding.pry<ESC>^
+  au FileType ruby nnoremap <buffer> yu :g/require 'pry'; binding.pry/d<CR>
+  au BufNewFile,BufRead *_spec.rb call <SID>RSpecSyntax()
+augroup END
+
+let ruby_operators = 1
+let ruby_space_errors = 1
+
+let g:rubycomplete_rails = 1
+command! -range ConvertHashSyntax <line1>,<line2>s/:(\S{-})(\s{-})=> /\1:\2/
+" }}}
+
+" Clojure {{{
+
+aug Clojure
+  au!
+  autocmd FileType clojure nnoremap <C-S> :Slamhound<CR>
+  autocmd FileType clojure nnoremap <silent> gr :w <bar> Require <bar> e<CR>
+  let g:clojure_align_multiline_strings = 1
+  let g:clojure_fuzzy_indent_patterns =
+        \ ['^with', '^def', '^let', '^fact']
+  let g:clojure_special_indent_words =
+        \ 'deftype,defrecord,reify,proxy,extend-type,extend-protocol,letfn,html'
+
+  autocmd FileType clojure setlocal textwidth=80
+  autocmd FileType clojure setlocal lispwords+=GET,POST,PATCH,PUT,DELETE |
+        \ setlocal lispwords+=context,select
+  autocmd BufNewFile,BufReadPost *.cljx setfiletype clojure
+  autocmd BufNewFile,BufReadPost *.cljx setlocal omnifunc=
+  autocmd BufNewFile,BufReadPost *.cljs setlocal omnifunc=
+  autocmd FileType clojure call <SID>TangentInit()
+  autocmd FileType clojure call <SID>sexp_mappings()
+  autocmd BufRead *.cljc ClojureHighlightReferences
+  autocmd FileType clojure let b:AutoPairs = {
+        \ '"': '"',
+        \ '{': '}',
+        \ '(': ')',
+        \ '[': ']'}
+        " Don't auto-pair quote reader macros
+        " \'`': '`',
+        " \ '''': '''',
+
+  autocmd User ProjectionistActivate call s:projectionist_connect()
+
+  function! s:projectionist_connect() abort
+    let connected = !empty(fireplace#path())
+    if !connected
+      for [root, value] in projectionist#query('connect')
+        try
+          silent execute "FireplaceConnect" value root
+          let connected = 1
+          break
+        catch /.*Connection refused.*/
+        endtry
+      endfor
+    endif
+
+    " if connected && exists(':Piggieback')
+    "   for [root, value] in projectionist#query('piggieback')
+    "     silent execute "Piggieback" value
+    "     break
+    "   endfor
+    " endif
+  endfunction
+
+  " autocmd BufNewFile,BufReadPost *.cljx setlocal omnifunc=
+  " autocmd BufNewFile,BufReadPost *.cljs setlocal omnifunc=
+
+  autocmd FileType clojure let b:console='lein repl'
+  autocmd FileType clojure call <SID>ClojureMaps()
+
+  function! s:ClojureMaps() abort
+    nnoremap <silent> <buffer> [m :call search('^(def', 'Wzb')<CR>
+    nnoremap <silent> <buffer> ]m :call search('^(def', 'Wz')<CR>
+  endfunction
+
+  command! Scratch call <SID>OpenScratch()
+  autocmd FileType clojure nnoremap <buffer> \s :Scratch<CR>
+
+  let g:scratch_buffer_name = 'SCRATCH'
+
+  function! s:OpenScratch()
+    if bufwinnr(g:scratch_buffer_name) > 0
+      execute bufwinnr(g:scratch_buffer_name) . 'wincmd' 'w'
+      return
+    endif
+
+    vsplit SCRATCH
+    set buftype=nofile
+    set filetype=clojure
+    let b:scratch = 1
+  endfunction
+aug END
+
+function! s:sexp_mappings() abort
+  if !exists('g:sexp_loaded')
+    return
+  endif
+
+  nmap <buffer> cfo <Plug>(sexp_raise_list)
+  nmap <buffer> cfO <Plug>(sexp_raise_element)
+  nmap <buffer> cfe <Plug>(sexp_raise_element)
+endfunction
+
+function! s:TangentInit() abort
+  set textwidth=80
+  command! TReset    call fireplace#session_eval('(user/reset)')
+  command! TGo       call fireplace#session_eval('(user/go)')
+  command! TMigrate  call fireplace#session_eval('(user/migrate)')
+  command! TRollback call fireplace#session_eval('(user/rollback)')
+  nnoremap g\ :TReset<CR>
+endfunction
+
+" }}}
+
+" Go {{{
+
+let g:go_highlight_functions = 1
+let g:go_highlight_methods = 1
+let g:go_highlight_structs = 1
+let g:go_highlight_operators = 1
+let g:go_highlight_build_constraints = 1
+
+augroup Go
+  autocmd!
+  autocmd FileType go setlocal omnifunc=go#complete#Complete
+  autocmd FileType go setlocal foldmethod=syntax
+  autocmd FileType go setlocal foldlevel=100
+  autocmd FileType go nnoremap <buffer> <F9> :GoTest<CR>
+  autocmd FileType go inoremap <buffer> <F9> <ESC>:GoTest<CR>i
+augroup END
+
+" }}}
+
+" RAML {{{
+
+function! s:buffer_syntax() " {{{
+  syn keyword ramlRAML          RAML             contained
+  syn match   ramlVersionString '^#%RAML \d\.\d' contains=ramlRAML
+endfunction " }}}
+
+augroup RAML
+  autocmd!
+  autocmd BufRead,BufNewFile *.raml set filetype=yaml
+  autocmd BufRead,BufNewFile *.raml call s:buffer_syntax()
+augroup END
+
+hi def link ramlVersionString Special
+hi def link ramlRAML Error
+" }}}
+
+" Mustache/Handlebars {{{
+let g:mustache_abbreviations = 1
+" }}}
+
+" Netrw {{{
+augroup netrw
+  autocmd!
+  autocmd FileType netrw nnoremap <buffer> Q :Rexplore<CR>
+
+  " Hee hee, oil and vinegar
+  function! s:setup_oil() abort
+    nnoremap <buffer> q <C-6>
+    xnoremap <buffer> q <C-6>
+  endfunction
+augroup END
+" }}}
+" }}}
+
+" Remove trailing whitespace {{{
+fun! <SID>StripTrailingWhitespaces()
+  let l = line(".")
+  let c = col(".")
+  %s/\s\+$//e
+  call cursor(l, c)
+endfun
+
+augroup striptrailingwhitespaces " {{{
+autocmd FileType c,cpp,java,php,ruby,python,sql,javascript,sh,jst,less,haskell,haml,coffee,scss,clojure,objc,elixir,yaml,json,eruby
+  \ autocmd BufWritePre <buffer> :call <SID>StripTrailingWhitespaces()
+augroup END " }}}
+
+" }}}
+
+" Goyo {{{
+let g:limelight_conceal_ctermfg = "10"
+let g:limelight_conceal_guifg = "#586e75"
+autocmd! User GoyoEnter Limelight
+autocmd! User GoyoLeave Limelight!
+" }}}
+
+"-----------------------------------------------------------------------------
+
+" Commands {{{
+
+" Edit temporary SQL files {{{
+let s:curr_sql = 0
+fun! <SID>EditSqlTempFile()
+  let l:fname = '/tmp/q' . s:curr_sql . '.sql'
+  execute 'edit' l:fname
+  let s:curr_sql = s:curr_sql + 1
+endfun
+com! EditSqlTempFile call <SID>EditSqlTempFile()
+" }}}
+
+" Double Indentation
+command! -range DoubleIndentation <line1>,<line2>s/^\(\s.\{-}\)\(\S\)/\1\1\2/
+
+" Quick-and-dirty fix capitalization of sql files
+command! -range FixSqlCapitalization <line1>,<line2>v/\v(^\s*--.*$)|(TG_)/norm guu
+
+" VimPipe Commands {{{
+" let g:sql_type_default = 'pgsql'
+command! SqlLive let b:vimpipe_command="vagrant ssh -c '~/mysql'"
+command! SqlRails let b:vimpipe_command="bin/rails dbconsole"
+command! SqlHeroku let b:vimpipe_command="heroku pg:psql"
+command! SqlEntities let b:vimpipe_command="psql -h 127.1 entities nomi"
+command! SqlUsers let b:vimpipe_command="psql -h 127.1 users nomi"
+command! SqlTangent let b:vimpipe_command="psql -h local.docker tangent super"
+" }}}
+
+" Git commands {{{
+command! -nargs=* Gpf Gpush -f <args>
+command! -nargs=* Gcv Gcommit --verbose <args>
+" }}}
+
+" Focus dispatch to only the last failures
+command! -nargs=* FocusFailures FocusDispatch rspec --only-failures <args>
+
+" }}}
+
+" Autocommands {{{
+
+augroup fugitive " {{{
+  au!
+  autocmd BufNewFile,BufRead fugitive://* set bufhidden=delete
+augroup END " }}}
+
+augroup omni " {{{
+  au!
+  " autocmd FileType javascript setlocal omnifunc=tern#Complete
+  "autocmd FileType python setlocal omnifunc=pythoncomplete#Complete
+  autocmd FileType php setlocal omnifunc=
+augroup END " }}}
+
+augroup sql " {{{
+  au!
+  autocmd FileType sql                 let b:vimpipe_command="psql -h 127.0.0.1 landlordsny_development landlordsny"
+  autocmd FileType sql                 let b:vimpipe_filetype="postgresql"
+  autocmd FileType sql                 set syntax=postgresql
+  autocmd FileType postgresql          set nowrap
+  autocmd BufNewFile,BufReadPost *.sql set syntax=pgsql
+augroup END " }}}
+
+augroup markdown " {{{
+  au!
+  autocmd FileType markdown let b:vimpipe_command='markdown'
+  autocmd FileType markdown let b:vimpipe_filetype='html'
+  autocmd FileType markdown set tw=80
+augroup END " }}}
+
+augroup typescript " {{{
+  au!
+  autocmd FileType typescript let b:vimpipe_command='tsc'
+  autocmd FileType typescript let b:vimpipe_filetype='javascript'
+  autocmd FileType typescript TSSstarthere
+  autocmd FileType typescript nnoremap <buffer> gd :TSSdef<CR>
+augroup END " }}}
+
+augroup jsx " {{{
+  au!
+  " autocmd FileType jsx set syntax=javascript
+  autocmd FileType javascript set filetype=javascript.jsx
+augroup END " }}}
+
+augroup nicefoldmethod " {{{
+  au!
+  " Don't screw up folds when inserting text that might affect them, until
+  " leaving insert mode. Foldmethod is local to the window. Protect against
+  " screwing up folding when switching between windows.
+  autocmd InsertEnter *
+    \ if !exists('w:last_fdm') |
+    \   let w:last_fdm=&foldmethod |
+    \   setlocal foldmethod=manual |
+    \ endif
+  autocmd InsertLeave,WinLeave *
+    \ if exists('w:last_fdm') |
+    \    let &l:foldmethod=w:last_fdm |
+    \    unlet w:last_fdm |
+    \ endif
+augroup END " }}}
+
+augroup visualbell " {{{
+  au!
+  autocmd GUIEnter * set visualbell t_vb=
+augroup END
+" }}}
+
+augroup quickfix " {{{
+  au!
+  autocmd QuickFixCmdPost grep cwindow
+augroup END " }}}
+
+augroup php " {{{
+  au!
+augroup END  "}}}
+
+augroup rubylang " {{{
+  au!
+  autocmd FileType ruby compiler rake
+augroup END " }}}
+
+augroup javascript "{{{
+  au!
+  autocmd FileType javascript let &errorformat =
+        \ '%E%.%#%n) %s:,' .
+        \ '%C%.%#Error: %m,' .
+        \ '%C%.%#at %s (%f:%l:%c),' .
+        \ '%Z%.%#at %s (%f:%l:%c),' .
+        \ '%-G%.%#,'
+augroup END " }}}
+
+augroup git " {{{
+  autocmd!
+  autocmd FileType gitcommit set textwidth=72
+augroup END
+" }}}
+" }}}
+
+" Leader commands {{{
+
+" Edit specific files {{{
+nnoremap <silent> <leader>ev :split $MYVIMRC<CR>
+nnoremap <silent> <leader>eb :split ~/.vim_bundles<CR>
+nnoremap <silent> <leader>es :UltiSnipsEdit<CR>
+nnoremap <silent> <leader>ea :split ~/.vim/after/plugin/abolish.vim<CR>
+
+nnoremap <silent> <leader>sv :so $MYVIMRC<CR>
+nnoremap <silent> <leader>sb :so ~/.vim_bundles<CR>
+nnoremap <silent> <leader>sa :so ~/.vim/after/plugin/abolish.vim<CR>
+
+nnoremap <Leader>el :EditSqlTempFile<CR>
+" }}}
+
+" Toggle navigation panels {{{
+nnoremap <Leader>l :TagbarToggle<CR>
+nnoremap <Leader>mb :MBEToggle<CR>
+nnoremap <Leader>u :GundoToggle<CR>
+
+nnoremap <Leader>t :CtrlP<CR>
+nnoremap <Leader>z :FZF<CR>
+nnoremap <Leader>b :CtrlPBuffer<CR>
+nnoremap <Leader>a :CtrlPTag<CR>
+nnoremap <Leader>r :CtrlPGitBranch<CR>
+" }}}
+
+" CtrlP {{{
+let g:ctrlp_custom_ignore = {
+      \ 'dir': 'node_modules',
+      \ }
+" }}}
+
+" Git leader commands {{{
+noremap <Leader>g :Git<SPACE>
+noremap <Leader>gu :Gpull<CR>
+noremap <Leader>gp :Gpush<CR>
+noremap <Leader>s :Gstatus<CR>
+noremap <Leader>cv :Gcommit --verbose<CR>
+noremap <Leader>ca :Gcommit --verbose --amend<CR>
+
+nnoremap <Leader>dl :diffg LOCAL<CR>
+nnoremap <Leader>dr :diffg REMOTE<CR>
+nnoremap <Leader>db :diffg BASE<CR>
+nnoremap <Leader>du :diffu<CR>
+nnoremap <Leader>dg :diffg<CR>
+
+nnoremap <Leader>d2 :diffg //2<CR>:diffu<CR>
+nnoremap <Leader>d3 :diffg //3<CR>:diffu<CR>
+
+nnoremap <Leader>yt :SignifyToggle<CR>
+" }}}
+
+" Breakpoint Leader Commands {{{
+nnoremap <Leader>x :Breakpoint<CR>
+nnoremap <Leader>dx :BreakpointRemove *<CR>
+" }}}
+
+" Tabularize {{{
+  " Leader Commands {{{
+  nnoremap <localleader>t= :Tabularize /=<CR>
+  vmap <localleader>t= :Tabularize /=<CR>
+
+  nnoremap <localleader>t> :Tabularize /=><CR>
+  vmap <localleader>t> :Tabularize /=><CR>
+  " }}}
+
+  " => Aligning {{{
+  function! s:rocketalign()
+    let l:p = '^.*=>\s.*$'
+    echo l:p
+    if exists(':Tabularize') && getline('.') =~# '^.*=' &&
+                \ (getline(line('.')-1) =~# l:p || getline(line('.')+1) =~# l:p)
+      let column = strlen(substitute(getline('.')[0:col('.')],'[^=>]','','g'))
+      let position = strlen(matchstr(getline('.')[0:col('.')],'.*=>\s*\zs.*'))
+      Tabularize/=>/l1
+      normal! $
+      call search(repeat('[^=>]*=>',column).'\s\{-\}'.repeat('.',position),'ce',line('.'))
+    endif
+  endfunction
+  "inoremap <buffer> <space>=><space> =><Esc>:call <SID>rocketalign()<CR>a
+  " }}}
+
+  " = Aligning {{{
+  function! s:eqalign()
+    let l:p = '^.*=\s.*$'
+    if exists(':Tabularize') && getline('.') =~# '^.*=' &&
+                \ (getline(line('.')-1) =~# l:p || getline(line('.')+1) =~# l:p)
+      let column = strlen(substitute(getline('.')[0:col('.')],'[^=]','','g'))
+      let position = strlen(matchstr(getline('.')[0:col('.')],'.*=\s*\zs.*'))
+      Tabularize/=/l1
+      normal! $
+      call search(repeat('[^=]*=',column).'\s\{-\}'.repeat('.',position),'ce',line('.'))
+    endif
+  endfunction
+  "inoremap <buffer><silent> <space>=<space> =<Esc>:call <SID>eqalign()<CR>a
+  " }}}
+
+  " : Aligning {{{
+  function! s:colonalign()
+    let l:p : '^.*:\s.*$'
+    if exists(':Tabularize') && getline('.') :~# '^.*:' &&
+                \ (getline(line('.')-1) :~# l:p || getline(line('.')+1) :~# l:p)
+      let column : strlen(substitute(getline('.')[0:col('.')],'[^:]','','g'))
+      let position : strlen(matchstr(getline('.')[0:col('.')],'.*:\s*\zs.*'))
+      Tabularize/:/l1
+      normal! $
+      call search(repeat('[^:]*:',column).'\s\{-\}'.repeat('.',position),'ce',line('.'))
+    endif
+  endfunction
+  "inoremap <buffer><silent> <space>:<space> :<Esc>:call <SID>colonalign()<CR>a
+  " }}}
+" }}}
+
+" }}}
+
+" Mappings {{{
+" 'delete current'
+nnoremap dc 0d$
+nnoremap com :silent !tmux set status<CR>
+nnoremap <F9>  :Make<CR>
+nnoremap g<CR> :Dispatch<CR>
+nnoremap g\ :Start<CR>
+inoremap <F9> <ESC>:Make<CR>i
+
+" Navigate buffers {{{
+nnoremap gb :bn<CR>
+nnoremap gB :bp<CR>
+" }}}
+
+" Window Navigation {{{
+nnoremap <space>w <C-w>
+nnoremap <space>h <C-w>h
+nnoremap <space>j <C-w>j
+nnoremap <space>k <C-w>k
+nnoremap <space>l <C-w>l
+nnoremap <space>z <C-w>z
+" }}}
+
+
+" Sort with motion {{{
+if !exists("g:sort_motion_flags")
+  let g:sort_motion_flags = ""
+endif
+function! s:sort_motion(mode) abort
+  if a:mode == 'line'
+    execute "'[,']sort " . g:sort_motion_flags
+  elseif a:mode == 'char'
+    execute "normal! `[v`]y"
+    let sorted = join(sort(split(@@, ', ')), ', ')
+    execute "normal! v`]c" . sorted
+  elseif a:mode == 'V' || a:mode == ''
+    execute "'<,'>sort " . g:sort_motion_flags
+  endif
+endfunction
+
+function! s:sort_lines()
+  let beginning = line('.')
+  let end = v:count + beginning - 1
+  execute beginning . ',' . end . 'sort'
+endfunction
+
+xnoremap <silent> <Plug>SortMotionVisual :<C-U>call <SID>sort_motion(visualmode())<CR>
+nnoremap <silent> <Plug>SortMotion :<C-U>set opfunc=<SID>sort_motion<CR>g@
+nnoremap <silent> <Plug>SortLines :<C-U>call <SID>sort_lines()<CR>
+
+map go <Plug>SortMotion
+vmap go <Plug>SortMotionVisual
+map goo <Plug>SortLines
+" }}}
+" }}}
+
+let g:hare_executable = 'cabal exec -- ghc-hare'
diff --git a/users/glittershark/system/home/modules/zshrc b/users/glittershark/system/home/modules/zshrc
new file mode 100644
index 000000000000..cca822c4ce3e
--- /dev/null
+++ b/users/glittershark/system/home/modules/zshrc
@@ -0,0 +1,306 @@
+#!/usr/bin/zsh
+# vim: set fdm=marker fmr={{{,}}}:
+
+stty -ixon
+
+# Compinstall {{{
+zstyle ':completion:*' completer _complete _ignored _correct _approximate
+zstyle ':completion:*' matcher-list '' 'm:{[:lower:]}={[:upper:]} m:{[:lower:][:upper:]}={[:upper:][:lower:]} r:|[._- :]=** r:|=**' 'l:|=* r:|=*'
+zstyle ':completion:*' max-errors 5
+zstyle ':completion:*' use-cache yes
+zstyle ':completion::complete:grunt::options:' expire 1
+zstyle ':completion:*' prompt '%e errors'
+zstyle :compinstall filename '~/.zshrc'
+autoload -Uz compinit
+compinit
+# }}}
+
+# Zsh-newuser-install {{{
+HISTFILE=~/.histfile
+HISTSIZE=1000
+SAVEHIST=1000
+setopt appendhistory autocd extendedglob notify autopushd
+unsetopt beep nomatch
+bindkey -v
+# }}}
+
+# Basic options {{{
+set -o vi
+umask 022
+export VIRTUAL_ENV_DISABLE_PROMPT=1
+# export PATH=~/.local/bin:~/.cabal/bin:$PATH:~/code/go/bin:~/bin:~/npm/bin:~/.gem/ruby/2.1.0/bin:~/.gem/ruby/2.0.0/bin:/home/smith/bin
+# }}}
+
+# Zsh highlight highlighters {{{
+ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets pattern root)
+# }}}
+
+# More basic options {{{
+setopt no_hist_verify
+setopt histignorespace
+# }}}
+
+# Utility Functions {{{
+
+# Set the terminal's title bar.
+function titlebar() {
+echo -ne "\033]0;$*\007"
+}
+
+function quiet() {
+"$@" >/dev/null
+}
+
+function quieter() {
+"$@" >/dev/null 2>&1
+}
+
+# From http://stackoverflow.com/questions/370047/#370255
+function path_remove() {
+IFS=:
+# convert it to an array
+t=($PATH)
+unset IFS
+# perform any array operations to remove elements from the array
+t=(${t[@]%%$1})
+IFS=:
+# output the new array
+echo "${t[*]}"
+}
+
+# }}}
+
+# Force screen to use zsh {{{
+# }}}
+
+# Environment {{{
+# }}}
+
+# Directory Stuff {{{
+
+# Always use color output for `ls`
+
+# Directory listing
+
+# Easier navigation: .., ..., -
+
+# File size
+
+# Recursively delete `.DS_Store` files
+
+# Create a new directory and enter it
+function md() {
+  mkdir -p "$@" && cd "$@"
+}
+
+# }}}
+
+# MPD/MPC stuff {{{
+function mp() {
+# Test if drive is already mounted
+if ! lsblk | grep /media/external >/dev/null; then
+  if ! sudo mount /media/external; then
+    echo "External drive not plugged in, or could not mount"
+    return 1
+  fi
+fi
+if (mpc >/dev/null 2>&1); then
+  ncmpcpp
+else
+  mpd &&
+    (pgrep mpdscribble || mpdscribble) &&
+    ncmpcpp
+fi
+}
+
+# kill mp
+function kmp() {
+killall ncmpcpp
+mpd --kill
+
+local files
+
+if (files=$(lsof 2>&1 | grep -v docker | grep external)); then
+  echo
+  echo "==> Still processes using external drive:"
+  echo
+  echo $files
+else
+  sudo umount /media/external
+fi
+}
+
+
+function mppal() {
+mpc search album "$1" | mpc add &&
+  mpc play;
+}
+# }}}
+
+# Git stuff {{{
+# function ga() { git add "${@:-.}"; } # Add all files by default
+# Add non-whitespace changes
+# function gc() { git checkout "${@:-master}"; } # Checkout master by default
+
+# open all changed files (that still actually exist) in the editor
+function ged() {
+local files=()
+for f in $(git diff --name-only "$@"); do
+  [[ -e "$f" ]] && files=("${files[@]}" "$f")
+done
+local n=${#files[@]}
+echo "Opening $n $([[ "$@" ]] || echo "modified ")file$([[ $n != 1 ]] && \
+  echo s)${@:+ modified in }$@"
+q "${files[@]}"
+}
+
+# git find-replace
+function gfr() {
+if [[ "$#" == "0" ]]; then
+  echo 'Usage:'
+  echo ' gg_replace term replacement file_mask'
+  echo
+  echo 'Example:'
+  echo ' gg_replace cappuchino cappuccino *.html'
+  echo
+else
+  find=$1; shift
+  replace=$1; shift
+
+  ORIG_GLOBIGNORE=$GLOBIGNORE
+  GLOBIGNORE=*.*
+  if [[ "$#" = "0" ]]; then
+    set -- ' ' $@
+  fi
+
+  while [[ "$#" -gt "0" ]]; do
+    for file in `git grep -l $find -- $1`; do
+      sed -e "s/$find/$replace/g" -i'' $file
+    done
+    shift
+  done
+
+  GLOBIGNORE=$ORIG_GLOBIGNORE
+fi
+}
+
+function vconflicts() {
+$EDITOR $(git status --porcelain | awk '/^UU/ { print $2 }')
+}
+# }}}
+
+# fzf {{{
+v() {
+  local file
+  file=$(fzf-tmux --query="$1" --select-1 --exit-0)
+  [ -n "$file" ] && ${EDITOR:-vim} "$file"
+}
+
+c() {
+  local dir
+  dir=$(find ${1:-*} -path '*/\.*' -prune -o -type d -print 2> /dev/null | fzf +m) && cd "$dir"
+}
+
+co() {
+  local branch
+  branch=$(git branch -a | sed -s "s/\s*\**//g" | fzf --query="$1" --select-1 --exit-0) && git checkout "$branch"
+}
+
+
+# fh - repeat history
+# h() {
+#   eval $(([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s | sed 's/ *[0-9]* *//')
+# }
+
+# fkill - kill process
+fkill() {
+  ps -ef | sed 1d | fzf-tmux -m | awk '{print $2}' | xargs kill -${1:-9}
+}
+# }}}
+
+# Tmux utils {{{
+kill_detached() {
+  for sess in $(tmux ls | grep -v attached | sed -s "s/:.*$//"); do
+    tmux kill-session -t $sess;
+  done
+}
+# }}}
+
+# Docker {{{
+
+
+# dbp foo/bar .
+function dbp () {
+  docker build -t $1 ${@:2} && docker push $1
+}
+
+# }}}
+
+# Vagrant {{{
+# }}}
+
+# Twitter! {{{
+
+
+# favelast <username>
+function favelast() {
+  t fave $(t tl -l $1 | head -n1 | first)
+}
+
+function rtlast() {
+  t rt $(t tl -l $1 | head -n1 | first)
+}
+
+function tthread() {
+  t reply $(t tl -l $TWITTER_WHOAMI | head -n1 | first) $@
+}
+# }}}
+
+# Geeknote {{{
+gnc() {
+  gn create --title $1 --content '' &&
+    gn find --count=1 "$1"
+    gn edit 1
+}
+# }}}
+
+# Systemd aliases {{{
+# }}}
+
+# Misc aliases {{{
+
+function fw() { # fix white
+  local substitution
+  local substitution='s/\x1b\[90m/\x1b[92m/g'
+  $@ > >(perl -pe "$substitution") 2> >(perl -pe "$substitution" 1>&2)
+}
+# }}}
+
+# Grep options {{{
+unset GREP_OPTIONS
+export GREP_OPTIONS=
+# }}}
+
+
+# Run docker containers {{{
+    # -d \
+    # -v $HOME/.pentadactyl:/home/firefox/.pentadactyl:rw \
+    # -v $HOME/.pentadactylrc:/home/firefox/.pentadactylrc:rw \
+    # -v $HOME/.mozilla:/home/firefox/.mozilla:rw \
+    # -v $HOME/.config:/home/firefox/.config \
+    # -v $HOME/Downloads:/home/firefox/Downloads:rw \
+    # -v /etc/fonts:/etc/fonts \
+    # -v /tmp/.X11-unix:/tmp/.X11-unix \
+    # -v /dev/snd:/dev/snd \
+    # --net=host \
+    # -v $XDG_RUNTIME_DIR:$XDG_RUNTIME_DIR \
+    # -e uid=$(id -u) \
+    # -e gid=$(id -g) \
+    # -e DISPLAY=$DISPLAY \
+    # -e XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \
+    # --name firefox \
+    # --rm -it \
+    # glittershark/firefox
+# }}}
+
+[ -f ./.localrc ] && source ./.localrc
diff --git a/users/glittershark/system/home/platforms/darwin.nix b/users/glittershark/system/home/platforms/darwin.nix
new file mode 100644
index 000000000000..d6b33ba5625c
--- /dev/null
+++ b/users/glittershark/system/home/platforms/darwin.nix
@@ -0,0 +1,24 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  home.packages = with pkgs; [
+    coreutils
+    gnupg
+    pinentry_mac
+  ];
+
+  home.activation.linkApplications = lib.hm.dag.entryAfter ["writeBoundary"] ''
+    $DRY_RUN_CMD ln -sf $VERBOSE_ARG \
+      ~/.nix-profile/Applications/* ~/Applications/
+  '';
+
+  programs.zsh.initExtra = ''
+    export NIX_PATH=$HOME/.nix-defexpr/channels:$NIX_PATH
+
+    if [[ "$TERM" == "alacritty" ]]; then
+      export TERM="xterm-256color"
+    fi
+  '';
+}
diff --git a/users/glittershark/system/home/platforms/linux.nix b/users/glittershark/system/home/platforms/linux.nix
new file mode 100644
index 000000000000..6ffc1c770d70
--- /dev/null
+++ b/users/glittershark/system/home/platforms/linux.nix
@@ -0,0 +1,89 @@
+{ config, pkgs, ... }:
+
+{
+  imports = [
+    ../modules/alacritty.nix
+    ../modules/alsi.nix
+    ../modules/development.nix
+    ../modules/emacs.nix
+    ../modules/email.nix
+    ../modules/firefox.nix
+    ../modules/games.nix
+    ../modules/obs.nix
+    ../modules/i3.nix
+    ../modules/shell.nix
+    ../modules/tarsnap.nix
+    ../modules/vim.nix
+  ];
+
+  xsession.enable = true;
+
+  home.packages = with pkgs; [
+    (import (fetchTarball "https://github.com/ashkitten/nixpkgs/archive/init-glimpse.tar.gz") {}).glimpse
+
+    # Desktop stuff
+    arandr
+    firefox
+    feh
+    chromium
+    xclip
+    xorg.xev
+    picom
+    peek
+    signal-desktop
+    apvlv # pdf viewer
+    vlc
+    irssi
+    gnutls
+    pandoc
+    barrier
+
+    # System utilities
+    powertop
+    usbutils
+    pciutils
+    gdmap
+    lsof
+    tree
+    ncat
+    iftop
+
+    # Security
+    gnupg
+    keybase
+    openssl
+
+    # Spotify...etc
+    spotify
+    playerctl
+  ];
+
+  services.redshift = {
+    enable = true;
+    provider = "geoclue2";
+  };
+
+  services.pasystray.enable = true;
+
+  services.gpg-agent = {
+    enable = true;
+  };
+
+  gtk = {
+    enable = true;
+    gtk3.bookmarks = [
+      "file:///home/grfn/code"
+    ];
+  };
+
+  programs.tarsnap = {
+    enable = true;
+    keyfile = "/home/grfn/.private/tarsnap.key";
+    printStats = true;
+    humanizeNumbers = true;
+  };
+
+  programs.zsh.initExtra = ''
+    [[ ! $IN_NIX_SHELL ]] && alsi -l
+  '';
+}
diff --git a/users/glittershark/system/install b/users/glittershark/system/install
new file mode 100755
index 000000000000..a9a45953da07
--- /dev/null
+++ b/users/glittershark/system/install
@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+if [[ -f /etc/nixos/.system-installed ]]; then
+    echo "=== System config already installed, skipping"
+else
+    echo "==> Installing system config"
+
+    [[ -d /etc/nixos ]] && sudo mv /etc/nixos{,.bak}
+    sudo mkdir -p /etc/nixos
+    sudo cp /etc/nixos.bak/hardware-configuration.nix /etc/nixos
+
+    sudo cp ./system/configuration.nix /etc/nixos/
+    sudo ln -s $(pwd)/system/{machines,modules,pkgs} /etc/nixos
+    sudo touch /etc/nixos/.system-installed
+
+    echo "==> System config installed, your old configuration is at /etc/nixos.bak"
+fi
+echo
+
+if [[ -f ~/.config/nixpkgs/system-installed ]]; then
+    echo "=== home-manager config already installed, skipping"
+else
+    echo "==> Installing home-manager config"
+    nix-channel --add https://github.com/rycee/home-manager/archive/master.tar.gz home-manager
+    nix-channel --update
+    # nix-shell '<home-manager>' -A install
+
+    [[ -d ~/.config/nixpkgs ]] && mv ~/.config/{nixpkgs,nixpkgs.bak}
+    mkdir -p ~/.config/nixpkgs
+    ln -s $(pwd)/home/* ~/.config/nixpkgs
+
+    echo "==> home-manager config installed"
+fi
diff --git a/users/glittershark/system/pkgs/alsi/default.nix b/users/glittershark/system/pkgs/alsi/default.nix
new file mode 100644
index 000000000000..d4da8ff38ef7
--- /dev/null
+++ b/users/glittershark/system/pkgs/alsi/default.nix
@@ -0,0 +1,22 @@
+{ perl, stdenv, fetchFromGitHub }:
+stdenv.mkDerivation {
+  name = "alsi";
+  pname = "alsi";
+  version = "0.4.8";
+
+  src = fetchFromGitHub {
+    owner = "trizen";
+    repo = "alsi";
+    rev = "fe2a925caad38d4cc7afe10d74ba60c5db09ee66";
+    sha256 = "060xlalfclrda5f1h3svj4v2gr19mdrsc62vrg7hgii0f3lib7j5";
+  };
+
+  buildInputs = [
+    (perl.withPackages (ps: with ps; [ DataDump ]))
+  ];
+
+  installPhase = ''
+    mkdir -p $out/bin
+    cp alsi $out/bin/alsi
+  '';
+}
diff --git a/users/glittershark/system/pkgs/argocd.nix b/users/glittershark/system/pkgs/argocd.nix
new file mode 100644
index 000000000000..5ab0e95d4462
--- /dev/null
+++ b/users/glittershark/system/pkgs/argocd.nix
@@ -0,0 +1 @@
+(import <nixpkgs-unstable> {}).argocd
diff --git a/users/glittershark/system/pkgs/clang-tools.nix b/users/glittershark/system/pkgs/clang-tools.nix
new file mode 100644
index 000000000000..d13fbd44576a
--- /dev/null
+++ b/users/glittershark/system/pkgs/clang-tools.nix
@@ -0,0 +1,15 @@
+with import <nixpkgs> {};
+runCommand "clang-tools" {} ''
+  mkdir -p $out/bin
+  for file in ${clang-tools}/bin/*; do
+    if [ $(basename "$file") != "clangd" ]; then
+      ln -s "$file" $out/bin
+    fi
+  done
+
+  sed \
+    -e "18iexport CPLUS_INCLUDE_PATH=${llvmPackages.libcxx}/include/c++/v1\\''${CPATH:+':'}\\''${CPATH}" \
+    -e '/CPLUS_INCLUDE_PATH/d' \
+      < ${clang-tools}/bin/clangd \
+      > $out/bin/clangd
+''
diff --git a/users/glittershark/system/pkgs/clang-tools/default.nix b/users/glittershark/system/pkgs/clang-tools/default.nix
new file mode 100644
index 000000000000..7c1009665eb6
--- /dev/null
+++ b/users/glittershark/system/pkgs/clang-tools/default.nix
@@ -0,0 +1,24 @@
+{ pkgs }:
+with pkgs;
+
+runCommand "clang-tools" {} ''
+  mkdir -p $out/bin
+  export libc_includes="${stdenv.lib.getDev stdenv.cc.libc}/include"
+  export libcpp_includes="${llvmPackages.libcxx}/include/c++/v1"
+
+  export clang=${llvmPackages.clang-unwrapped}
+
+  echo $clang
+
+  substituteAll ${./wrapper} $out/bin/clangd
+  chmod +x $out/bin/clangd
+  for tool in \
+    clang-apply-replacements \
+    clang-check \
+    clang-format \
+    clang-rename \
+    clang-tidy
+  do
+    ln -s $out/bin/clangd $out/bin/$tool
+  done
+''
diff --git a/users/glittershark/system/pkgs/clang-tools/wrapper b/users/glittershark/system/pkgs/clang-tools/wrapper
new file mode 100644
index 000000000000..949a4243e009
--- /dev/null
+++ b/users/glittershark/system/pkgs/clang-tools/wrapper
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+buildcpath() {
+  local path
+  while (( $# )); do
+    case $1 in
+        -isystem)
+            shift
+            path=$path${path:+':'}$1
+    esac
+    shift
+  done
+  echo $path
+}
+
+export CPATH=${CPATH}${CPATH:+':'}$(buildcpath ${NIX_CFLAGS_COMPILE})
+export CPATH=${CPATH}${CPATH:+':'}@libc_includes@
+export CPLUS_INCLUDE_PATH=@libcpp_includes@${CPATH:+':'}${CPATH}
+
+exec -a "$0" @clang@/bin/$(basename $0) "$@"
diff --git a/users/glittershark/system/system/configuration.nix b/users/glittershark/system/system/configuration.nix
new file mode 100644
index 000000000000..eae567015b73
--- /dev/null
+++ b/users/glittershark/system/system/configuration.nix
@@ -0,0 +1,11 @@
+{ config, pkgs, ... }:
+
+let machine = throw "Pick a machine from ./machines"; in
+{
+  imports =
+    [
+      /etc/nixos/hardware-configuration.nix
+      ./modules/common.nix
+      machine
+    ];
+}
diff --git a/users/glittershark/system/system/machines/bumblebee.nix b/users/glittershark/system/system/machines/bumblebee.nix
new file mode 100644
index 000000000000..0fec21409255
--- /dev/null
+++ b/users/glittershark/system/system/machines/bumblebee.nix
@@ -0,0 +1,23 @@
+{ config, lib, pkgs, ... }:
+{
+  imports = [
+    ../modules/reusable/battery.nix
+  ];
+
+  networking.hostName = "bumblebee";
+
+  powerManagement = {
+    enable = true;
+    cpuFreqGovernor = "powersave";
+    powertop.enable = true;
+  };
+
+  # Hibernate on low battery
+  laptop.onLowBattery = {
+    enable = true;
+    action = "hibernate";
+    thresholdPercentage = 5;
+  };
+
+  services.xserver.xkbOptions = "caps:swapescape";
+}
diff --git a/users/glittershark/system/system/machines/chupacabra.nix b/users/glittershark/system/system/machines/chupacabra.nix
new file mode 100644
index 000000000000..99225e354562
--- /dev/null
+++ b/users/glittershark/system/system/machines/chupacabra.nix
@@ -0,0 +1,50 @@
+{ config, lib, pkgs, ... }:
+{
+  imports = [
+    ../modules/reusable/battery.nix
+    <nixos-hardware/common/cpu/intel>
+    <nixos-hardware/common/pc/laptop>
+  ];
+
+  networking.hostName = "chupacabra";
+
+  powerManagement = {
+    enable = true;
+    powertop.enable = true;
+  };
+
+  laptop.onLowBattery = {
+    enable = true;
+    action = "hibernate";
+    thresholdPercentage = 5;
+  };
+
+  boot.initrd.luks.devices."cryptswap".device = "/dev/disk/by-uuid/3b6e2fd4-bfe9-4392-a6e0-4f3b3b76e019";
+
+  boot.kernelParams = [ "acpi_rev_override" ];
+  services.thermald.enable = true;
+
+  hardware.cpu.intel.updateMicrocode = true;
+
+  # Intel-only graphics
+  hardware.nvidiaOptimus.disable = true;
+  boot.blacklistedKernelModules = [ "nouveau" "intel" ];
+  services.xserver.videoDrivers = [ "intel" ];
+
+  # Nvidia Optimus (hybrid) - currently not working
+  # services.xserver.videoDrivers = [ "intel" "nvidia" ];
+  # boot.blacklistedKernelModules = [ "nouveau" "bbswitch" ];
+  # boot.extraModulePackages = [ pkgs.linuxPackages.nvidia_x11 ];
+  # hardware.bumblebee.enable = true;
+  # hardware.bumblebee.pmMethod = "none";
+
+  systemd.services.disable-usb-autosuspend = {
+    description = "Disable USB autosuspend";
+    wantedBy = [ "multi-user.target" ];
+    serviceConfig = { Type = "oneshot"; };
+    unitConfig.RequiresMountsFor = "/sys";
+    script = ''
+      echo -1 > /sys/module/usbcore/parameters/autosuspend
+    '';
+  };
+}
diff --git a/users/glittershark/system/system/modules/common.nix b/users/glittershark/system/system/modules/common.nix
new file mode 100644
index 000000000000..66d57704a089
--- /dev/null
+++ b/users/glittershark/system/system/modules/common.nix
@@ -0,0 +1,142 @@
+{ config, lib, pkgs, ... }:
+
+{
+  imports =
+    [
+      ./xserver.nix
+      ./fonts.nix
+      ./sound.nix
+      ./kernel.nix
+      ./rtlsdr.nix
+      /home/grfn/code/urb/urbos/system
+    ];
+
+  boot.loader.systemd-boot.enable = true;
+  boot.loader.efi.canTouchEfiVariables = true;
+
+  networking.useDHCP = false;
+  networking.networkmanager.enable = true;
+
+  # Select internationalisation properties.
+  # i18n = {
+  #   consoleFont = "Lat2-Terminus16";
+  #   consoleKeyMap = "us";
+  #   defaultLocale = "en_US.UTF-8";
+  # };
+
+  # Set your time zone.
+  time.timeZone = "America/New_York";
+
+  environment.systemPackages = with pkgs; [
+    wget
+    vim
+    zsh
+    git
+    w3m
+    libnotify
+    file
+    lm_sensors
+  ];
+
+  # Some programs need SUID wrappers, can be configured further or are
+  # started in user sessions.
+  # programs.mtr.enable = true;
+  # programs.gnupg.agent = {
+  #   enable = true;
+  #   enableSSHSupport = true;
+  #   pinentryFlavor = "gnome3";
+  # };
+
+  programs.nm-applet.enable = true;
+
+
+  services.openssh.enable = true;
+
+  programs.ssh.startAgent = true;
+
+  # Open ports in the firewall.
+  # networking.firewall.allowedTCPPorts = [ ... ];
+  # networking.firewall.allowedUDPPorts = [ ... ];
+  # Or disable the firewall altogether.
+  networking.firewall.enable = false;
+
+  # Enable CUPS to print documents.
+  # services.printing.enable = true;
+
+  users.mutableUsers = true;
+  programs.zsh.enable = true;
+  environment.pathsToLink = [ "/share/zsh" ];
+  users.users.grfn = {
+    isNormalUser = true;
+    initialPassword = "password";
+    extraGroups = [
+      "wheel"
+      "networkmanager"
+      "audio"
+      "docker"
+    ];
+    shell = pkgs.zsh;
+  };
+
+  # This value determines the NixOS release from which the default
+  # settings for stateful data, like file locations and database versions
+  # on your system were taken. It‘s perfectly fine and recommended to leave
+  # this value at the release version of the first install of this system.
+  # Before changing this value read the documentation for this option
+  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
+  system.stateVersion = "20.03"; # Did you read the comment?
+
+  nixpkgs.config.allowUnfree = true;
+
+  services.geoclue2.enable = true;
+
+  powerManagement = {
+    enable = true;
+    cpuFreqGovernor = lib.mkDefault "powersave";
+    powertop.enable = true;
+  };
+  # Hibernate on low battery
+  laptop.onLowBattery = {
+    enable = true;
+    action = "hibernate";
+    thresholdPercentage = 5;
+  };
+
+  nix = {
+    trustedUsers = [ "grfn" ];
+    autoOptimiseStore = true;
+
+    buildMachines = [{
+      hostName = "172.16.0.3";
+      sshUser = "griffin";
+      sshKey = "/home/grfn/.ssh/id_rsa";
+      system = "x86_64-darwin";
+      maxJobs = 4;
+    } {
+      hostName = "172.16.0.4";
+      sshUser = "griffin";
+      sshKey = "/home/grfn/.ssh/id_rsa";
+      system = "x86_64-darwin";
+      maxJobs = 8; # 16 cpus
+    }];
+
+    distributedBuilds = true;
+
+    gc = {
+      automatic = true;
+      dates = "weekly";
+      options = "--delete-older-than 30d";
+    };
+  };
+
+  urbos.enable = true;
+  urbos.username = "grfn";
+
+  services.udev.extraRules = ''
+    # UDEV rules for Teensy USB devices
+    ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", ENV{ID_MM_DEVICE_IGNORE}="1"
+    ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789A]?", ENV{MTP_NO_PROBE}="1"
+    SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789ABCD]?", MODE:="0666"
+    KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", MODE:="0666"
+  '';
+}
diff --git a/users/glittershark/system/system/modules/fonts.nix b/users/glittershark/system/system/modules/fonts.nix
new file mode 100644
index 000000000000..babe30d4271f
--- /dev/null
+++ b/users/glittershark/system/system/modules/fonts.nix
@@ -0,0 +1,12 @@
+{ config, lib, pkgs, ... }:
+{
+  fonts = {
+    fonts = with pkgs; [
+      nerdfonts
+      noto-fonts-emoji
+      twitter-color-emoji
+    ];
+
+    fontconfig.defaultFonts.emoji = ["Twitter Color Emoji"];
+  };
+}
diff --git a/users/glittershark/system/system/modules/kernel.nix b/users/glittershark/system/system/modules/kernel.nix
new file mode 100644
index 000000000000..92aa6955a73b
--- /dev/null
+++ b/users/glittershark/system/system/modules/kernel.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+with lib.versions;
+let
+  inherit (pkgs) runCommand;
+  kernelRelease = config.linuxPackages.kernel.version or pkgs.linux.version;
+  mj = major kernelRelease;
+  mm = majorMinor kernelRelease;
+  linux-ck = runCommand "linux-ck-combined.patch" {} ''
+    ${pkgs.xz}/bin/unxz -kfdc ${builtins.fetchurl {
+      # http://ck.kolivas.org/patches/5.0/5.4/5.4-ck1/patch-5.4-ck1.xz
+      url = "http://ck.kolivas.org/patches/${mj}.0/${mm}/${mm}-ck1/patch-${mm}-ck1.xz";
+      sha256 = "0p2ccwlsmq0587x6cnbrk4h2bwpl9342bmhsbyi1a87cs2jfwigl";
+    }} > $out
+  '';
+in
+{
+  boot.kernelPackages = pkgs.linuxPackages.extend (self: super: {
+    kernel = super.kernel.override {
+      kernelPatches = super.kernel.kernelPatches ++ [{
+        name = "linux-ck";
+        patch = linux-ck;
+      }];
+      argsOverride = {
+        modDirVersion = super.kernel.modDirVersion + "-ck1";
+      };
+    };
+  });
+}
diff --git a/users/glittershark/system/system/modules/reusable/README.org b/users/glittershark/system/system/modules/reusable/README.org
new file mode 100644
index 000000000000..34d9bfdcb729
--- /dev/null
+++ b/users/glittershark/system/system/modules/reusable/README.org
@@ -0,0 +1,2 @@
+This directory contains things I'm eventually planning on contributing upstream
+to nixpkgs
diff --git a/users/glittershark/system/system/modules/reusable/battery.nix b/users/glittershark/system/system/modules/reusable/battery.nix
new file mode 100644
index 000000000000..d7043bf54979
--- /dev/null
+++ b/users/glittershark/system/system/modules/reusable/battery.nix
@@ -0,0 +1,32 @@
+{ config, lib, pkgs, ... }:
+with lib;
+{
+  options = {
+    laptop.onLowBattery = {
+      enable = mkEnableOption "Perform action on low battery";
+
+      thresholdPercentage = mkOption {
+        description = "Threshold battery percentage on which to perform the action";
+        default = 5;
+        type = types.int;
+      };
+
+      action = mkOption {
+        description = "Action to perform on low battery";
+        default = "hibernate";
+        type = types.enum [ "hibernate" "suspend" "suspend-then-hibernate" ];
+      };
+    };
+  };
+
+  config =
+    let cfg = config.laptop.onLowBattery;
+    in mkIf cfg.enable {
+    services.udev.extraRules = concatStrings [
+      ''SUBSYSTEM=="power_supply", ''
+      ''ATTR{status}=="Discharging", ''
+      ''ATTR{capacity}=="[0-${toString cfg.thresholdPercentage}]", ''
+      ''RUN+="/${pkgs.systemd}/bin/systemctl ${cfg.action}"''
+    ];
+  };
+}
diff --git a/users/glittershark/system/system/modules/rtlsdr.nix b/users/glittershark/system/system/modules/rtlsdr.nix
new file mode 100644
index 000000000000..ce58ebb0dcda
--- /dev/null
+++ b/users/glittershark/system/system/modules/rtlsdr.nix
@@ -0,0 +1,17 @@
+{ config, lib, pkgs, ... }:
+
+{
+
+  environment.systemPackages = with pkgs; [
+    rtl-sdr
+  ];
+
+  services.udev.packages = with pkgs; [
+    rtl-sdr
+  ];
+
+  # blacklist for rtl-sdr
+  boot.blacklistedKernelModules = [
+    "dvb_usb_rtl28xxu"
+  ];
+}
diff --git a/users/glittershark/system/system/modules/sound.nix b/users/glittershark/system/system/modules/sound.nix
new file mode 100644
index 000000000000..0d5ce3e318c3
--- /dev/null
+++ b/users/glittershark/system/system/modules/sound.nix
@@ -0,0 +1,14 @@
+{ config, lib, pkgs, ... }:
+{
+  # Enable sound.
+  sound.enable = true;
+  hardware.pulseaudio.enable = true;
+  nixpkgs.config.pulseaudio = true;
+
+  environment.systemPackages = with pkgs; [
+    pulseaudio-ctl
+    paprefs
+    pasystray
+    pavucontrol
+  ];
+}
diff --git a/users/glittershark/system/system/modules/xserver.nix b/users/glittershark/system/system/modules/xserver.nix
new file mode 100644
index 000000000000..2638f075249c
--- /dev/null
+++ b/users/glittershark/system/system/modules/xserver.nix
@@ -0,0 +1,18 @@
+{ config, pkgs, ... }:
+{
+  # Enable the X11 windowing system.
+  services.xserver = {
+    enable = true;
+    layout = "us";
+
+    libinput.enable = true;
+
+    windowManager.i3 = {
+      enable = true;
+      extraPackages = with pkgs; [
+        i3status
+        i3lock
+      ];
+    };
+  };
+}