{"article":{"slug":"executable-scripts-with-dependencies","title":"Executable Scripts with Dependencies","subtitle":null,"summary":"The Unix shell is great for supporting executable scripts via the shebang header, but I’ve always found scripting languages limiting, due to the inability to specify dependencies (other than the standard library). This has always been Python’s appeal with its “batteries included”, but I dislike Python, and its standard library isn’t enough either. And then, Scala CLI has spoiled me, now being my favorite way to build scripts.","content_type":"tutorial","language":"en","canonical_url":"https://alexn.org/blog/2026/09/17/executable-scripts-with-dependencies/","author":{"name":"Alexandru Nedelcu","url":null,"person_slug":null,"person_url":null},"authored_by":"human","publisher":{"name":"Alexandru Nedelcu","url":"https://alexn.org","listing_slug":null,"listing":null},"topics":[{"name":"Programming","slug":"programming","url":"https://listedarticles.com/topics/programming"},{"name":"Developer Tools","slug":"developer-tools","url":"https://listedarticles.com/topics/developer-tools"},{"name":"Software Engineering","slug":"software-engineering","url":"https://listedarticles.com/topics/software-engineering"},{"name":"Open Source","slug":"open-source","url":"https://listedarticles.com/topics/open-source"}],"about_listings":[],"cover_image_url":null,"license":"all-rights-reserved","word_count":993,"reading_minutes":4,"published_at":"2026-09-17T00:00:00.000Z","added_at":"2026-10-03T09:17:26.676Z","updated_at":"2026-10-03T09:17:26.676Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":false},"profile_url":"https://listedarticles.com/articles/executable-scripts-with-dependencies","markdown_url":"https://listedarticles.com/articles/executable-scripts-with-dependencies.md","example":false,"citation":"Alexandru Nedelcu, Alexandru Nedelcu. \"Executable Scripts with Dependencies.\" 17 Sept 2026. https://alexn.org/blog/2026/09/17/executable-scripts-with-dependencies/ (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://alexn.org/blog/2026/09/17/executable-scripts-with-dependencies/"},"body_markdown":"The Unix shell is great for supporting executable scripts via the shebang header, but I’ve always found scripting languages limiting, due to the inability to specify dependencies (other than the standard library). This has always been Python’s appeal with its “batteries included”, but I dislike Python, and its standard library isn’t enough either. And then, Scala CLI has spoiled me, now being my favorite way to build scripts.\n\nSo without further ado, here’s how to build executable scripts that have dependencies in some of my favorite languages…\n\n## C# #\n\n### Prerequisites #\n\n.NET 10 SDK or newer needs to be installed, since file-based apps (running a single `.cs` file directly, without a project) were introduced in .NET 10.\n\n```\n# For Homebrew (macOS)\nbrew install dotnet\n```\n### hello.cs #\n\n```\n#!/usr/bin/env -S dotnet run\n#:package System.CommandLine@2.0.12\nusing System.CommandLine;\nvar nameArgument = new Argument<string>(\"name\");\nvar rootCommand = new RootCommand(\"Say hello\");\nrootCommand.Add(nameArgument);\nrootCommand.SetAction(parseResult =>\n{\n    var name = parseResult.GetValue(nameArgument);\n    Console.WriteLine($\"Hello, {name}!\");\n});\nreturn await rootCommand.Parse(args).InvokeAsync();\n```\nSave this as `hello.cs` and then:\n\n```\n$ chmod +x ./hello.cs\n$ ./hello.cs\n```\n## Clojure #\n\n### Prerequisites #\n\nNeeds Babashka installed.\n\n```\n# With Homebrew (macOS)\nbrew install borkdude/brew/babashka\n```\n### hello.clj #\n\n```\n#!/usr/bin/env bb\n(require '[babashka.deps :as deps])\n(deps/add-deps '{:deps {org.babashka/cli {:mvn/version \"0.12.91\"}}})\n(require '[babashka.cli :as cli])\n(defn hello [{:keys [name]}]\n  (println (str \"Hello, \" name \"!\")))\n(cli/dispatch\n  [{:exec-fn hello\n    :args->opts [:name]\n    :spec {:name {:positional true :require true :desc \"Name to greet\"}}}]\n  *command-line-args*\n  {:prog \"hello\" :help true})\n```\nSave this as `hello.clj` and then:\n\n```\n$ chmod +x ./hello.clj\n$ ./hello.clj\n```\n## FSharp #\n\n### Prerequisites #\n\n.NET Core needs to be installed.\n\n```\n# For Homebrew (macOS)\nbrew install dotnet\n```\n### hello.fsx #\n\n```\n#!/usr/bin/env -S dotnet fsi\n#r \"nuget: Argu, 6.2.5\"\nopen Argu\ntype Arguments =\n    | [<MainCommand; ExactlyOnce>] Name of string\n    interface IArgParserTemplate with\n        member this.Usage =\n            match this with\n            | Name _ -> \"Name to greet\"\nlet parser =\n    ArgumentParser.Create<Arguments>(\n        programName = \"hello\",\n        helpTextMessage = \"Say hello\",\n        errorHandler = ProcessExiter()\n    )\nlet argv =\n    fsi.CommandLineArgs |> Array.tail\nlet args =\n    parser.ParseCommandLine(inputs = argv)\nlet name =\n    args.GetResult(<@ Name @>)\nprintfn \"Hello, %s!\" name\n```\nSave this as `hello.fsx` and then:\n\n```\n$ chmod +x ./hello.fsx\n$ ./hello.fsx\n```\n## Haskell #\n\n### Prerequisites #\n\nHaskell needs `cabal`.\n\n```\n# With Homebrew (macOS)\nbrew install ghc cabal-install\n# Required afterwards :-(\ncabal update\n```\nAlso see GHCup as alternative to Homebrew.\n\n### hello.hs #\n\n```\n#!/usr/bin/env cabal\n{- cabal:\nbuild-depends:\n    base >= 4.18 && < 5,\n    optparse-applicative == 0.19.0.0\n-}\nimport Options.Applicative\ndata Options = Options\n  { name :: String\n  }\noptions :: Parser Options\noptions =\n  Options\n    <$> strArgument\n      ( metavar \"NAME\"\n     <> help \"Name to greet\"\n      )\nmain :: IO ()\nmain = do\n  opts <-\n    execParser $\n      info\n        (options <**> helper)\n        (fullDesc <> progDesc \"Say hello\")\n  putStrLn $ \"Hello, \" <> name opts <> \"!\"\n```\nSave this as `hello.hs` and then:\n\n```\n$ chmod +x ./hello.hs\n$ ./hello.hs\n```\n## Java #\n\n### Prerequisites #\n\nYou need JBang installed.\n\n```\n# With Homebrew (macOS)\nbrew install jbang\n# With SDKMAN! (https://sdkman.io/)\nsdk install jbang\n```\n### hello.java #\n\n```\n///usr/bin/env jbang \"$0\" \"$@\" ; exit $?\n//JAVA 21+\n//DEPS info.picocli:picocli:4.7.7\nimport picocli.CommandLine;\nimport picocli.CommandLine.Parameters;\nclass hello implements Runnable {\n    @Parameters(index = \"0\", defaultValue = \"world\")\n    String name;\n    public static void main(String[] args) {\n        System.exit(new CommandLine(new hello()).execute(args));\n    }\n    @Override\n    public void run() {\n        System.out.println(\"Hello, \" + name + \"!\");\n    }\n}\n```\nSave that as `hello.java` and then:\n\n```\n$ chmod +x ./hello.java\n$ ./hello.java\n```\n## Kotlin (via JBang) #\n\n### Prerequisites #\n\nYou need JBang installed.\n\n```\n# With Homebrew (macOS)\nbrew install jbang\n# With SDKMAN! (https://sdkman.io/)\nsdk install jbang\n```\n### hello.kt #\n\n```\n///usr/bin/env jbang \"$0\" \"$@\" ; exit $?\n//KOTLIN 2.4.20\n//DEPS com.github.ajalt.clikt:clikt-jvm:5.1.0\nimport com.github.ajalt.clikt.core.CliktCommand\nimport com.github.ajalt.clikt.core.main\nimport com.github.ajalt.clikt.parameters.arguments.argument\nclass Hello : CliktCommand() {\n    private val name by argument()\n    override fun run() {\n        echo(\"Hello, $name!\")\n    }\n}\nfun main(args: Array<String>) {\n    Hello().main(args)\n}\n```\nSave that as `hello.kt` and then:\n\n```\n$ chmod +x ./hello.kt\n$ ./hello.kt\n```\n## Kotlin (via experimental scripting support) #\n\nKotlin has experimental support for custom scripting.\n\n### Prerequisites #\n\nKotlin must be installed in your path.\n\n```\n# With Homebrew (macOS)\nbrew install kotlin\n# With SDKMAN! (https://sdkman.io/)\nsdk install kotlin\n```\n### hello.main.kts #\n\n```\n#!/usr/bin/env kotlin\n@file:DependsOn(\"com.github.ajalt.clikt:clikt-jvm:5.1.0\")\nimport com.github.ajalt.clikt.core.CliktCommand\nimport com.github.ajalt.clikt.core.main\nimport com.github.ajalt.clikt.parameters.arguments.argument\nclass Hello : CliktCommand() {\n    private val name by argument()\n    override fun run() {\n        echo(\"Hello, $name!\")\n    }\n}\nHello().main(args)\n```\nFile needs to be saved as `*.main.kts` specifically, or it won’t work, so save it as `hello.main.kts`.\n\n```\n$ chmod +x ./hello.main.kts\n$ ./hello.main.kts\n```\n## Python #\n\n### Prerequisites #\n\nPython needs uv installed.\n\n```\n# With Homebrew (macOS)\nbrew install uv\n```\n### hello.py #\n\n```\n#!/usr/bin/env -S uv run --script\n# /// script\n# requires-python = \">=3.10\"\n# dependencies = [\n#   \"typer==0.27.2\",\n# ]\n# ///\nfrom typing import Annotated\nimport typer\ndef main(\n    name: Annotated[str, typer.Argument(help=\"Name to greet\")],\n) -> None:\n    print(f\"Hello, {name}!\")\nif __name__ == \"__main__\":\n    typer.run(main)\n```\nSave this as `hello.py` and then:\n\n```\n$ chmod +x ./hello.py\n$ ./hello.py\n```\n## Ruby #\n\n### Prerequisites #\n\nNeeds Ruby and Bundler installed (Bundler ships with Ruby by default).\n\n```\n# With Homebrew (macOS)\nbrew install ruby\n```\n### hello.rb #\n\n```\n#!/usr/bin/env ruby\nrequire \"bundler/inline\"\ngemfile do\n  source \"https://rubygems.org\"\n  gem \"optimist\"\nend\nopts = Optimist.options do\n  banner \"Say hello\"\nend\nname = ARGV[0]\nOptimist.die \"name is required\" if name.nil?\nputs \"Hello, #{name}!\"\n```\nSave this as `hello.rb` and then:\n\n```\n$ chmod +x ./hello.rb\n$ ./hello.rb\n```\n## Rust #\n\n### Prerequisites #\n\nNeeds `cargo` installed via rustup.\n\n```\n# With Homebrew:\nbrew install rustup\n```\n### hello.rs #\n\n```\n#!/usr/bin/env -S cargo +nightly -q -Zscript\n---cargo\n[package]\nedition = \"2024\"\n[dependencies]\nanyhow = \"1\"\nclap = { version = \"4\", features = [\"derive\"] }\n---\nuse anyhow::Result;\nuse clap::Parser;\n#[derive(Parser)]\nstruct Args {\n    name: String,\n}\nfn main() -> Result<()> {\n    let args = Args::parse();\n    println!(\"Hello, {}!\", args.name);\n    Ok(())\n}\n```\nCan be saved as `hello.rs` and executed with:\n\n```\n$ chmod +x ./hello.rs\n$ ./hello.rs\n```\nWhen first executing this script, it takes a while for Cargo to download dependencies and compile the script, but afterwards it’s instant.\n\n## Scala #\n\n### Prerequisites #\n\nWhen you install the Scala runner, it actually uses Scala CLI since 3.5.0.\n\n```\n# With Homebrew:\nbrew install scala\n# With SDKMAN! (https://sdkman.io/)\nsdk install scala\n```\n### hello.scala #\n\n```\n#!/usr/bin/env -S scala shebang\n//> using scala \"3.9.0\"\n//> using dep \"com.monovore::decline:2.5.0\"\nimport com.monovore.decline.*\nobject Hello extends CommandApp(\n  name = \"hello\",\n  header = \"Say hello\",\n  main =\n    Opts\n      .argument[String](\"name\")\n      .map { name =>\n        println(s\"Hello, $name!\")\n      }\n)\n```\nSave this as `hello.scala` and then:\n\n```\n$ chmod +x ./hello.scala\n$ ./hello.scala\n```\n## TypeScript #\n\n### Prerequisites #\n\nWe need deno installed.\n\n```\n# With Homebrew (macOS)\nbrew install deno\n```\n### hello.ts #\n\n```\n#!/usr/bin/env -S deno run --quiet\nimport { Command } from \"jsr:@cliffy/command@1.2.1\";\nawait new Command()\n  .name(\"hello\")\n  .description(\"Say hello\")\n  .arguments(\"<name:string>\")\n  .action((_options, name: string) => {\n    console.log(`Hello, ${name}!`);\n  })\n  .parse(Deno.args);\n```\nSave this as `hello.ts` and then:\n\n```\n$ chmod +x ./hello.ts\n$ ./hello.ts\n```","body_html":"<p>The Unix shell is great for supporting executable scripts via the shebang header, but I’ve always found scripting languages limiting, due to the inability to specify dependencies (other than the standard library). This has always been Python’s appeal with its “batteries included”, but I dislike Python, and its standard library isn’t enough either. And then, Scala CLI has spoiled me, now being my favorite way to build scripts.</p>\n<p>So without further ado, here’s how to build executable scripts that have dependencies in some of my favorite languages…</p>\n<h2 id=\"c\">C#</h2>\n<h3 id=\"prerequisites\">Prerequisites</h3>\n<p>.NET 10 SDK or newer needs to be installed, since file-based apps (running a single <code>.cs</code> file directly, without a project) were introduced in .NET 10.</p>\n<pre><code># For Homebrew (macOS)\nbrew install dotnet</code></pre>\n<h3 id=\"hello-cs\">hello.cs</h3>\n<pre><code>#!/usr/bin/env -S dotnet run\n#:package System.CommandLine@2.0.12\nusing System.CommandLine;\nvar nameArgument = new Argument&lt;string&gt;(&quot;name&quot;);\nvar rootCommand = new RootCommand(&quot;Say hello&quot;);\nrootCommand.Add(nameArgument);\nrootCommand.SetAction(parseResult =&gt;\n{\n    var name = parseResult.GetValue(nameArgument);\n    Console.WriteLine($&quot;Hello, {name}!&quot;);\n});\nreturn await rootCommand.Parse(args).InvokeAsync();</code></pre>\n<p>Save this as <code>hello.cs</code> and then:</p>\n<pre><code>$ chmod +x ./hello.cs\n$ ./hello.cs</code></pre>\n<h2 id=\"clojure\">Clojure</h2>\n<h3 id=\"prerequisites-2\">Prerequisites</h3>\n<p>Needs Babashka installed.</p>\n<pre><code># With Homebrew (macOS)\nbrew install borkdude/brew/babashka</code></pre>\n<h3 id=\"hello-clj\">hello.clj</h3>\n<pre><code>#!/usr/bin/env bb\n(require &#39;[babashka.deps :as deps])\n(deps/add-deps &#39;{:deps {org.babashka/cli {:mvn/version &quot;0.12.91&quot;}}})\n(require &#39;[babashka.cli :as cli])\n(defn hello [{:keys [name]}]\n  (println (str &quot;Hello, &quot; name &quot;!&quot;)))\n(cli/dispatch\n  [{:exec-fn hello\n    :args-&gt;opts [:name]\n    :spec {:name {:positional true :require true :desc &quot;Name to greet&quot;}}}]\n  *command-line-args*\n  {:prog &quot;hello&quot; :help true})</code></pre>\n<p>Save this as <code>hello.clj</code> and then:</p>\n<pre><code>$ chmod +x ./hello.clj\n$ ./hello.clj</code></pre>\n<h2 id=\"fsharp\">FSharp</h2>\n<h3 id=\"prerequisites-3\">Prerequisites</h3>\n<p>.NET Core needs to be installed.</p>\n<pre><code># For Homebrew (macOS)\nbrew install dotnet</code></pre>\n<h3 id=\"hello-fsx\">hello.fsx</h3>\n<pre><code>#!/usr/bin/env -S dotnet fsi\n#r &quot;nuget: Argu, 6.2.5&quot;\nopen Argu\ntype Arguments =\n    | [&lt;MainCommand; ExactlyOnce&gt;] Name of string\n    interface IArgParserTemplate with\n        member this.Usage =\n            match this with\n            | Name _ -&gt; &quot;Name to greet&quot;\nlet parser =\n    ArgumentParser.Create&lt;Arguments&gt;(\n        programName = &quot;hello&quot;,\n        helpTextMessage = &quot;Say hello&quot;,\n        errorHandler = ProcessExiter()\n    )\nlet argv =\n    fsi.CommandLineArgs |&gt; Array.tail\nlet args =\n    parser.ParseCommandLine(inputs = argv)\nlet name =\n    args.GetResult(&lt;@ Name @&gt;)\nprintfn &quot;Hello, %s!&quot; name</code></pre>\n<p>Save this as <code>hello.fsx</code> and then:</p>\n<pre><code>$ chmod +x ./hello.fsx\n$ ./hello.fsx</code></pre>\n<h2 id=\"haskell\">Haskell</h2>\n<h3 id=\"prerequisites-4\">Prerequisites</h3>\n<p>Haskell needs <code>cabal</code>.</p>\n<pre><code># With Homebrew (macOS)\nbrew install ghc cabal-install\n# Required afterwards :-(\ncabal update</code></pre>\n<p>Also see GHCup as alternative to Homebrew.</p>\n<h3 id=\"hello-hs\">hello.hs</h3>\n<pre><code>#!/usr/bin/env cabal\n{- cabal:\nbuild-depends:\n    base &gt;= 4.18 &amp;&amp; &lt; 5,\n    optparse-applicative == 0.19.0.0\n-}\nimport Options.Applicative\ndata Options = Options\n  { name :: String\n  }\noptions :: Parser Options\noptions =\n  Options\n    &lt;$&gt; strArgument\n      ( metavar &quot;NAME&quot;\n     &lt;&gt; help &quot;Name to greet&quot;\n      )\nmain :: IO ()\nmain = do\n  opts &lt;-\n    execParser $\n      info\n        (options &lt;**&gt; helper)\n        (fullDesc &lt;&gt; progDesc &quot;Say hello&quot;)\n  putStrLn $ &quot;Hello, &quot; &lt;&gt; name opts &lt;&gt; &quot;!&quot;</code></pre>\n<p>Save this as <code>hello.hs</code> and then:</p>\n<pre><code>$ chmod +x ./hello.hs\n$ ./hello.hs</code></pre>\n<h2 id=\"java\">Java</h2>\n<h3 id=\"prerequisites-5\">Prerequisites</h3>\n<p>You need JBang installed.</p>\n<pre><code># With Homebrew (macOS)\nbrew install jbang\n# With SDKMAN! (https://sdkman.io/)\nsdk install jbang</code></pre>\n<h3 id=\"hello-java\">hello.java</h3>\n<pre><code>///usr/bin/env jbang &quot;$0&quot; &quot;$@&quot; ; exit $?\n//JAVA 21+\n//DEPS info.picocli:picocli:4.7.7\nimport picocli.CommandLine;\nimport picocli.CommandLine.Parameters;\nclass hello implements Runnable {\n    @Parameters(index = &quot;0&quot;, defaultValue = &quot;world&quot;)\n    String name;\n    public static void main(String[] args) {\n        System.exit(new CommandLine(new hello()).execute(args));\n    }\n    @Override\n    public void run() {\n        System.out.println(&quot;Hello, &quot; + name + &quot;!&quot;);\n    }\n}</code></pre>\n<p>Save that as <code>hello.java</code> and then:</p>\n<pre><code>$ chmod +x ./hello.java\n$ ./hello.java</code></pre>\n<h2 id=\"kotlin-via-jbang\">Kotlin (via JBang)</h2>\n<h3 id=\"prerequisites-6\">Prerequisites</h3>\n<p>You need JBang installed.</p>\n<pre><code># With Homebrew (macOS)\nbrew install jbang\n# With SDKMAN! (https://sdkman.io/)\nsdk install jbang</code></pre>\n<h3 id=\"hello-kt\">hello.kt</h3>\n<pre><code>///usr/bin/env jbang &quot;$0&quot; &quot;$@&quot; ; exit $?\n//KOTLIN 2.4.20\n//DEPS com.github.ajalt.clikt:clikt-jvm:5.1.0\nimport com.github.ajalt.clikt.core.CliktCommand\nimport com.github.ajalt.clikt.core.main\nimport com.github.ajalt.clikt.parameters.arguments.argument\nclass Hello : CliktCommand() {\n    private val name by argument()\n    override fun run() {\n        echo(&quot;Hello, $name!&quot;)\n    }\n}\nfun main(args: Array&lt;String&gt;) {\n    Hello().main(args)\n}</code></pre>\n<p>Save that as <code>hello.kt</code> and then:</p>\n<pre><code>$ chmod +x ./hello.kt\n$ ./hello.kt</code></pre>\n<h2 id=\"kotlin-via-experimental-scripting-support\">Kotlin (via experimental scripting support)</h2>\n<p>Kotlin has experimental support for custom scripting.</p>\n<h3 id=\"prerequisites-7\">Prerequisites</h3>\n<p>Kotlin must be installed in your path.</p>\n<pre><code># With Homebrew (macOS)\nbrew install kotlin\n# With SDKMAN! (https://sdkman.io/)\nsdk install kotlin</code></pre>\n<h3 id=\"hello-main-kts\">hello.main.kts</h3>\n<pre><code>#!/usr/bin/env kotlin\n@file:DependsOn(&quot;com.github.ajalt.clikt:clikt-jvm:5.1.0&quot;)\nimport com.github.ajalt.clikt.core.CliktCommand\nimport com.github.ajalt.clikt.core.main\nimport com.github.ajalt.clikt.parameters.arguments.argument\nclass Hello : CliktCommand() {\n    private val name by argument()\n    override fun run() {\n        echo(&quot;Hello, $name!&quot;)\n    }\n}\nHello().main(args)</code></pre>\n<p>File needs to be saved as <code>*.main.kts</code> specifically, or it won’t work, so save it as <code>hello.main.kts</code>.</p>\n<pre><code>$ chmod +x ./hello.main.kts\n$ ./hello.main.kts</code></pre>\n<h2 id=\"python\">Python</h2>\n<h3 id=\"prerequisites-8\">Prerequisites</h3>\n<p>Python needs uv installed.</p>\n<pre><code># With Homebrew (macOS)\nbrew install uv</code></pre>\n<h3 id=\"hello-py\">hello.py</h3>\n<pre><code>#!/usr/bin/env -S uv run --script\n# /// script\n# requires-python = &quot;&gt;=3.10&quot;\n# dependencies = [\n#   &quot;typer==0.27.2&quot;,\n# ]\n# ///\nfrom typing import Annotated\nimport typer\ndef main(\n    name: Annotated[str, typer.Argument(help=&quot;Name to greet&quot;)],\n) -&gt; None:\n    print(f&quot;Hello, {name}!&quot;)\nif __name__ == &quot;__main__&quot;:\n    typer.run(main)</code></pre>\n<p>Save this as <code>hello.py</code> and then:</p>\n<pre><code>$ chmod +x ./hello.py\n$ ./hello.py</code></pre>\n<h2 id=\"ruby\">Ruby</h2>\n<h3 id=\"prerequisites-9\">Prerequisites</h3>\n<p>Needs Ruby and Bundler installed (Bundler ships with Ruby by default).</p>\n<pre><code># With Homebrew (macOS)\nbrew install ruby</code></pre>\n<h3 id=\"hello-rb\">hello.rb</h3>\n<pre><code>#!/usr/bin/env ruby\nrequire &quot;bundler/inline&quot;\ngemfile do\n  source &quot;https://rubygems.org&quot;\n  gem &quot;optimist&quot;\nend\nopts = Optimist.options do\n  banner &quot;Say hello&quot;\nend\nname = ARGV[0]\nOptimist.die &quot;name is required&quot; if name.nil?\nputs &quot;Hello, #{name}!&quot;</code></pre>\n<p>Save this as <code>hello.rb</code> and then:</p>\n<pre><code>$ chmod +x ./hello.rb\n$ ./hello.rb</code></pre>\n<h2 id=\"rust\">Rust</h2>\n<h3 id=\"prerequisites-10\">Prerequisites</h3>\n<p>Needs <code>cargo</code> installed via rustup.</p>\n<pre><code># With Homebrew:\nbrew install rustup</code></pre>\n<h3 id=\"hello-rs\">hello.rs</h3>\n<pre><code>#!/usr/bin/env -S cargo +nightly -q -Zscript\n---cargo\n[package]\nedition = &quot;2024&quot;\n[dependencies]\nanyhow = &quot;1&quot;\nclap = { version = &quot;4&quot;, features = [&quot;derive&quot;] }\n---\nuse anyhow::Result;\nuse clap::Parser;\n#[derive(Parser)]\nstruct Args {\n    name: String,\n}\nfn main() -&gt; Result&lt;()&gt; {\n    let args = Args::parse();\n    println!(&quot;Hello, {}!&quot;, args.name);\n    Ok(())\n}</code></pre>\n<p>Can be saved as <code>hello.rs</code> and executed with:</p>\n<pre><code>$ chmod +x ./hello.rs\n$ ./hello.rs</code></pre>\n<p>When first executing this script, it takes a while for Cargo to download dependencies and compile the script, but afterwards it’s instant.</p>\n<h2 id=\"scala\">Scala</h2>\n<h3 id=\"prerequisites-11\">Prerequisites</h3>\n<p>When you install the Scala runner, it actually uses Scala CLI since 3.5.0.</p>\n<pre><code># With Homebrew:\nbrew install scala\n# With SDKMAN! (https://sdkman.io/)\nsdk install scala</code></pre>\n<h3 id=\"hello-scala\">hello.scala</h3>\n<pre><code>#!/usr/bin/env -S scala shebang\n//&gt; using scala &quot;3.9.0&quot;\n//&gt; using dep &quot;com.monovore::decline:2.5.0&quot;\nimport com.monovore.decline.*\nobject Hello extends CommandApp(\n  name = &quot;hello&quot;,\n  header = &quot;Say hello&quot;,\n  main =\n    Opts\n      .argument[String](&quot;name&quot;)\n      .map { name =&gt;\n        println(s&quot;Hello, $name!&quot;)\n      }\n)</code></pre>\n<p>Save this as <code>hello.scala</code> and then:</p>\n<pre><code>$ chmod +x ./hello.scala\n$ ./hello.scala</code></pre>\n<h2 id=\"typescript\">TypeScript</h2>\n<h3 id=\"prerequisites-12\">Prerequisites</h3>\n<p>We need deno installed.</p>\n<pre><code># With Homebrew (macOS)\nbrew install deno</code></pre>\n<h3 id=\"hello-ts\">hello.ts</h3>\n<pre><code>#!/usr/bin/env -S deno run --quiet\nimport { Command } from &quot;jsr:@cliffy/command@1.2.1&quot;;\nawait new Command()\n  .name(&quot;hello&quot;)\n  .description(&quot;Say hello&quot;)\n  .arguments(&quot;&lt;name:string&gt;&quot;)\n  .action((_options, name: string) =&gt; {\n    console.log(`Hello, ${name}!`);\n  })\n  .parse(Deno.args);</code></pre>\n<p>Save this as <code>hello.ts</code> and then:</p>\n<pre><code>$ chmod +x ./hello.ts\n$ ./hello.ts</code></pre>","headings":[{"level":2,"text":"C#","id":"c"},{"level":3,"text":"Prerequisites","id":"prerequisites"},{"level":3,"text":"hello.cs","id":"hello-cs"},{"level":2,"text":"Clojure","id":"clojure"},{"level":3,"text":"Prerequisites","id":"prerequisites-2"},{"level":3,"text":"hello.clj","id":"hello-clj"},{"level":2,"text":"FSharp","id":"fsharp"},{"level":3,"text":"Prerequisites","id":"prerequisites-3"},{"level":3,"text":"hello.fsx","id":"hello-fsx"},{"level":2,"text":"Haskell","id":"haskell"},{"level":3,"text":"Prerequisites","id":"prerequisites-4"},{"level":3,"text":"hello.hs","id":"hello-hs"},{"level":2,"text":"Java","id":"java"},{"level":3,"text":"Prerequisites","id":"prerequisites-5"},{"level":3,"text":"hello.java","id":"hello-java"},{"level":2,"text":"Kotlin (via JBang)","id":"kotlin-via-jbang"},{"level":3,"text":"Prerequisites","id":"prerequisites-6"},{"level":3,"text":"hello.kt","id":"hello-kt"},{"level":2,"text":"Kotlin (via experimental scripting support)","id":"kotlin-via-experimental-scripting-support"},{"level":3,"text":"Prerequisites","id":"prerequisites-7"},{"level":3,"text":"hello.main.kts","id":"hello-main-kts"},{"level":2,"text":"Python","id":"python"},{"level":3,"text":"Prerequisites","id":"prerequisites-8"},{"level":3,"text":"hello.py","id":"hello-py"},{"level":2,"text":"Ruby","id":"ruby"},{"level":3,"text":"Prerequisites","id":"prerequisites-9"},{"level":3,"text":"hello.rb","id":"hello-rb"},{"level":2,"text":"Rust","id":"rust"},{"level":3,"text":"Prerequisites","id":"prerequisites-10"},{"level":3,"text":"hello.rs","id":"hello-rs"},{"level":2,"text":"Scala","id":"scala"},{"level":3,"text":"Prerequisites","id":"prerequisites-11"},{"level":3,"text":"hello.scala","id":"hello-scala"},{"level":2,"text":"TypeScript","id":"typescript"},{"level":3,"text":"Prerequisites","id":"prerequisites-12"},{"level":3,"text":"hello.ts","id":"hello-ts"}]}}