diff --git a/mercurial/interfaces/repository.py b/mercurial/interfaces/repository.py
--- a/mercurial/interfaces/repository.py
+++ b/mercurial/interfaces/repository.py
@@ -344,6 +344,7 @@ class ipeercommandexecutor(Protocol):
     outstanding requests are waited on.
     """
 
+    @abc.abstractmethod
     def callcommand(self, name, args):
         """Request that a named command be executed.
 
@@ -366,6 +367,7 @@ class ipeercommandexecutor(Protocol):
         until all command requests have been issued.
         """
 
+    @abc.abstractmethod
     def sendcommands(self):
         """Trigger submission of queued command requests.
 
@@ -376,6 +378,7 @@ class ipeercommandexecutor(Protocol):
         When called, no more new commands may be issued with this executor.
         """
 
+    @abc.abstractmethod
     def close(self):
         """Signal that this command request is finished.
 
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -258,7 +258,7 @@ moderncaps = {
 legacycaps = moderncaps.union({b'changegroupsubset'})
 
 
-class localcommandexecutor:  # (repository.ipeercommandexecutor)
+class localcommandexecutor(repository.ipeercommandexecutor):
     def __init__(self, peer):
         self._peer = peer
         self._sent = False
diff --git a/mercurial/wireprotov1peer.py b/mercurial/wireprotov1peer.py
--- a/mercurial/wireprotov1peer.py
+++ b/mercurial/wireprotov1peer.py
@@ -107,8 +107,7 @@ class unsentfuture(futures.Future):
         return self.result(timeout)
 
 
-# @interfaceutil.implementer(repository.ipeercommandexecutor)
-class peerexecutor:
+class peerexecutor(repository.ipeercommandexecutor):
     def __init__(self, peer):
         self._peer = peer
         self._sent = False