<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Caspian</title>
    <description>The latest articles on DEV Community by Caspian (@caspianrz).</description>
    <link>https://dev.to/caspianrz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4019211%2Fee001621-f65b-4e29-ab51-bd6c26ec905c.jpg</url>
      <title>DEV Community: Caspian</title>
      <link>https://dev.to/caspianrz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/caspianrz"/>
    <language>en</language>
    <item>
      <title>Lua's Hidden Startup Hook</title>
      <dc:creator>Caspian</dc:creator>
      <pubDate>Sun, 19 Jul 2026 09:50:44 +0000</pubDate>
      <link>https://dev.to/caspianrz/luas-hidden-startup-hook-4gi</link>
      <guid>https://dev.to/caspianrz/luas-hidden-startup-hook-4gi</guid>
      <description>&lt;p&gt;While reading through the Lua source code, I stumbled upon a small but interesting feature that I had never noticed before: &lt;strong&gt;&lt;code&gt;LUA_INIT&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Lua has a built-in startup initialization mechanism that allows you to execute Lua code automatically whenever the standalone interpreter starts.&lt;/p&gt;

&lt;p&gt;It is controlled through an environment variable &lt;code&gt;LUA_INIT&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;By setting this variable, you can make Lua run a piece of code before executing your actual script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running initialization code directly
&lt;/h2&gt;

&lt;p&gt;The simplest form is putting Lua code directly into &lt;code&gt;LUA_INIT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LUA_INIT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'print("Lua is starting!")'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lua myscript.lua
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lua will first execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Lua is starting!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then continue running &lt;code&gt;myscript.lua&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This can be useful for setting global variables, configuring your environment, loading helper modules, or debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loading an initialization file
&lt;/h2&gt;

&lt;p&gt;Instead of embedding code in an environment variable, you can prefix the value with &lt;code&gt;@&lt;/code&gt; and provide a filename:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LUA_INIT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'@startup.lua'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Lua will load and execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;startup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lua&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;before running your program.&lt;/p&gt;

&lt;p&gt;This is a much cleaner approach for larger initialization logic.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- startup.lua&lt;/span&gt;

&lt;span class="nb"&gt;package.path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;package.path&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="s2"&gt;";./modules/?.lua"&lt;/span&gt;

&lt;span class="n"&gt;DEBUG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Custom Lua environment loaded"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every Lua session started with that environment variable will automatically use this configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting LUA_INIT temporarily in PowerShell
&lt;/h2&gt;

&lt;p&gt;While experimenting with this feature, I also learned a useful PowerShell trick.&lt;/p&gt;

&lt;p&gt;Unlike Unix shells where you might do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;LUA_INIT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'print("hello")'&lt;/span&gt; lua script.lua
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PowerShell uses a different syntax for environment variables.&lt;/p&gt;

&lt;p&gt;You can create a temporary environment variable for a command using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;powershell&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;LUA_INIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"print('hello from init')"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lua.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;script.lua&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The variable only exists inside that PowerShell command scope and is passed to &lt;code&gt;lua.exe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is a convenient way to test &lt;code&gt;LUA_INIT&lt;/code&gt; without permanently modifying your system environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking at the source code
&lt;/h2&gt;

&lt;p&gt;While exploring the Lua standalone interpreter source (&lt;code&gt;lua.c&lt;/code&gt;), this behavior can be found in the initialization handling code.&lt;/p&gt;

&lt;p&gt;The interpreter checks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;LUA_INIT_&lt;/code&gt; with the Lua version suffix for example:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;LUA_INIT_5_5&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'print("Hello")'&lt;/span&gt; lua
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will also work.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;LUA_INIT&lt;/code&gt; as a fallback&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then it decides whether the value is code or a file.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="n"&gt;starts&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="sc"&gt;'@'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;load&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Lua&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The implementation is small, but it provides a powerful extension point.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small detail: "before anything else" is not literally everything
&lt;/h2&gt;

&lt;p&gt;The initialization code runs very early, but it is not the very first thing Lua does.&lt;/p&gt;

&lt;p&gt;Before calling the &lt;code&gt;LUA_INIT&lt;/code&gt; handler, the standalone interpreter has already:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;created the Lua state&lt;/li&gt;
&lt;li&gt;initialized the standard libraries&lt;/li&gt;
&lt;li&gt;parsed command-line arguments&lt;/li&gt;
&lt;li&gt;performed some interpreter setup&lt;/li&gt;
&lt;li&gt;started garbage collection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only after these steps does Lua execute the initialization chunk.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;LUA_INIT&lt;/code&gt; is better described as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Run custom Lua code before executing the user's script or interactive session."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;rather than:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Run code before Lua starts."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why is this useful?
&lt;/h2&gt;

&lt;p&gt;There are many practical uses:&lt;/p&gt;

&lt;h3&gt;
  
  
  Development helpers
&lt;/h3&gt;

&lt;p&gt;Automatically enable debugging:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LUA_INIT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'debug = true'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Custom environments
&lt;/h3&gt;

&lt;p&gt;Load frequently used modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"my_helpers"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Local tooling
&lt;/h3&gt;

&lt;p&gt;Create project-specific Lua startup behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LUA_INIT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'@.lua_startup.lua'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Experimenting with Lua internals
&lt;/h3&gt;

&lt;p&gt;For people reading Lua's source code, &lt;code&gt;LUA_INIT&lt;/code&gt; is also a nice example of how the standalone interpreter connects the operating system environment with the Lua runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;LUA_INIT&lt;/code&gt; is a tiny feature hidden inside Lua's interpreter, but it demonstrates one of Lua's strengths: the runtime stays simple while still providing powerful extension points.&lt;/p&gt;

&lt;p&gt;Sometimes reading source code reveals features that are not obvious from everyday usage — and &lt;code&gt;LUA_INIT&lt;/code&gt; is one of those small gems.&lt;/p&gt;

</description>
      <category>lua</category>
    </item>
  </channel>
</rss>
