diff --git a/2configs/tv/git-public.nix b/2configs/tv/git-public.nix
index 7babcbb5b..7222f99eb 100644
--- a/2configs/tv/git-public.nix
+++ b/2configs/tv/git-public.nix
@@ -1,87 +1,80 @@
 { config, lib, pkgs, ... }:
-
-with lib;
+with import ../../4lib/tv { inherit lib pkgs; };
 let
-  inherit (builtins) map readFile;
-  inherit (lib) concatMap listToAttrs;
-  # TODO lib should already include our stuff
-  inherit (import ../../4lib/tv { inherit lib pkgs; }) addNames git;
 
-  public-git-repos = [
-    (public "cgserver")
-    (public "crude-mail-setup")
-    (public "dot-xmonad")
-    (public "hack")
-    (public "load-env")
-    (public "make-snapshot")
-    (public "mime")
-    (public "much")
-    (public "nixos-infest")
-    (public "nixpkgs")
-    (public "painload")
-    (public "quipper")
-    (public "regfish")
-    (public' {
-      name = "stockholm";
-      desc = "take all the computers hostage, they'll love you!";
-    })
-    (public "wai-middleware-time")
-    (public "web-routes-wai-custom")
-    (public "xintmap")
-  ];
-
-  users = addNames {
-    tv = { pubkey = readFile ../../Zpubkeys/tv_wu.ssh.pub; };
-    lass = { pubkey = readFile ../../Zpubkeys/lass.ssh.pub; };
-    uriel = { pubkey = readFile ../../Zpubkeys/uriel.ssh.pub; };
-    makefu = { pubkey = readFile ../../Zpubkeys/makefu.ssh.pub; };
-  };
-
-  repos = listToAttrs (map ({ repo, ... }: { name = repo.name; value = repo; }) public-git-repos);
-
-  rules = concatMap ({ rules, ... }: rules) public-git-repos;
-
-  public' = { name, desc }:
-    let
-      x = public name;
-    in
-    x // { repo = x.repo // { inherit desc; }; };
-
-  public = repo-name:
-    rec {
-      repo = {
-        name = repo-name;
-        hooks = {
-          post-receive = git.irc-announce {
-            nick = config.networking.hostName; # TODO make this the default
-            channel = "#retiolum";
-            server = "cd.retiolum";
-          };
-        };
-        public = true;
-      };
-      rules = with git; with users; [
-        { user = tv;
-          repo = [ repo ];
-          perm = push "refs/*" [ non-fast-forward create delete merge ];
-        }
-        { user = [ lass makefu uriel ];
-          repo = [ repo ];
-          perm = fetch;
-        }
-      ];
+  out = {
+    imports = [ ../../3modules/tv/git.nix ];
+    tv.git = {
+      enable = true;
+      root-title = "public repositories at ${config.tv.identity.self.name}";
+      root-desc = "keep calm and engage";
+      inherit repos rules users;
     };
-
-in
-
-{
-  imports = [
-    ../../3modules/tv/git.nix
-  ];
-  tv.git = {
-    enable = true;
-    inherit repos rules users;
-    root-title = "public repositories at ${config.networking.hostName}";
-    root-desc = "keep calm and engage";
   };
-}
+
+  repos = public-repos;
+  rules = concatMap make-rules (attrValues repos);
+
+  public-repos = mapAttrs make-public-repo {
+    cgserver = {};
+    crude-mail-setup = {};
+    dot-xmonad = {};
+    hack = {};
+    load-env = {};
+    make-snapshot = {};
+    mime = {};
+    much = {};
+    nixos-infest = {};
+    nixpkgs = {};
+    painload = {};
+    quipper = {};
+    regfish = {};
+    stockholm = {
+      desc = "take all the computers hostage, they'll love you!";
+    };
+    wai-middleware-time = {};
+    web-routes-wai-custom = {};
+    xintmap = {};
+  };
+
+  # TODO move users to separate module
+  users = mapAttrs make-user {
+    tv = ../../Zpubkeys/tv_wu.ssh.pub;
+    lass = ../../Zpubkeys/lass.ssh.pub;
+    uriel = ../../Zpubkeys/uriel.ssh.pub;
+    makefu = ../../Zpubkeys/makefu.ssh.pub;
+  };
+
+  make-public-repo = name: { desc ? null, ... }: {
+    inherit name desc;
+    public = true;
+    hooks = {
+      post-receive = git.irc-announce {
+        # TODO make nick = config.tv.identity.self.name the default
+        nick = config.tv.identity.self.name;
+        channel = "#retiolum";
+        server = "cd.retiolum";
+      };
+    };
+  };
+
+  make-rules =
+    with git // users;
+    repo:
+      singleton {
+        user = tv;
+        repo = [ repo ];
+        perm = push "refs/*" [ non-fast-forward create delete merge ];
+      } ++
+      optional repo.public {
+        user = [ lass makefu uriel ];
+        repo = [ repo ];
+        perm = fetch;
+      };
+
+  make-user = name: pubkey-file: {
+    inherit name;
+    pubkey = readFile pubkey-file;
+  };
+
+in out