Metadata-Version: 2.4
Name: luafend
Version: 2.1.0
Summary: Command line client for Luafend - Lua and Luau source code protection.
Project-URL: Homepage, https://bypass.onl
Project-URL: Documentation, https://luafend.com/docs
Keywords: lua,luau,obfuscator,obfuscation,code-protection,roblox
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Build Tools
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# Luafend CLI

Command line client for [Luafend](https://bypass.onl) — source protection for Lua and
Luau. Protect a script from your terminal, a build script or a CI job.

Targets **Luau**, **Lua 5.1** and **Lua 5.4**, covering Roblox, Garry's Mod, LuaJIT,
embedded Lua and standalone hosts.

## Install

```bash
pip install luafend
```

Or without installing it into your project:

```bash
pipx install luafend
```

Requires Python 3.9 or newer. Standard library only, no dependencies.

## Two ways to use it

Run `luafend` with no arguments for an interactive shell, where every command starts with a
slash and Tab completes files, flags and values:

```
luafend ~ > /obfuscate main.lua --mode maximum
```

Or run the same commands straight from your shell, without the slash — this is the form a
build script or CI job uses:

```bash
luafend obfuscate main.lua --mode maximum --lua luau
```

## Getting started

```bash
luafend login                    # opens your browser, no password typed
luafend obfuscate main.lua       # writes main.obf.lua
```

The first run asks for the mode and the Lua version and remembers both. Every run after
that is silent, and prints what it used and where the setting came from.

## Use it from Python

```python
import luafend

print(luafend.obfuscate('print("hello")', key="luf_YOUR_KEY", mode="maximum", lua="luau"))
```

To write the result to a file, pass `out` and the encoding is handled for you:

```python
import luafend

source = open("main.lua", encoding="utf-8").read()
luafend.obfuscate(source, key="luf_YOUR_KEY", mode="maximum", lua="luau",
                  out="main.obf.lua")
```

That is the whole interface. `key` is an API key from the dashboard; leave it out and the
`LUAFEND_TOKEN` environment variable is used, then the account from `luafend login`.
`mode` is `lite`, `balanced` or `maximum`, and `lua` is `luau`, `lua-5.1` or `lua-5.4`.

Anything the server refuses raises `luafend.LuafendError` with the reason: out of credit,
mode not on your plan, key invalid, or the script does not parse.

## Commands

| Command | What it does |
|---|---|
| `login` | Sign in through your browser |
| `logout` | Sign out and revoke this machine's token |
| `whoami` | Name, email, sign-in provider, plan |
| `billing` | Plan, credits, monthly usage and limits |
| `obfuscate <file>` | Protect one script |
| `batch <pattern>` | Protect many files at once |
| `settings` | Show, reset or write project settings |
| `cd [folder]` | Show or change the current folder |
| `update` | Check for a newer version and install it |
| `docs` | Open the documentation |
| `version` | Show the CLI version |

## Options

| Flag | Meaning |
|---|---|
| `--mode lite\|balanced\|maximum` | How much protection. Lite is fastest, Maximum compiles the script into its own virtual machine |
| `--lua luau\|lua-5.1\|lua-5.4` | Which Lua the result has to run on |
| `-o, --out <path>` | Where to write. A folder for `batch`, a file for `obfuscate` |
| `--pick` | Choose mode and version again instead of using the saved ones |
| `--force` | Overwrite an existing output file |
| `--stdout` | Print the result instead of writing a file |
| `--all` | `batch` only: rebuild every file, including unchanged ones |

Without `--lua`, the version is guessed from the file: a `.luau` extension or Roblox
globals such as `game:GetService` mean Luau. The guess is always printed.

## Protecting many files

```bash
luafend batch "src/**/*.lua" -o dist
```

`*` and `?` never cross a path separator, `**` matches any number of directories. A plain
folder means every `.lua` and `.luau` inside it. Files that have not changed since their
last build are skipped, so a rebuild does not spend your monthly quota twice. Requests are
paced to your account's rate limit.

## Project settings

`luafend.json` pins how a project builds, so everyone working on it gets the same result:

```json
{
  "mode": "maximum",
  "lua": "luau",
  "out": "dist",
  "include": ["src/**/*.lua"]
}
```

It is searched for upwards from the current folder, so any subfolder of the project
behaves the same. With an `include` list, plain `luafend batch` is enough.

`luafend settings` shows what applies and where each value came from. `luafend settings
init` writes a starter file next to your token, which then applies everywhere you have no
project file.

## Signing in

`login` never asks for a password. It opens a consent page in the browser where you are
already signed in and waits for approval. The token it receives is stored in your OS
config directory, never in the working directory:

| | |
|---|---|
| Windows | `%APPDATA%\luafend\config.json` |
| macOS | `~/Library/Application Support/luafend/config.json` |
| Linux | `~/.config/luafend/config.json` |

On macOS and Linux the file is created with mode `0600`. `logout` revokes the token on the
server as well as deleting it here.

The token is only ever sent to the official Luafend API or to a server on your own machine.

## In CI

Set `LUAFEND_TOKEN` instead of signing in. It takes priority over the config file, so no
login step is needed:

```yaml
- run: pip install luafend
- run: luafend batch "src/**/*.lua" -o dist --mode balanced --lua luau
  env:
    LUAFEND_TOKEN: ${{ secrets.LUAFEND_TOKEN }}
```

Without a terminal, nothing is ever asked interactively: a missing setting fails with the
flag it needs named, rather than blocking on a prompt nobody can answer.

Exit codes:

| Code | Meaning |
|---|---|
| `0` | Success |
| `1` | Error |
| `2` | Not signed in, or the session expired |
| `3` | Out of credits, or the plan does not allow that mode |

## Environment

| Variable | Effect |
|---|---|
| `LUAFEND_TOKEN` | Use this token instead of the stored one |
| `LUAFEND_API` | Point at a different API host, for local development |
| `NO_COLOR` | Turn colour off |
| `LUAFEND_ASCII=1` | Plain ASCII instead of box drawing characters |

## Links

- Website — https://bypass.onl
- Documentation — https://bypass.onl/docs
- The same client for Node.js — https://www.npmjs.com/package/luafend
