diff --git a/CMakeLists.txt b/CMakeLists.txt
index d5ff07305cb4f88bf378c626121e1ce6c06dd07d..7c21382b37a816a7220377b0d9eebe50c680a645 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -126,13 +126,14 @@ if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
         -Weverything
 
         # Disable some things because we want C++20 and don't constrol some Qt
-        # generated files...
+        # generated files... Also permit VLA
         -Wno-c++98-compat -Wno-c++98-c++11-c++14-c++17-compat-pedantic
         -Wno-extra-semi-stmt
         -Wno-redundant-parens
         -Wno-padded
         -Wno-global-constructors
         -Wno-exit-time-destructors
+        -Wno-vla-extension
     )
     target_link_libraries(Vivy PRIVATE
         -fopenmp
diff --git a/rsc/lua/lib.lua b/rsc/lua/lib.lua
index b8f400e7da65e89c369686f306a35e0159cf75f0..fb3f7efe7338c8f7be4aa9da7976dccdb82a1aac 100644
--- a/rsc/lua/lib.lua
+++ b/rsc/lua/lib.lua
@@ -25,9 +25,8 @@ function generalize(tbl) for k, v in pairs(tbl) do _G[k] = v end end
 function enum(tbl)
     local length = #tbl
     for i = 1, length do
-        local v      = tbl[i]
-        local newval = v .. "_" .. i
-        tbl[v]       = newval
+        local v = tbl[i]
+        tbl[v]  = v
     end
     setrometatable(tbl, "an enum")
     return tbl
diff --git a/src/Lib/Script/CRTPLuaScriptObject.hh b/src/Lib/Script/CRTPLuaScriptObject.hh
index 1e6f359310f34621242b0ceb8fa3bcb11d5c3105..9d189783a16d21334ca3f57d41ce74a0fc5d110e 100644
--- a/src/Lib/Script/CRTPLuaScriptObject.hh
+++ b/src/Lib/Script/CRTPLuaScriptObject.hh
@@ -33,6 +33,18 @@ namespace Vivy::Script
     }                                                                    \
     ~theClassName() noexcept {}
 
+// The type of the thing that a job iterate over
+enum class JobIteratorType { Line = 1, Syllabe = 2 };
+static inline JobIteratorType
+getJobIteratorTypeFromString(const std::string_view it) noexcept
+{
+    if (it == "LINE")
+        return JobIteratorType::Line;
+    else if (it == "SYLLABE")
+        return JobIteratorType::Syllabe;
+    return static_cast<JobIteratorType>(0); // Invalid!
+}
+
 // CRTP to expose objects to Lua
 template <class Object> class CRTPLuaScriptObject {
 protected:
@@ -286,6 +298,8 @@ script_class (ModuleDeclaration) {
     std::vector<const ModuleDeclaration *> importedModules{};
 
     bool validateModule(lua_State *const) const noexcept;
+    int exportFunction(lua_State *const, const std::string_view) noexcept;
+    int exportJob(lua_State *const, const std::string_view, const std::string_view) noexcept;
 
 public:
     std::string moduleName{};
diff --git a/src/Lib/Script/CRTPLuaScriptObject/ModuleDeclaration.cc b/src/Lib/Script/CRTPLuaScriptObject/ModuleDeclaration.cc
index 04f76add3c58d776345408fc3b1632a3d0400a87..ba0a4b32526fd89552bce24580a18fa4205ec56d 100644
--- a/src/Lib/Script/CRTPLuaScriptObject/ModuleDeclaration.cc
+++ b/src/Lib/Script/CRTPLuaScriptObject/ModuleDeclaration.cc
@@ -2,6 +2,7 @@
 #include "lua.hpp"
 #include <QFileInfo>
 #include <QString>
+#include <cstring>
 
 using namespace Vivy::Script;
 
@@ -40,7 +41,8 @@ ModuleDeclaration::importMethod(lua_State *const L) noexcept
         lua_gettable(L, 2);    // Stack is { top: str, module, str, table, self }
         const std::string_view func         = CHECK_STRING_VIEW(L, 5);
         FunctionDeclaration *const function = context->getFunction(mod, func);
-        function->pushLuaFunction(L);
+        if (function)
+            function->pushLuaFunction(L);
         // Stack is { top: nil | function, FunctionDeclaration, str, module, str, table, self }
     }
 
@@ -48,14 +50,58 @@ ModuleDeclaration::importMethod(lua_State *const L) noexcept
     return 1;
 }
 
