diff --git a/toonz/sources/include/toonz/scriptengine.h b/toonz/sources/include/toonz/scriptengine.h
index 3b667b1..f25fa18 100644
--- a/toonz/sources/include/toonz/scriptengine.h
+++ b/toonz/sources/include/toonz/scriptengine.h
@@ -48,6 +48,7 @@ public:
   void evaluate(const QString &cmd);
   void interrupt();
   bool isEvaluating() const;
+  bool wait(unsigned long time = ULONG_MAX);
 
   enum OutputType {
     SimpleText,
diff --git a/toonz/sources/toonz/main.cpp b/toonz/sources/toonz/main.cpp
index 8ae73fc..3d25cdc 100644
--- a/toonz/sources/toonz/main.cpp
+++ b/toonz/sources/toonz/main.cpp
@@ -37,6 +37,8 @@
 #include "toonz/stylemanager.h"
 #include "toonz/tscenehandle.h"
 #include "toonz/txshsimplelevel.h"
+#include "toonz/tproject.h"
+#include "toonz/scriptengine.h"
 
 // TnzSound includes
 #include "tnzsound.h"
@@ -236,6 +238,18 @@ project->setUseScenePath(TProject::Extras, false);
 
 //-----------------------------------------------------------------------------
 
+static void script_output(int type, const QString &value) {
+  if ( type == ScriptEngine::ExecutionError ||
+       type == ScriptEngine::SyntaxError ||
+       type == ScriptEngine::UndefinedEvaluationResult ||
+       type == ScriptEngine::Warning )
+    std::cerr << value.toStdString() << std::endl;
+  else
+    std::cout << value.toStdString() << std::endl;
+}
+
+//-----------------------------------------------------------------------------
+
 int main(int argc, char *argv[]) {
 #ifdef Q_OS_WIN
   //  Enable standard input/output on Windows Platform for debug
@@ -248,13 +262,13 @@ int main(int argc, char *argv[]) {
 #endif
 
   // parsing arguments and qualifiers
-  TFilePath loadScenePath;
+  TFilePath loadFilePath;
   QString argumentLayoutFileName = "";
   QHash<QString, QString> argumentPathValues;
   if (argc > 1) {
     TCli::Usage usage(argv[0]);
     TCli::UsageLine usageLine;
-    TCli::FilePathArgument loadSceneArg("scenePath", "Source scene file");
+    TCli::FilePathArgument loadFileArg("filePath", "Source scene file to open or script file to run");
     TCli::StringQualifier layoutFileQual(
         "-layout filename",
         "Custom layout file to be used, it should be saved in "
@@ -288,11 +302,11 @@ int main(int argc, char *argv[]) {
       usageLine = usageLine + *systemPathQualMap[qualKey];
     }
     usage.add(usageLine);
-    usage.add(usageLine + loadSceneArg);
+    usage.add(usageLine + loadFileArg);
 
     if (!usage.parse(argc, argv)) exit(1);
 
-    loadScenePath = loadSceneArg.getValue();
+    loadFilePath = loadFileArg.getValue();
     if (layoutFileQual.isSelected())
       argumentLayoutFileName =
           QString::fromStdString(layoutFileQual.getValue());
@@ -666,13 +680,46 @@ int main(int argc, char *argv[]) {
   w.startupFloatingPanels();
 
   CommandManager::instance()->execute(T_Hand);
-  if (!loadScenePath.isEmpty()) {
+  if (!loadFilePath.isEmpty()) {
     splash.showMessage(
-        QString("Loading file '") + loadScenePath.getQString() + "'...",
+        QString("Loading file '") + loadFilePath.getQString() + "'...",
         Qt::AlignCenter, Qt::white);
 
-    loadScenePath = loadScenePath.withType("tnz");
-    if (TFileStatus(loadScenePath).doesExist()) IoCmd::loadScene(loadScenePath);
+    if (loadFilePath.getType() == "toonzscript") {
+      // load script
+      if (TFileStatus(loadFilePath).doesExist()) {
+        // find project for this script file
+        TProjectManager *pm = TProjectManager::instance();
+        TProjectP sceneProject = pm->loadSceneProject(loadFilePath);
+        if (!sceneProject) {
+          std::cerr << QObject::tr(
+                    "It is not possible to load the scene %1 because it does not "
+                    "belong to any project.")
+                    .arg(loadFilePath.getQString()).toStdString() << std::endl;
+          return 1;
+        }
+        if (sceneProject && !sceneProject->isCurrent())
+          pm->setCurrentProjectPath(sceneProject->getProjectPath());
+
+        ScriptEngine engine;
+        QObject::connect(&engine, &ScriptEngine::output, script_output);
+        QString s =
+          QString::fromStdWString(loadFilePath.getWideString())
+            .replace("\\", "\\\\")
+            .replace("\"", "\\\"");
+        QString cmd = QString("run(\"%1\")").arg(s);
+        engine.evaluate(cmd);
+        engine.wait();
+        return 0;
+      } else {
+        std::cerr << QObject::tr("Script file %1 does not exists.")
+                  .arg(loadFilePath.getQString()).toStdString() << std::endl;
+        return 1;
+      }
+    } else {
+      loadFilePath = loadFilePath.withType("tnz");
+      if (TFileStatus(loadFilePath).doesExist()) IoCmd::loadScene(loadFilePath);
+    }
   }
 
   QFont *myFont;
diff --git a/toonz/sources/toonzlib/scriptengine.cpp b/toonz/sources/toonzlib/scriptengine.cpp
index b266a9d..82dbb7f 100644
--- a/toonz/sources/toonzlib/scriptengine.cpp
+++ b/toonz/sources/toonzlib/scriptengine.cpp
@@ -256,6 +256,9 @@ void ScriptEngine::evaluate(const QString &cmd) {
   m_executor->start();
 }
 
+bool ScriptEngine::wait(unsigned long time)
+  { return !m_executor || m_executor->wait(time); }
+
 bool ScriptEngine::isEvaluating() const { return m_engine->isEvaluating(); }
 
 void ScriptEngine::interrupt() { m_engine->abortEvaluation(); }