diff --git a/src/Lib/AbstractDocument.hh b/src/Lib/AbstractDocument.hh
index 2ac849281a667e28551498e54f5731f05ab4a10a..0703f5c2a2469efc5321fb59063282cb466839bc 100644
--- a/src/Lib/AbstractDocument.hh
+++ b/src/Lib/AbstractDocument.hh
@@ -76,8 +76,9 @@ protected:
     const Uuid uuid{};
 
 public:
-    virtual void copy(const QString &) = 0;
-    virtual void save()                = 0;
+    virtual void copy(const QString &)   = 0;
+    virtual void rename(const QString &) = 0;
+    virtual void save()                  = 0;
 
     QString getName() const noexcept { return name; }
     Type getType() const noexcept { return type; }
diff --git a/src/Lib/Document/VivyDocument.cc b/src/Lib/Document/VivyDocument.cc
index 32c97625ae8ea7e800b021516d686d72e6b34354..0bc030af292f13e54b2c5d419c37551f7f2195ce 100644
--- a/src/Lib/Document/VivyDocument.cc
+++ b/src/Lib/Document/VivyDocument.cc
@@ -233,19 +233,11 @@ VivyDocument::detectDocumentType(const QFileInfo &file, Capabilities *ableType)
 void
 VivyDocument::copy(const QString &newName)
 {
-    const QString newNameWithExtension =
-        (newName.right(fileSuffix.size()) == fileSuffix) ? newName : newName + "." + fileSuffix;
-    const QFileInfo newPath(documentLocation, newNameWithExtension);
+    const QFileInfo newPath = computeFileInfo(newName);
 
     // Rename + create the disk on disk as it's a memory document
-    if (documentOptions & MemoryDocumentCreation) {
-        documentName     = newPath.baseName();
-        documentLocation = newPath.absoluteDir();
-        documentOptions  = static_cast<Options>(documentOptions & (~MemoryDocumentCreation));
-        qDebug().nospace() << "Renaming a memory file => create it on disk with { "
-                           << documentLocation << ", " << documentName << " }";
-        save();
-    }
+    if (documentOptions & MemoryDocumentCreation)
+        return saveMemoryFile(newPath);
 
     // Compute new paths, the document is really on disk initially
     else {
@@ -257,6 +249,44 @@ VivyDocument::copy(const QString &newName)
     }
 }
 
+void
+VivyDocument::rename(const QString &newName)
+{
+    const QFileInfo newPath = computeFileInfo(newName);
+
+    // Rename + create the disk on disk as it's a memory document
+    if (documentOptions & MemoryDocumentCreation)
+        return saveMemoryFile(newPath);
+
+    // Compute new paths, the document is really on disk initially
+    else {
+        qDebug() << "Renaming a real file";
+        renameWith(newPath, [=, this]() noexcept -> void {
+            documentLocation = newPath.dir();
+            documentName     = newPath.baseName();
+        });
+    }
+}
+
+QFileInfo
+VivyDocument::computeFileInfo(const QString &newName) const noexcept
+{
+    const QString newNameWithExtension =
+        (newName.right(fileSuffix.size()) == fileSuffix) ? newName : newName + "." + fileSuffix;
+    return QFileInfo(documentLocation, newNameWithExtension);
+}
+
+void
+VivyDocument::saveMemoryFile(const QFileInfo &newPath)
+{
+    documentName     = newPath.baseName();
+    documentLocation = newPath.absoluteDir();
+    documentOptions  = static_cast<Options>(documentOptions & (~MemoryDocumentCreation));
+    qDebug().nospace() << "Renaming a memory file => create it on disk with { " << documentLocation
+                       << ", " << documentName << " }";
+    save();
+}
+
 std::shared_ptr<AudioSubDocument>
 VivyDocument::getAudioSubDocument() const noexcept
 {
diff --git a/src/Lib/Document/VivyDocument.hh b/src/Lib/Document/VivyDocument.hh
index e5841422fc4356327cf6c71b1b1505bb0d6aa62d..48086b842d62a7e7187e9a5a72d5c6b7bd2552bc 100644
--- a/src/Lib/Document/VivyDocument.hh
+++ b/src/Lib/Document/VivyDocument.hh
@@ -68,6 +68,9 @@ private:
     static bool detectDocumentType(const QFileInfo &file, Capabilities *) noexcept;
 
     void addDocumentType(Capabilities) noexcept;
+    void saveMemoryFile(const QFileInfo &);
+    QFileInfo computeFileInfo(const QString &) const noexcept;
+
     QJsonDocument getSaveJsonDocumentFile() const;
     void loadSaveJsonDocumentFile(const QJsonDocument &);
 
@@ -81,6 +84,7 @@ public:
     explicit VivyDocument(const QString &name, Options opt = NoOption);
 
     void copy(const QString &) override;
+    void rename(const QString &) override;
     void save() override;
     bool loadSubDocument(const QString &) noexcept;
     bool loadSubDocument(const QString &, Capabilities) noexcept;
diff --git a/src/Lib/Script/ScriptDocument.cc b/src/Lib/Script/ScriptDocument.cc
index 89e019db7e8d4ebf2da2505e7b75834245d67d85..715451b6dd7e4b8a46b60e9c5f11bad3d2f913ef 100644
--- a/src/Lib/Script/ScriptDocument.cc
+++ b/src/Lib/Script/ScriptDocument.cc
@@ -22,6 +22,14 @@ ScriptDocument::copy(const QString &newName)
     copyWith(newPath, [=, this]() noexcept { name = newName; });
 }
 
+void
+ScriptDocument::rename(const QString &newName)
+{
+    /* Compute new paths */
+    const QFileInfo newPath(newName);
+    renameWith(newPath, [=, this]() noexcept { name = newName; });
+}
+
 void
 ScriptDocument::save()
 {
diff --git a/src/Lib/Script/ScriptDocument.hh b/src/Lib/Script/ScriptDocument.hh
index 8242e8fd9dd75f26f3a2bb632dada3877b6684f8..3799669c62b2b804c16ab65fe8f952b9cbb5eb35 100644
--- a/src/Lib/Script/ScriptDocument.hh
+++ b/src/Lib/Script/ScriptDocument.hh
@@ -16,6 +16,7 @@ public:
     explicit ScriptDocument(const QString &name);
 
     void copy(const QString &) override;
+    void rename(const QString &) override;
     void save() override;
 
     void attachTextDocument(const QTextDocument *const) noexcept;