+#include <iostream>
+
 int
 ModuleDeclaration::exportMethod(lua_State *const L) noexcept
 {
-    auto *const self              = CHECK(L, 1);
-    auto *const context           = LuaContext::getContext(L);
-    const std::string_view object = CHECK_STRING_VIEW(L, 2);
-    err(context) << "Vivy:export: Not implemented\n";
-    return 0;
+    ModuleDeclaration *const self = CHECK(L, 1);
+    luaL_checktype(L, 2, LUA_TTABLE);
+
+    // Stack will be { top: string, table, self }
+    lua_pushinteger(L, 1);
+    lua_gettable(L, 2);
+    const std::string_view objectName = CHECK_STRING_VIEW(L, -1);
+
+    const lua_Unsigned len = lua_rawlen(L, 2);
+    if (len == 2)
+        return self->exportFunction(L, objectName);
+
+    else if (len == 3) {
+        // Stack will be { top: int, string, table, self }
+        lua_pushinteger(L, 2);
+        lua_gettable(L, 2);
+        const std::string_view jobItTypeStr = CHECK_STRING_VIEW(L, -1);
+        return self->exportJob(L, objectName, jobItTypeStr);
+    }
+
+    LUA_RETURN_NOTHING(L);
+}
+
+int
+ModuleDeclaration::exportFunction(lua_State *const L, const std::string_view name) noexcept
+{
+    auto *const context = LuaContext::getContext(L);
+    out(context) << "Export function " << moduleName << "::" << name << '\n';
+    LUA_RETURN_NOTHING(L);
+}
+
+int
+ModuleDeclaration::exportJob(lua_State *const L, const std::string_view name,
+                             const std::string_view itTypeStr) noexcept
+{
+    auto *const context             = LuaContext::getContext(L);
+    const JobIteratorType jobItType = getJobIteratorTypeFromString(itTypeStr);
+    if (jobItType != JobIteratorType::Line && jobItType != JobIteratorType::Syllabe) {
+        char str[itTypeStr.length() + 1];
+        std::memset(str, 0, sizeof(str));
+        std::strncpy(str, itTypeStr.data(), sizeof(str));
+        luaL_error(L, "The iteration type must be LINE or SYLLABE, got %s", str);
+    }
+
+    out(context) << "Export job " << moduleName << "::" << name << "{" << itTypeStr << "}\n";
+
+    LUA_RETURN_NOTHING(L);
 }
 
 int
@@ -169,6 +215,9 @@ ModuleDeclaration::pushToRuntime(lua_State *const L) noexcept
     else
         context->setFailed("Module " + self->moduleName + " is invalid");
 
+    // TODO: Import needed modules here!
+    const std::string_view importNeededModulesHere = "Import needed modules here!";
+
     LUA_RETURN_NOTHING(L);
 }
 
diff --git a/utils/lua/sample-spec.module b/utils/lua/sample-spec.module
index 74ad9edba718efd9d9f72b9da859446df7d856d8..b007d97a926900929530b3043f19f42f83e31958 100644
--- a/utils/lua/sample-spec.module
+++ b/utils/lua/sample-spec.module
@@ -37,7 +37,7 @@ module:export { "printFoo", function () prettyPrint ("Bar") end }
 module:export { "retime_lines", LINE, function (opt, line)
     line.start  = line.start + opt.preTime
     line.finish = line.start + opt.postTime
-    if line.start <= 0 then line.start = 0 end
+    if line.start  <= Vivy:start()  then line.start  = Vivy:start()  end
     if line.finish >= Vivy:finish() then line.finish = Vivy:finish() end
     return line
 end }