{"_id":"luafend","_rev":"41-cdfd73fe468794024b1fe18c33498a37","name":"luafend","dist-tags":{"latest":"2.5.0"},"versions":{"2.3.0":{"name":"luafend","version":"2.3.0","keywords":["lua","luau","obfuscator","obfuscation","code-protection","minifier","roblox"],"license":"UNLICENSED","_id":"luafend@2.3.0","maintainers":[{"name":"luafend","email":"maxi.alberg10@gmail.com"}],"homepage":"https://bypass.onl","bin":{"luafend":"bin/luafend.js"},"dist":{"shasum":"a1e0463a4744d998d87eefd4e0426accc5411793","tarball":"https://registry.npmjs.org/luafend/-/luafend-2.3.0.tgz","fileCount":14,"integrity":"sha512-BULbsWNEEdbCmM3Yl/CZzWB1WM1GtJCOog1vzuHQL08vsGDGz+N0T2iClCNQsB0WdxZvbA1aAVP/jH5Re29A5Q==","signatures":[{"sig":"MEUCIFA2p2GaMVlk3gZP7mFiel2wfdjp2XtnpzjvFqlhU5DNAiEAv8z45Kvqeqamo3DjjI7LD13P9V1h5TT8JrAkpbaSh0o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":86963},"main":"src/index.js","engines":{"node":">=18"},"_npmUser":{"name":"luafend","email":"maxi.alberg10@gmail.com"},"_npmVersion":"11.16.0","description":"Command line client for Luafend - Lua and Luau source code protection.","directories":{},"_nodeVersion":"24.18.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/luafend_2.3.0_1786283965620_0.21203675677216527","host":"s3://npm-registry-packages-npm-production"}},"2.4.0":{"name":"luafend","version":"2.4.0","keywords":["lua","luau","obfuscator","obfuscation","code-protection","minifier","roblox"],"license":"UNLICENSED","_id":"luafend@2.4.0","maintainers":[{"name":"luafend","email":"maxi.alberg10@gmail.com"}],"homepage":"https://bypass.onl","bin":{"luafend":"bin/luafend.js"},"dist":{"shasum":"1b2271f09e7e30e6d06a9d16826d75757840e55c","tarball":"https://registry.npmjs.org/luafend/-/luafend-2.4.0.tgz","fileCount":14,"integrity":"sha512-PtHrGhj5q1Sfg/CiHW0CvdcM+569X6A0Ci+oSnn+uxYeTGBzuDUiMeEazOvVqU5Pfwis+3Bsh9JmVp8rDvIrYA==","signatures":[{"sig":"MEUCIQD0XFqARKefXxSFATiwoxP8xaE9LkVCdjnvCO+shmpwzAIgXvBVKtBEDGMXtUJxKzwMkcVCbJQtgwZ4+Sk6sluDdZ4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":89448},"main":"src/index.js","engines":{"node":">=18"},"_npmUser":{"name":"luafend","email":"maxi.alberg10@gmail.com"},"_npmVersion":"11.16.0","description":"Command line client for Luafend - Lua and Luau source code protection.","directories":{},"_nodeVersion":"24.18.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/luafend_2.4.0_1786284751512_0.8734983529916502","host":"s3://npm-registry-packages-npm-production"}},"2.5.0":{"name":"luafend","version":"2.5.0","description":"Command line client for Luafend - Lua and Luau source code protection.","main":"src/index.js","bin":{"luafend":"bin/luafend.js"},"engines":{"node":">=18"},"license":"UNLICENSED","homepage":"https://bypass.onl","keywords":["lua","luau","obfuscator","obfuscation","code-protection","minifier","roblox"],"_id":"luafend@2.5.0","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-TjjhzHNSpji+ySFE6EXuu5860fWxkgEm0I0DboDZdzpongQzzW1/IZ5fP6W/zDyCcUy+IpDCxLBlqoaHV5jA1g==","shasum":"73af86cc6930dff99448438c213d03053448aaff","tarball":"https://registry.npmjs.org/luafend/-/luafend-2.5.0.tgz","fileCount":14,"unpackedSize":90192,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFLIx408/AbfTaBleUwPVN5s4/Tsy8ggvjwLdp8b8hQ+AiBvWHvC17KVo9TGeP/yTSCkKcwxTGB7Q5knziMKf1btiQ=="}]},"_npmUser":{"name":"luafend","email":"maxi.alberg10@gmail.com"},"directories":{},"maintainers":[{"name":"luafend","email":"maxi.alberg10@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/luafend_2.5.0_1786287945788_0.6201543645471383"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-06T13:46:54.331Z","modified":"2026-08-09T15:05:46.090Z","0.0.1":"2026-08-06T13:46:54.508Z","0.1.0":"2026-08-06T14:30:31.883Z","0.2.0":"2026-08-06T14:51:03.795Z","0.3.0":"2026-08-06T15:24:00.704Z","0.4.0":"2026-08-06T16:33:35.290Z","0.5.0":"2026-08-06T16:45:14.571Z","0.6.0":"2026-08-06T17:08:18.334Z","0.7.0":"2026-08-06T17:50:17.778Z","0.8.0":"2026-08-06T18:17:11.079Z","0.9.0":"2026-08-06T18:32:03.155Z","1.1.0":"2026-08-06T19:19:15.435Z","1.3.0":"2026-08-06T19:51:39.638Z","1.5.0":"2026-08-06T23:04:26.526Z","1.6.0":"2026-08-06T23:58:35.169Z","1.7.0":"2026-08-07T00:30:05.491Z","1.8.0":"2026-08-07T00:55:44.333Z","2.0.0":"2026-08-08T18:37:53.948Z","2.1.0":"2026-08-08T18:52:45.701Z","2.2.0":"2026-08-09T13:19:56.975Z","2.3.0":"2026-08-09T13:59:25.774Z","2.4.0":"2026-08-09T14:12:31.656Z","2.5.0":"2026-08-09T15:05:45.944Z"},"license":"UNLICENSED","homepage":"https://bypass.onl","keywords":["lua","luau","obfuscator","obfuscation","code-protection","minifier","roblox"],"description":"Command line client for Luafend - Lua and Luau source code protection.","maintainers":[{"name":"luafend","email":"maxi.alberg10@gmail.com"}],"readme":"# Luafend\n\nCommand line tool **and** Node.js library for [Luafend](https://bypass.onl) — source\nprotection for Lua and Luau. One package: protect a script from your terminal, from a build\nscript, from CI, or from your own code.\n\nTargets **Luau**, **Lua 5.1** and **Lua 5.4**, covering Roblox, Garry's Mod, LuaJIT,\nembedded Lua and standalone hosts.\n## Install\n\n```bash\nnpm install -g luafend\n```\n\nOr run it without installing:\n\n```bash\nnpx luafend\n```\n\nRequires Node.js 18 or newer. No dependencies.\n\n## Two ways to run the command line\n\nType **one word** — in Command Prompt or PowerShell on Windows, in Terminal on macOS and\nLinux — and Luafend opens its own shell. Inside it, every command starts with a slash:\n\n```\nluafend\n\nluafend ~ > /login\nluafend ~ > /obfuscate main.lua --mode maximum\nluafend ~ > /exit\n```\n\nTab completes commands, files, flags and values. Typing `--` suggests the flags that\ncommand accepts. `/help` lists everything.\n\nOr drop the slash and run the same command straight from your own shell. Nothing opens,\nthe job runs, you get your prompt back — this is the form a build script or CI job uses:\n\n```bash\nluafend login\nluafend obfuscate main.lua --mode maximum --lua luau\n```\n\n## Getting started\n\n```bash\nluafend login                    # opens your browser, no password typed\nluafend obfuscate main.lua       # writes main.obf.lua\n```\n\nThe first run asks for the mode and the Lua version and remembers both. Every run after\nthat is silent, and prints what it used and where the setting came from.\n\n## Use it from code\n\nThe short way: set it on the package, then run.\n\n```js\nconst luafend = require(\"luafend\");\n\nluafend.key = \"luf_YOUR_KEY\";\nluafend.mode = \"maximum\";\nluafend.lua = \"luau\";\n\nconst result = await luafend.run('print(\"hello\")');\n\nif (result.ok) {\n  console.log(result.output);\n} else {\n  console.log(result.error);\n}\n```\n\nSet `luafend.out = \"main.obf.lua\"` and the file is written for you as UTF-8. Set\n`luafend.source` and `run()` needs no argument at all.\n\nThese settings live on the package, so there is one set of them per program. That is\nright for a script and wrong for concurrent work; for a server use a client, which\ncarries its own:\n\n```js\nconst client = new luafend.Luafend({ key: \"luf_YOUR_KEY\" });\nclient.mode = \"maximum\";\nconst result = await client.run(source);\n```\n\nOr describe a single build one line at a time:\n\n```js\nconst luafend = require(\"luafend\");\n\nconst job = new luafend.Job();\njob.key = \"luf_YOUR_KEY\";\njob.source = 'print(\"hello\")';\njob.mode = \"maximum\";\njob.lua = \"luau\";\n\nconst result = await job.run();\n\nif (result.ok) {\n  console.log(result.output);\n} else {\n  console.log(result.error);\n}\n```\n\n`run()` never rejects. Every Result also carries the measurements, with no flag to switch\non:\n\n```js\nconsole.log(result.size);        // bytes of the protected script\nconsole.log(result.sourceSize);  // bytes of what you sent\nconsole.log(result.seconds);     // how long it took\nconsole.log(result.timestamp);   // when it finished, UTC\nconsole.log(result.quotaLeft);   // obfuscations left this month\n```\n\nSet `job.out = \"main.obf.lua\"` and the file is written for you as UTF-8, line endings\nintact.\n\nIf you just want the string and are happy for a failure to throw, there is a one line form\nthat rejects with a `LuafendError` instead:\n\n```js\nconsole.log(await luafend.obfuscate('print(\"hello\")', {\n  key: \"luf_YOUR_KEY\", mode: \"maximum\", lua: \"luau\",\n}));\n```\n\nLeave `key` out and `LUAFEND_TOKEN` is used, then the account from `luafend login`.\n`mode` is `lite`, `balanced` or `maximum`; `lua` is `luau`, `lua-5.1` or `lua-5.4`.\n\n## Commands\n\n| Command | What it does |\n|---|---|\n| `login` | Sign in through your browser |\n| `logout` | Sign out and revoke this machine's token |\n| `whoami` | Name, email, sign-in provider, plan |\n| `billing` | Plan, credits, monthly usage and limits |\n| `obfuscate <file>` | Protect one script |\n| `batch <pattern>` | Protect many files at once |\n| `settings` | Show, reset or write project settings |\n| `cd [folder]` | Show or change the current folder |\n| `update` | Check for a newer version and install it |\n| `docs` | Open the documentation |\n| `version` | Show the CLI version |\n\n## Options\n\n| Flag | Meaning |\n|---|---|\n| `--mode lite\\|balanced\\|maximum` | How much protection. Lite is fastest, Maximum compiles the script into its own virtual machine |\n| `--lua luau\\|lua-5.1\\|lua-5.4` | Which Lua the result has to run on |\n| `-o, --out <path>` | Where to write. A folder for `batch`, a file for `obfuscate` |\n| `--pick` | Choose mode and version again instead of using the saved ones |\n| `--force` | Overwrite an existing output file |\n| `--stdout` | Print the result instead of writing a file |\n| `--all` | `batch` only: rebuild every file, including unchanged ones |\n\nWithout `--lua`, the version is guessed from the file: a `.luau` extension or Roblox\nglobals such as `game:GetService` mean Luau. The guess is always printed.\n\n## Protecting many files\n\n```bash\nluafend batch \"src/**/*.lua\" -o dist\n```\n\n`*` and `?` never cross a path separator, `**` matches any number of directories. A plain\nfolder means every `.lua` and `.luau` inside it. Files that have not changed since their\nlast build are skipped, so a rebuild does not spend your monthly quota twice. Requests are\npaced to your account's rate limit.\n\n## Project settings\n\n`luafend.json` pins how a project builds, so everyone working on it gets the same result:\n\n```json\n{\n  \"mode\": \"maximum\",\n  \"lua\": \"luau\",\n  \"out\": \"dist\",\n  \"include\": [\"src/**/*.lua\"]\n}\n```\n\nIt is searched for upwards from the current folder, so any subfolder of the project\nbehaves the same. With an `include` list, plain `luafend batch` is enough.\n\n`luafend settings` shows what applies and where each value came from. `luafend settings\ninit` writes a starter file next to your token, which then applies everywhere you have no\nproject file.\n\n## Signing in\n\n`login` never asks for a password. It opens a consent page in the browser where you are\nalready signed in and waits for approval. The token it receives is stored in your OS\nconfig directory, never in the working directory:\n\n| | |\n|---|---|\n| Windows | `%APPDATA%\\luafend\\config.json` |\n| macOS | `~/Library/Application Support/luafend/config.json` |\n| Linux | `~/.config/luafend/config.json` |\n\nOn macOS and Linux the file is created with mode `0600`. `logout` revokes the token on the\nserver as well as deleting it here.\n\nThe token is only ever sent to the official Luafend API or to a server on your own machine.\n\n## In CI\n\nSet `LUAFEND_TOKEN` instead of signing in. It takes priority over the config file, so no\nlogin step is needed:\n\n```yaml\n- run: npx luafend batch \"src/**/*.lua\" -o dist --mode balanced --lua luau\n  env:\n    LUAFEND_TOKEN: ${{ secrets.LUAFEND_TOKEN }}\n```\n\nWithout a terminal, nothing is ever asked interactively: a missing setting fails with the\nflag it needs named, rather than blocking on a prompt nobody can answer.\n\nExit codes:\n\n| Code | Meaning |\n|---|---|\n| `0` | Success |\n| `1` | Error |\n| `2` | Not signed in, or the session expired |\n| `3` | Out of credits, or the plan does not allow that mode |\n\n## Environment\n\n| Variable | Effect |\n|---|---|\n| `LUAFEND_TOKEN` | Use this token instead of the stored one |\n| `LUAFEND_API` | Point at a different API host, for local development |\n| `NO_COLOR` | Turn colour off |\n| `LUAFEND_ASCII=1` | Plain ASCII instead of box drawing characters |\n\n## Links\n\n- Website — https://bypass.onl\n- Documentation — https://bypass.onl/docs\n- The same client for Python — https://pypi.org/project/luafend/\n","readmeFilename":"README.md"}