diff --git a/modules/programs/zsh.nix b/modules/programs/zsh.nix
index f06d0d0b9..e595e5c20 100644
--- a/modules/programs/zsh.nix
+++ b/modules/programs/zsh.nix
@@ -188,6 +188,28 @@ let
     };
   };
 
+  historySubstringSearchModule = types.submodule {
+    options = {
+      enable = mkEnableOption "history substring search";
+      searchUpKey = mkOption {
+        type = types.str;
+        default = "^[[A";
+        description = ''
+          The key code to be used when searching up.
+          The default of <literal>^[[A</literal> corresponds to the UP key.
+        '';
+      };
+      searchDownKey = mkOption {
+        type = types.str;
+        default = "^[[B";
+        description = ''
+          The key code to be used when searching down.
+          The default of <literal>^[[B</literal> corresponds to the DOWN key.
+        '';
+      };
+    };
+  };
+
 in
 
 {
@@ -295,6 +317,12 @@ in
         description = "Enable zsh syntax highlighting";
       };
 
+      historySubstringSearch = mkOption {
+        type = historySubstringSearchModule;
+        default = {};
+        description = "Options related to zsh-history-substring-search.";
+      };
+
       history = mkOption {
         type = historyModule;
         default = {};
@@ -555,10 +583,18 @@ in
         ${dirHashesStr}
 
         ${optionalString cfg.enableSyntaxHighlighting
-          # Load zsh-syntax-highlighting last, after all custom widgets have been created
+          # Load zsh-syntax-highlighting after all custom widgets have been created
           # https://github.com/zsh-users/zsh-syntax-highlighting#faq
           "source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"
         }
+        ${optionalString (cfg.historySubstringSearch.enable or false)
+          # Load zsh-history-substring-search after zsh-syntax-highlighting
+          # https://github.com/zsh-users/zsh-history-substring-search#usage
+        ''
+          source ${pkgs.zsh-history-substring-search}/share/zsh-history-substring-search/zsh-history-substring-search.zsh
+          bindkey '${cfg.historySubstringSearch.searchUpKey}' history-substring-search-up
+          bindkey '${cfg.historySubstringSearch.searchDownKey}' history-substring-search-down
+        ''}
       '';
     }