{"id":30503676,"url":"https://github.com/acrion/nexuslua","last_synced_at":"2025-08-25T13:39:34.507Z","repository":{"id":311146291,"uuid":"1038021647","full_name":"acrion/nexuslua","owner":"acrion","description":"The command-line interpreter for nexuslua, enabling true hardware multithreading for Lua scripts via an asynchronous agent model.","archived":false,"fork":false,"pushed_at":"2025-08-22T11:24:54.000Z","size":37,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-22T12:38:43.084Z","etag":null,"topics":["asynchronous","cli","command-line-tool","concurrency","interpreter","lua","multithreading","nexuslua","parallel-computing","runtime","scripting"],"latest_commit_sha":null,"homepage":"https://nexuslua.org","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/acrion.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"acrion","liberapay":"acrion","buy_me_a_coffee":"acrion","patreon":"acriondev"}},"created_at":"2025-08-14T13:48:10.000Z","updated_at":"2025-08-22T11:24:57.000Z","dependencies_parsed_at":"2025-08-22T12:55:11.321Z","dependency_job_id":null,"html_url":"https://github.com/acrion/nexuslua","commit_stats":null,"previous_names":["acrion/nexuslua"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/acrion/nexuslua","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acrion%2Fnexuslua","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acrion%2Fnexuslua/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acrion%2Fnexuslua/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acrion%2Fnexuslua/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/acrion","download_url":"https://codeload.github.com/acrion/nexuslua/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acrion%2Fnexuslua/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272077577,"owners_count":24869283,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-25T02:00:12.092Z","response_time":1107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asynchronous","cli","command-line-tool","concurrency","interpreter","lua","multithreading","nexuslua","parallel-computing","runtime","scripting"],"created_at":"2025-08-25T13:39:29.016Z","updated_at":"2025-08-25T13:39:34.495Z","avatar_url":"https://github.com/acrion.png","language":"C++","readme":"**True, hardware-level multithreading for Lua through an asynchronous agent model.**\n\nnexuslua is a command-line interpreter that extends the Lua programming language with a powerful concurrency model built\non agents and asynchronous messaging. While standard Lua uses coroutines for cooperative multitasking, nexuslua\nleverages real OS-level threads, allowing you to parallelize CPU-bound tasks and design complex, decoupled applications\nwith ease.\n\nThis project is the runtime executable for the [nexuslua library](https://github.com/acrion/nexuslua-library) and serves\nas a reference implementation and command-line tool for running nexuslua scripts and plugins. It is the core technology\nbehind the desktop application [acrionphoto](https://github.com/acrion/photo).\n\n\u003e **Watch the Talk:** For a deep dive into the original concepts, check out the presentation from the\n**[Lua Workshop 2022](https://www.youtube.com/watch?v=Y6wz6Qk475E)** (under the project's former name, \"acrionlua\").\n\n---\n\n## Installation\n\n### Arch User Repository (AUR)\n\nIf you are on an Arch-based Linux distribution, the easiest way to install is from the Arch User Repository (AUR).\nYou will need an AUR helper, such as `pikaur` or `yay`.\n\nUsing `pikaur`:\n```bash\npikaur -S nexuslua\n```\n\nThis will automatically download the source code, compile it, and install it on your system. The `nexuslua` executable will then be available in your `PATH`.\n\n### Build and Install from Source\n\nIf you are not on Arch Linux or want to build the latest version yourself, you can compile it from source using CMake.\n\n**Prerequisites:**\n* A C++20 compatible compiler (e.g., GCC, Clang, MSVC)\n* CMake (version 3.25 or newer)\n* Git\n\n**1. Configure and Build**\n\nFirst, configure the project. A `Release` build is highly recommended for performance. Then, compile it.\n\n```bash\n# Configure the build from the repository root\ncmake -B build -S src -DCMAKE_BUILD_TYPE=Release\n\n# Compile the project\ncmake --build build\n```\n\nThe `nexuslua` executable and the `libnexuslua.so` (or equivalent) library will be located in the `build/bin/` directory. You can run it directly from there.\n\n**2. (Optional) System-Wide Installation**\n\nTo install `nexuslua` so it's available system-wide, you can use the `install` command. It is recommended to add `-DINSTALL_GTEST=OFF` during the configuration step to prevent Google Test files from being installed as well.\n\n```bash\n# 1. Configure for installation (add -DINSTALL_GTEST=OFF for a clean install)\ncmake -B build -S src -DCMAKE_BUILD_TYPE=Release -DINSTALL_GTEST=OFF\n\n# 2. Build the project\ncmake --build build\n\n# 3. Install the files (usually requires administrator privileges)\nsudo cmake --install build\n```\n\nThis will typically install the `nexuslua` binary to `/usr/local/bin` and the library to `/usr/local/lib`.\n\n**3. (Optional) Via the all-in-one orchestrator**\n\nIf you want the full stack (including plugins \u0026 acrionphoto GUI app), you can use the umbrella repo:\n\n* [https://github.com/acrion/nexuslua-build](https://github.com/acrion/nexuslua-build)\n  Use `--profile nexuslua` to build the core engine only, or `--profile acrionphoto` for the entire application stack.\n\n---\n\n## Tutorial: From 10 Seconds to 1 Second\n\nThe best way to understand nexuslua is to see it in action. We'll take a simple, CPU-bound task—finding prime numbers in\na large range—and progressively parallelize it using nexuslua's features.\n\n### Step 1: The Baseline (Plain Lua)\n\nFirst, let's see how a standard Lua script performs. This code checks 50,000 numbers for primality in a single-threaded\nloop.\n\n**`demo1.lua`**\n\n```lua\n#!/usr/bin/env nexuslua\n\nlocal nCheckedPrimes = 0\nlocal count = 0\nlocal startTime = time()\n\nfunction IsPrime(number)\n    local q = math.sqrt(number)\n    local found = true\n    for k = 3, q, 2 do\n        if number % k == 0 then\n            found = false\n            break\n        end\n    end\n    return found\nend\n\nlocal n1 = 10000000001\nlocal n2 = 10000100001\n\nprint(\"Checking prime numbers between \", n1, \" and \", n2)\n\nfor i = n1, n2, 2 do\n    if IsPrime(i) then\n        count = count + 1\n    end\n    nCheckedPrimes = nCheckedPrimes + 1\nend\n\nlocal endTime = time()\nprint(\"Checked \", nCheckedPrimes, \" numbers in \", (endTime - startTime) / 1.0e8, \" seconds, found \", count, \" prime\")\n```\n\n**Execution:**\n\n```sh\n$ nexuslua demo1.lua\nChecked 50001 numbers in 10.03 seconds, found 4306 prime\n```\n\nAs expected, it's slow. The entire calculation runs on a single core.\n\n### Step 2: Introducing Asynchronous Messages\n\nNow, let's introduce nexuslua's messaging. We'll convert `IsPrime` into a message handler. The main script will `send` a\nmessage for each number to be checked.\n\n**`demo2.lua`**\n\n```lua\n#!/usr/bin/env nexuslua\n\nlocal nRequests = 0\nlocal nCheckedPrimes = 0\nlocal count = 0\nlocal startTime = time()\n\nfunction IsPrime(parameters)\n    -- ... (same implementation as before) ...\n    return { isPrime = found }\nend\n\nfunction CountPrime(parameters)\n    nCheckedPrimes = nCheckedPrimes + 1\n    if parameters.isPrime then\n        count = count + 1\n    end\n    if nCheckedPrimes == nRequests then\n        local endTime = time()\n        print(\"Checked \", nCheckedPrimes, \" numbers in \", (endTime - startTime) / 1.0e8, \" seconds, found \", count, \" prime\")\n    end\nend\n\naddmessage(\"IsPrime\")\naddmessage(\"CountPrime\")\n\nlocal n1, n2 = 10000000001, 10000100001\nprint(\"Checking prime numbers between \", n1, \" and \", n2)\n\nfor i = n1, n2, 2 do\n    -- Send a message to ourself to check a number.\n    -- The result will be sent to the \"CountPrime\" message handler.\n    send(\"main\", \"IsPrime\", { number = i, reply_to = { message = \"CountPrime\" } })\n    nRequests = nRequests + 1\nend\n```\n\n**Execution:**\n\n```sh\n$ nexuslua demo2.lua\nChecked 50001 numbers in 8.44 seconds, found 4306 prime\n```\n\nIt's a bit faster, but not by much. **Why?** The main script still runs in a single thread. It loops through all 50,000\nnumbers and queues up the messages. Only *after* the script finishes does nexuslua process the queued messages in\nparallel. This is an anti-pattern but illustrates a key concept: to achieve true concurrency, the work must be initiated\nfrom a separate, parallel context.\n\n### Step 3: Structuring for Parallelism\n\nLet's refactor the code to prepare for true parallelism. We'll move the loop into its own function, `RequestPrimes`,\nwhich can be triggered by a single message.\n\n**`demo3.lua`**\n\n```lua\n#!/usr/bin/env nexuslua\n\n-- ... (IsPrime and CountPrime functions remain the same) ...\n\nfunction RequestPrimes(parameters)\n    print(\"Checking prime numbers between \", parameters.n1, \" and \", parameters.n2)\n    for i = parameters.n1, parameters.n2, 2 do\n        send(\"main\", \"IsPrime\", { number = i, reply_to = { message = \"CountPrime\" } })\n        nRequests = nRequests + 1\n    end\nend\n\naddmessage(\"IsPrime\")\naddmessage(\"CountPrime\")\naddmessage(\"RequestPrimes\")\n\n-- Trigger the whole process with a single message\nsend(\"main\", \"RequestPrimes\", { n1 = 10000000001, n2 = 10000100001 })\n```\n\n**Execution:**\n\n```sh\n$ nexuslua demo3.lua\nChecked 50001 numbers in 8.04 seconds, found 4306 prime\n```\n\nThe performance is similar, but the design is now ready. We have decoupled the *request* for work from the *execution*\nof the work.\n\n### Step 4: Full Power with Agents\n\nThis is where nexuslua shines. We'll create a dedicated `numbers` **agent** to handle the `IsPrime` checks. This agent\nruns in its own OS thread, completely in parallel with the `main` script.\n\n**`demo5.lua`**\n\n```lua\n#!/usr/bin/env nexuslua\n\nlocal nRequests, nCheckedPrimes, count = 0, 0, 0\nlocal startTime = time()\n\nfunction CountPrime(parameters)\n    nCheckedPrimes = nCheckedPrimes + 1\n    if parameters.isPrime then count = count + 1 end\n    if nCheckedPrimes == nRequests then\n        local endTime = time()\n        print(\"Checked \", nCheckedPrimes, \" numbers in \", (endTime - startTime) / 1.0e8, \" seconds, found \", count, \" prime\")\n    end\nend\n\nfunction RequestPrimes(parameters)\n    local maxThreads = (cores() + 1) // 2\n    print(\"Checking prime numbers between \", parameters.n1, \" and \", parameters.n2, \" using \" .. maxThreads .. \" threads.\")\n    for i = parameters.n1, parameters.n2, 2 do\n        -- Send the work to the dedicated \"numbers\" agent\n        send(\"numbers\", \"IsPrime\", { number = i, threads = maxThreads, reply_to = { agent = \"main\", message = \"CountPrime\" } })\n        nRequests = nRequests + 1\n    end\nend\n\nif not isreplicated() then\n    -- Define the agent's code as a string\n    local numbersAgentCode = [==[\n        function IsPrime(parameters)\n            -- ... (same prime checking logic) ...\n            return { isPrime = found }\n        end\n    ]==]\n\n    -- Create the \"numbers\" agent. It immediately runs in a new thread.\n    addagent(\"numbers\", numbersAgentCode, { \"IsPrime\" })\n    \n    addmessage(\"CountPrime\")\n    addmessage(\"RequestPrimes\")\n\n    -- Kick off the process\n    send(\"main\", \"RequestPrimes\", { n1 = 10000000001, n2 = 10000100001 })\nend\n```\n\n**Execution:**\n\n```sh\n$ nexuslua demo5.lua\nChecked 50001 numbers in 0.84 seconds, found 4306 prime\n```\n\n*Voilà!* A **12x speedup**. Here’s what happened:\n\n1. The `main` script creates the `numbers` agent, which starts running in a new thread.\n2. `main` sends a single message to itself to start `RequestPrimes`.\n3. The `RequestPrimes` loop now sends messages to the `numbers` agent, which is already running and ready to process\n   them in parallel.\n4. The `threads` parameter in `send()` tells the `numbers` agent it can replicate itself (create more threads) up to\n   `maxThreads` to handle the workload, massively parallelizing the prime checks.\n5. Each time a `numbers` agent finishes, it returns a result, which nexuslua automatically sends back to `main`'s\n   `CountPrime` function for aggregation.\n\nThis tutorial shows the core power of nexuslua: designing applications as a set of independent, message-driven agents\nthat can run concurrently.\n\n---\n\n## The Power of Decoupled Design\n\nEven if you don't need maximum parallelism, the agent model encourages a cleaner software architecture. Components\ncommunicate via well-defined messages instead of direct function calls. This decoupling makes your code more modular,\neasier to maintain, and naturally responsive, as no single component blocks another.\n\n---\n\n## Extending nexuslua with Plugins\n\nInstalled plugins are just **agents** addressable by name. While the CLI `run` chain (see below section *Usage*) is handy for quick tests, the idiomatic way to use plugins is to send asynchronous messages from a nexuslua script. This keeps your workflow non-blocking and composable.\n\n### Message shapes and why you must pass parameters forward\n\nPlugin replies have a consistent envelope:\n\n- The **payload returned by the plugin** (e.g. `imageBuffer`, `width`, `height`, `channels`, `depth`, …) may appear **at the top level** of the reply table **or** the plugin may perform work **in place** and return no payload.\n- In all cases the reply also carries:\n```\n\noriginal_message {\nmessage_name = \"\u003cMessageNameYouSent\u003e\"\nparameters   = { ...the parameters you sent... }\n}\n\n```\n- Some messages (e.g. **`CallOpenImageFile`**) return image fields **at the top level**.\n- Others (e.g. **`CallInvertImage`**) work **in place** and the next step must re-use the image fields from\n**`original_message.parameters`**.\n\n\u003e **Debugging tip:** call `printtable(p)` inside your handlers to inspect the exact shape you get back.\n\n### Example: open → invert → save (asynchronous, minimal)\n\nThe script below opens an image through the [acrion image tools](https://github.com/acrion/image-tools) plugin, inverts it in place, and then saves it.  \nIt intentionally demonstrates both cases: payload at **top level** (Open) vs **in-place** (Invert).\n\n```lua\n#!/usr/bin/env nexuslua\n-- Usage: nexuslua invert-and-save.lua \u003cinput\u003e \u003coutput\u003e\n\nlocal function merge(a, b)\nlocal t = {}\nfor k,v in pairs(a or {}) do t[k] = v end\nfor k,v in pairs(b or {}) do t[k] = v end\nreturn t\nend\n\nfunction OnLoaded(img)\n-- printtable(img)  -- inspect the reply if needed\nprint(\"Image loaded; inverting...\")\nsend(\"acrion image tools\", \"CallInvertImage\",\n     merge(img, { reply_to = { agent = \"main\", message = \"OnInverted\" } }))\nend\n\nfunction OnInverted(p)\n-- printtable(p)  -- Invert works in place: use original_message.parameters\nlocal out = arg[2]\nprint(\"Image inverted; saving to \" .. out .. \"...\")\nsend(\"acrion image tools\", \"CallSaveImageFile\",\n     merge(p.original_message.parameters, { path = out,\n                                            reply_to = { agent = \"main\", message = \"OnSaved\" } }))\nend\n\nfunction OnSaved(p)\n-- printtable(p)\nif p and p.error then\n  print(\"Error saving: \" .. tostring(p.error))\nelse\n  print(\"Workflow complete! Wrote \" .. p.original_message.parameters.path)\nend\nend\n\naddmessage(\"OnLoaded\")\naddmessage(\"OnInverted\")\naddmessage(\"OnSaved\")\n\nsend(\"acrion image tools\", \"CallOpenImageFile\", {\npath = arg[1],\nreply_to = { agent = \"main\", message = \"OnLoaded\" }\n})\n```\n\n**Why the `merge` calls?**\nEach message must receive its required image fields **flat** in the parameter table. nexuslua won’t “chain” fields from previous replies automatically. We therefore **re-use** the returned fields (top level for Open; `original_message.parameters` for in-place messages like Invert) and **overlay** any overrides (`reply_to`, `path`) before sending the next message.\n\n\u003e If you see “Missing parameter value for channels”: you likely forwarded the wrong table shape. Use `printtable(p)` and pass the image fields that the plugin actually returned (either top level or `original_message.parameters`).\n\n## Beyond Concurrency: Built-in Utility Functions\n\nnexuslua doesn't just add multithreading; it also enriches the Lua environment with a host of useful, cross-platform\nutility functions. These functions simplify common tasks and are available globally in any nexuslua script.\n\nHere are a few examples:\n\n- [import()](https://nexuslua.org/import.html): Utilize functions from shared libraries (*.dll, *.so, *.dylib) directly\n  within nexuslua scripts.\n- [zip(source_dir, archive_path)](https://nexuslua.org/zip.html) / [unzip(archive_path, target_dir)](https://nexuslua.org/unzip.html):\n  Built-in support for creating and extracting ZIP archives.\n- [`userdatadir()`] / [`homedir()`]: Provide cross-platform paths to standard user directories.\n- [env(...)](https://nexuslua.org/env.html): Read environment variables.\n- [`log(message)`](https://nexuslua.org/log.html): Writes a message to the `nexuslua.log` file in the [user data directory](https://cbeam.org/doxygen/namespacecbeam_1_1filesystem.html#ae598d93475d7f8675bb85d7542cf90ab) for easy debugging.\n- [`time()`](https://nexuslua.org/time.md): Returns a high-resolution timestamp, perfect for benchmarking.\n- [`cores()`](https://nexuslua.org/cores.md): Detects the number of available hardware threads on the system, which is useful for configuring parallel\n  tasks dynamically.\n\nFor a complete list and detailed documentation of all available functions, please visit **[https://nexuslua.org](https://nexuslua.org)**.\n\n---\n\n## Community\n\nHave questions, want to share what you've built, or just say hi? Join our community on Discord!\n\n💬 **[Join the nexuslua Discord Server](https://discord.gg/aaZPevdEen)**\n\n---\n\n## Plugin Manager \u0026 Marketplace Roadmap\n\n*   The [nexuslua library](https://github.com/acrion/nexuslua-library) already supports **Install / Uninstall / Update / License** management.\n*   The next step is to connect to the public registry at **[https://github.com/acrion/nexuslua-plugins](https://github.com/acrion/nexuslua-plugins)** to fetch **plugin metadata and versions** (from each plugin's `nexuslua_plugin.toml`).\n*   All plugins are usable from nexuslua, of course - but only a subset is relevant to [acrionphoto](https://github.com/acrion/photo); the application filters by a plugin's `main.lua` **message descriptors** (looking for I/O, coordinate handlers, and image parameters).\n\n## Plugin metadata (`nexuslua_plugin.toml`)\n\nEach plugin ships a `nexuslua_plugin.toml` in its **plugin root**. For *acrion image tools* the build generates it into the plugin directory. Example:\n\n```toml\ndisplayName = \"acrion image tools\"\nversion = \"1.0.246\"\nisFreeware = true\ndescription = \"A set of essential tools for basic image manipulation.\"\nurlHelp = \"https://github.com/acrion/image-tools\"\nurlLicense = \"https://github.com/acrion/image-tools/blob/main/LICENSE\"\nurlDownloadLinux = \"https://github.com/acrion/image-tools/releases/download/1.0.246/image-tools-Linux.zip\"\nurlDownloadWindows = \"https://github.com/acrion/image-tools/releases/download/1.0.246/image-tools-Windows.zip\"\n#urlDownloadDarwin = \"https://github.com/acrion/image-tools/releases/download/1.0.246/image-tools-Darwin.zip\"\n```\n\nNotes:\n\n* `urlDownloadDarwin` is commented out because the macOS build of the [acrion image tools plugin](https://github.com/acrion/image-tools) is temporarily unavailable during refactoring.\n* If `isFreeware = false`, the [acrionphoto](https://github.com/acrion/photo) Plugin Manager shows two extra buttons:\n\n  * **\"Get License Key…\"** → opens the system browser at `urlPurchase`.\n  * **\"Install key or other files…\"** → lets you select files to copy into the plugin’s `persistent/` folder (survives updates/uninstall).\n* In the forthcoming public registry (`acrion/nexuslua-plugins`), the central list stores **only URLs** to each plugin’s TOML. Versioning and updates remain fully under the plugin author’s control.\n\n---\n\n## Usage\n\nThe `nexuslua` executable can be used to run scripts, execute code directly, or interact with plugins from the command\nline.\n\n#### General Commands\n\n* **Print help and command line options**\n  ```bash\n  nexuslua -h\n  # or\n  nexuslua --help\n  ```\n\n* **Print version and license information**\n  ```bash\n  nexuslua -v\n  ```\n\n#### Executing Code\n\n* **Run a nexuslua script file**\n  ```bash\n  nexuslua /path/to/your/script.lua\n  ```\n\n* **Run a string of code from the command line**\n  ```bash\n  nexuslua -e \"print('hello')\"\n  ```\n\n#### Interacting with Plugins\n\n* **Get help on available plugins and messages**\n  ```bash\n  # List all available plugins and their messages\n  nexuslua help\n  \n  # Get detailed help for a specific plugin message\n  nexuslua help \"acrion image tools\" CallOpenImageFile\n  ```\n\n* **Run a sequence of plugin messages**\n\n  You can chain multiple commands to create complex workflows directly from your terminal. Note that you must repeat the\n  `run` keyword for each message in the sequence. This is intended for scenarios where you only want to use plugin\n  functionality without additional logic.\n  You have more possibilities when using plugins directly from your nexuslua scripts, particularly with regard to\n  concurrency.\n\n  ```bash\n  # This example loads an image, inverts its colors, and saves it to a new file.\n  nexuslua run \"acrion image tools\" CallOpenImageFile path /path/to/input.jpg \\\n           run \"acrion image tools\" CallInvertImage \\\n           run \"acrion image tools\" CallSaveImageFile path /path/to/output.jpg\n  ```\n\n**Note:** A REPL (Read-Eval-Print Loop) for interactive sessions is not yet implemented.\n","funding_links":["https://github.com/sponsors/acrion","https://liberapay.com/acrion","https://buymeacoffee.com/acrion","https://patreon.com/acriondev"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Facrion%2Fnexuslua","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Facrion%2Fnexuslua","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Facrion%2Fnexuslua/lists"}