diff --git a/default.nix b/default.nix
index b7024e3be9ab5a38ee842b67a4fa0d39d72ebb53..bc050e091e25ceb6564716d7fb43937bb59f570b 100644
--- a/default.nix
+++ b/default.nix
@@ -4,8 +4,22 @@ with pkgs;
 let
   firmware = subdir:
     callPackage ./nix/firmware.nix { inherit subdir; };
+  openocd = callPackage ./nix/openocd.nix { };
 in
 {
+  openocd = stdenv.mkDerivation {
+    name = "openocd-card10";
+    src = ./openocd;
+    phases = [ "unpackPhase" "installPhase" ];
+    buildInputs = [ openocd makeWrapper ];
+    installPhase = ''
+      mkdir -p $out/bin $out/share
+      cp -ar . $out/share/openocd
+      makeWrapper ${openocd}/bin/openocd $out/bin/openocd-card10 \
+        --add-flags "-f $out/share/openocd/scripts/interface/cmsis-dap.cfg" \
+        --add-flags "-f $out/share/openocd/scripts/target/max32665.cfg"
+    '';
+  };
   ble = firmware "ble";
   bmatest = firmware "bmatest";
   bmetest = firmware "bmetest";
diff --git a/nix/openocd.nix b/nix/openocd.nix
new file mode 100644
index 0000000000000000000000000000000000000000..769dcc35026a89f899fbc9692215957ea0069def
--- /dev/null
+++ b/nix/openocd.nix
@@ -0,0 +1,16 @@
+{ openocd, fetchFromGitHub, autoreconfHook, git, which }:
+openocd.overrideAttrs (oa: {
+  src = fetchFromGitHub {
+    owner = "maximmbed";
+    repo = "openocd";
+    rev = "e71ac88c9dbfa4ee1405d7a86376119dcc887ed1";
+    sha256 = "18yc1wyclmjxqg6jilfcm60hi01pgqc4dilsmksqbhg23m6x4ycw";
+    fetchSubmodules = true;
+  };
+  nativeBuildInputs = oa.nativeBuildInputs ++ [
+    autoreconfHook
+    git
+    which
+  ];
+  enableParallelBuilding = true;
+})