diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 7fcd831466fc7ac46241fe1d359a9d135dac21b0..a6d8f2fe04b7a4de4bb45862dc19f4fc5d2731f9 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -3297,6 +3297,8 @@ DynamicModel::writeDynamicFile(const string &basename, bool block, bool use_dll,
         create_directories(sparsefolder / "private");
       if (block_decomposed)
         create_directories(sparsefolder / "+block");
+
+      create_directories(plusfolder / "+debug");
     }
   create_directories(model_dir / "bytecode");
 
@@ -3341,6 +3343,10 @@ DynamicModel::writeDynamicFile(const string &basename, bool block, bool use_dll,
     writeSparseModelMFiles<true>(basename);
 
   writeSetAuxiliaryVariables(basename, julia);
+
+  // Support for model debugging
+  if (!julia)
+    writeDebugModelMFiles<true>(basename);
 }
 
 void
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index aced1279eb1f2314b990272bf367761ade292d5f..8b08051338b761e0c7354a511823f72b1abe0d3f 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -391,6 +391,15 @@ protected:
   //! Writes LaTeX model file
   void writeLatexModelFile(const string &mod_basename, const string &latex_basename, ExprNodeOutputType output_type, bool write_equation_tags) const;
 
+  /* Write files for helping a user to debug their model (MATLAB/Octave,
+     sparse representation).
+     Creates a dynamic/static files which evaluates separately the LHS and RHS
+     of each equation.
+     They are not optimized for performance (hence in particular the absence of
+     a C version, or the non-reuse of temporary terms). */
+  template<bool dynamic>
+  void writeDebugModelMFiles(const string &basename) const;
+
 private:
   //! Sparse matrix of double to store the values of the static Jacobian
   /*! First index is equation number, second index is endogenous type specific ID */
@@ -2939,3 +2948,49 @@ ModelTree::writeSparseModelCFiles(const string &basename, const string &mexext,
         }
     }
 }
+
+template<bool dynamic>
+void
+ModelTree::writeDebugModelMFiles(const string &basename) const
+{
+  constexpr ExprNodeOutputType output_type {dynamic ? ExprNodeOutputType::matlabSparseDynamicModel : ExprNodeOutputType::matlabSparseStaticModel};
+
+  const filesystem::path m_dir {packageDir(basename) / "+debug"};
+  // TODO: when C++20 support is complete, mark the following strings constexpr
+  const string prefix { dynamic ? "dynamic_" : "static_" };
+  const string ss_arg { dynamic ? ", steady_state" : "" };
+
+  const filesystem::path resid_filename {m_dir / (prefix + "resid.m")};
+  ofstream output {resid_filename, ios::out | ios::binary};
+  if (!output.is_open())
+    {
+      cerr << "ERROR: Can't open file " << resid_filename.string() << " for writing" << endl;
+      exit(EXIT_FAILURE);
+    }
+
+  output << "function [lhs, rhs] = " << prefix << "resid(y, x, params" << ss_arg << ")" << endl
+         << "T = NaN(" << temporary_terms_derivatives[0].size() << ", 1);" << endl
+         << "lhs = NaN(" << equations.size() << ", 1);" << endl
+         << "rhs = NaN(" << equations.size() << ", 1);" << endl;
+  deriv_node_temp_terms_t tef_terms;
+  temporary_terms_t temporary_terms;
+  writeTemporaryTerms<output_type>(temporary_terms_derivatives[0], temporary_terms,
+                                   temporary_terms_idxs, output, tef_terms);
+  for (size_t eq {0}; eq < equations.size(); eq++)
+    {
+      output << "lhs" << LEFT_ARRAY_SUBSCRIPT(output_type)
+             << eq + ARRAY_SUBSCRIPT_OFFSET(output_type)
+             << RIGHT_ARRAY_SUBSCRIPT(output_type) << " = ";
+      equations[eq]->arg1->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs);
+      output << ";" << endl
+             << "rhs" << LEFT_ARRAY_SUBSCRIPT(output_type)
+             << eq + ARRAY_SUBSCRIPT_OFFSET(output_type)
+             << RIGHT_ARRAY_SUBSCRIPT(output_type) << " = ";
+      equations[eq]->arg2->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs);
+      output << ";" << endl;
+    }
+
+  output << "end" << endl;
+
+  output.close();
+}
diff --git a/src/StaticModel.cc b/src/StaticModel.cc
index e3adc0b3e650162054bdae14d99e937e626dd25f..192b06dcaa4a8713f2f99cbda89e04ec37754de6 100644
--- a/src/StaticModel.cc
+++ b/src/StaticModel.cc
@@ -639,6 +639,8 @@ StaticModel::writeStaticFile(const string &basename, bool block, bool use_dll, c
         create_directories(sparsefolder / "private");
       if (block_decomposed)
         create_directories(sparsefolder / "+block");
+
+      create_directories(plusfolder / "+debug");
     }
   create_directories(model_dir / "bytecode");
 
@@ -683,6 +685,10 @@ StaticModel::writeStaticFile(const string &basename, bool block, bool use_dll, c
     writeSparseModelMFiles<false>(basename);
 
   writeSetAuxiliaryVariables(basename, julia);
+
+  // Support for model debugging
+  if (!julia)
+    writeDebugModelMFiles<false>(basename);
 }
 
 bool