diff --git a/src/libutil/args.cc b/src/libutil/args.cc
index f829415d1..afeaf4cea 100644
--- a/src/libutil/args.cc
+++ b/src/libutil/args.cc
@@ -217,10 +217,15 @@ MultiCommand::MultiCommand(const Commands & commands)
 {
     expectedArgs.push_back(ExpectedArg{"command", 1, true, [=](std::vector<std::string> ss) {
         assert(!command);
-        auto i = commands.find(ss[0]);
+        auto cmd = ss[0];
+        if (auto alias = get(deprecatedAliases, cmd)) {
+            warn("'%s' is a deprecated alias for '%s'", cmd, *alias);
+            cmd = *alias;
+        }
+        auto i = commands.find(cmd);
         if (i == commands.end())
-            throw UsageError("'%s' is not a recognised command", ss[0]);
-        command = {ss[0], i->second()};
+            throw UsageError("'%s' is not a recognised command", cmd);
+        command = {cmd, i->second()};
     }});
 
     categories[Command::catDefault] = "Available commands";
diff --git a/src/libutil/args.hh b/src/libutil/args.hh
index 1932e6a8a..154d1e6aa 100644
--- a/src/libutil/args.hh
+++ b/src/libutil/args.hh
@@ -234,6 +234,8 @@ public:
 
     std::map<Command::Category, std::string> categories;
 
+    std::map<std::string, std::string> deprecatedAliases;
+
     // Selected command, if any.
     std::optional<std::pair<std::string, ref<Command>>> command;
 
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index a63ee05b3..4b117f9bc 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -459,8 +459,7 @@ string base64Encode(const string & s);
 string base64Decode(const string & s);
 
 
-/* Get a value for the specified key from an associate container, or a
-   default value if the key doesn't exist. */
+/* Get a value for the specified key from an associate container. */
 template <class T>
 std::optional<typename T::mapped_type> get(const T & map, const typename T::key_type & key)
 {
diff --git a/src/nix/main.cc b/src/nix/main.cc
index ef301580a..1120ba5ef 100644
--- a/src/nix/main.cc
+++ b/src/nix/main.cc
@@ -110,6 +110,8 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
             .description = "consider all previously downloaded files out-of-date",
             .handler = {[&]() { refresh = true; }},
         });
+
+        deprecatedAliases.insert({"dev-shell", "develop"});
     }
 
     void printFlags(std::ostream & out) override