agpk
v1.2.4
Published
Agentics Package Manager — Encrypted native binary compiler + package manager for JavaScript
Maintainers
Readme
Agentics Package Manager
The only JavaScript toolchain that ships encrypted, native binaries.
Package manager. Bundler. Encryptor. Compiler. One tool.
What is AGPK?
AGPK is a complete JavaScript toolchain that does what no other tool on the market does: it takes your JavaScript or TypeScript project, bundles it, encrypts the source with AES-256-CTR, generates a native C binary with the encrypted payload embedded inside, and compiles it into a single executable. Your source code never touches a disk at runtime. It exists only in memory, for the duration of execution, and is wiped the moment the process ends.
It is also a fully functional package manager with dependency resolution, a global content-addressable store, lockfile management, and parallel installation - competing directly with npm, yarn, pnpm, and bun on the package management side, while offering a compilation pipeline that none of them have.
Output is a single native binary for the OS / arch of your choice - Linux, macOS, Windows, x64, x86, ARM64 or ARM32 - produced from any Node-compatible JavaScript or TypeScript source. A single agpk compile-all produces every binary plus a generated Node CLI wrapper into dist/ in one pass. Scripts in your package.json run with a single command (agpk <script>, yarn-style), and the interactive surface is a clack-prompts-style flow with select menus, validated text inputs, and a clean two-accent palette.
Why AGPK Exists
Every JavaScript bundler on the market produces readable output. Minification is obfuscation theatre - any competent engineer can reverse it in an afternoon. Bytecode compilation (V8 snapshots, Bun's bytecode) is equally reversible with widely available decompilers.
If you're shipping a commercial Node.js application, a proprietary CLI tool, a paid API server, or an internal enterprise tool, your source code is exposed. There is currently no production-grade solution in the JavaScript ecosystem that protects intellectual property at the binary level.
AGPK solves this. It doesn't obfuscate. It doesn't minify and hope. It encrypts with AES-256-CTR and compiles to a native binary where the decryption key is split, XOR-masked, and scattered across the compiled C code. The JavaScript source is reconstructed in memory at runtime and destroyed on exit. No temp files survive. No source hits the disk in readable form.
How the Binary Works
Understanding the compilation pipeline is critical to understanding why AGPK is fundamentally different from every other tool in this space.
The Pipeline
Stage 1 - Bundle
AGPK detects your project's entry point (from package.json or via smart auto-detection) and bundles all source files and node_modules into a single JavaScript file using bun or esbuild. All dependencies are inlined. The output is a self-contained JS blob with zero external requirements.
Stage 2 - Encrypt
The bundled source is encrypted with AES-256-CTR using a cryptographically random 256-bit key and a 128-bit initialization vector generated via Node's crypto.randomBytes. The encryption produces:
- The encrypted payload (same size as input - CTR mode is a stream cipher)
- A SHA-256 integrity hash of the original source
- The AES key, which is then split and obfuscated
Key Splitting
The 256-bit AES key is never stored whole. It is split into two 128-bit halves, and each half is XOR'd with a randomly generated 128-bit mask:
key_part1[i] = key[i] XOR mask[i]
key_part2[i] = key[i + 16] XOR mask[i]All three components (part1, part2, mask) are embedded as separate static byte arrays in the generated C code. To reconstruct the key at runtime:
for (int i = 0; i < 16; i++) {
key[i] = key_part1[i] ^ key_mask[i];
key[i + 16] = key_part2[i] ^ key_mask[i];
}The key is reconstructed on the stack, used for decryption, and immediately zeroed from memory. It never exists in a readable form in the binary's data section - static analysis tools looking for contiguous key material will find nothing.
Stage 3 - C Code Generation
AGPK generates four files:
| File | Purpose |
|------|---------|
| payload.h | Encrypted source as a static byte array, plus the split key parts, IV, and auth tag |
| config.h | Platform-specific configuration and Node.js interpreter search paths |
| stub.c | The runtime stub - handles decryption, temp file creation, process execution, and cleanup |
| aes.c / aes.h | Vendored tiny-AES-c implementation (no OpenSSL dependency) |
The AES implementation is compiled directly into the binary. There is no runtime dependency on OpenSSL, libcrypto, or any shared library. The binary is entirely self-contained.
Stage 4 - Native Compilation
The generated C code is compiled with gcc, clang, or cl.exe (auto-detected) into a native binary with full optimizations (-O2 -s). The result is a standard ELF (Linux), Mach-O (macOS), or PE (Windows) executable.
Runtime Execution Model
When the compiled binary is executed:
- Memory allocation - The encrypted payload size is known at compile time. A buffer is allocated on the heap.
- Key reconstruction - The three key components are XOR'd together on the stack to produce the original 256-bit AES key.
- Decryption - AES-256-CTR decryption is performed entirely in memory. The plaintext JavaScript is written to the allocated buffer.
- Key destruction - The reconstructed key and the AES context are immediately zeroed with
memset. - Temp file on tmpfs - On Linux, the decrypted source is written to
/dev/shm(a RAM-backed filesystem). If/dev/shmis unavailable,/tmpis used. The file is created with0700permissions in amkdtemp-generated directory. - Process execution -
fork()+execvp()launches Node.js with the temp file. All originalargvarguments are forwarded. - Immediate deletion - The temp file and its directory are
unlink()'d andrmdir()'d within 100ms of the child process starting - before it has finished loading. On Linux, the file remains accessible to the running process (the kernel keeps the inode alive) but is invisible on the filesystem. - Signal handling -
SIGINTandSIGTERMhandlers ensure cleanup occurs even if the process is killed. - Exit - The parent process waits for the child to exit and returns its exit code.
The decrypted JavaScript source exists on disk for less than 100 milliseconds, in a RAM-backed filesystem, in a randomly named directory, with no read permissions for other users. On many Linux configurations with /dev/shm, it never touches a physical disk at all.
Standalone Mode (Node SEA)
With --standalone, AGPK goes further. It uses Node.js Single Executable Applications (SEA) to embed the entire Node.js runtime into the binary alongside the encrypted payload. The result is a single file that runs on any machine without Node.js installed:
agpk compile --standalone
# Produces a ~50-90MB binary that runs anywhere, encrypted, zero dependenciesThe SEA bootstrap script reconstructs the AES key, decrypts the payload in memory, and evaluates it - all within the embedded V8 runtime. No temp files. No disk I/O for the source. Pure in-memory execution.
AGPK vs Everything Else
| Capability | npm | yarn | pnpm | bun | AGPK | |---|---|---|---|---|---| | Package management | ✓ | ✓ | ✓ | ✓ | ✓ | | Bundling | ✗ | ✗ | ✗ | ✓ | ✓ | | Source encryption | ✗ | ✗ | ✗ | ✗ | AES-256-CTR | | Native binary output | ✗ | ✗ | ✗ | ✗¹ | ✓ | | Standalone binaries | ✗ | ✗ | ✗ | ✗ | ✓ (Node SEA) | | Key splitting/obfuscation | ✗ | ✗ | ✗ | ✗ | ✓ | | Memory-only source execution | ✗ | ✗ | ✗ | ✗ | ✓ | | Content-addressable store | ✗ | ✗ | ✓ | ✗ | ✓ | | Hardlink installs | ✗ | ✗ | ✓ | ✗ | ✓ | | Parallel resolution | ✗ | ✗ | ✓ | ✓ | ✓ | | Build caching | ✗ | ✗ | ✗ | ✗² | ✓ | | HTTP keep-alive pooling | ✗ | ✗ | ✓ | ✓ | ✓ | | Framework auto-detection | ✗ | ✗ | ✗ | ✗ | ✓ | | Cross-platform compilation | ✗ | ✗ | ✗ | ✗ | ✓ |
¹ Bun's bun build --compile produces a binary, but the source is embedded as bytecode that can be decompiled. It is not encrypted.
² Bun caches transpilation, not compiled binary output.
Why not just use Bun's --compile?
Bun's compile flag produces a binary that contains V8/JSC bytecode. Bytecode is not source protection - it is a performance optimization. Decompilers for JavaScript bytecode exist and are actively maintained. The original source structure, variable names, and logic are recoverable.
AGPK's output is a compiled C binary containing an AES-256-CTR encrypted blob. Recovering the source requires:
- Reverse engineering the compiled C binary
- Locating three separate byte arrays (two key parts + XOR mask) in the binary's data section
- Understanding the XOR reconstruction algorithm
- Performing AES-256-CTR decryption with the reconstructed key
This is a fundamentally different class of protection. It is not unbreakable - nothing is - but it elevates the difficulty from "run a decompiler" to "reverse engineer a native binary," which is the same class of difficulty as reversing any compiled C/C++ application.
Why not pkg or nexe?
Both pkg and nexe are unmaintained, do not encrypt source code, have poor Node.js version support, and embed raw JavaScript or V8 snapshots in the binary. They solve distribution (single-file output) but not protection.
AGPK solves both. And it's also your package manager.
Installation
npm install -g agpkQuick Start
# Initialize a project (interactive)
agpk init
# Or scaffold instantly with sensible defaults
agpk init -y
# Install dependencies
agpk
# Add a package
agpk add express
# Run any script defined in package.json - yarn-style
agpk start
agpk test
agpk dev
# Build (runs your build script)
agpk build
# Compile to encrypted native binary
agpk compile
# Compile to standalone binary (embeds Node.js)
agpk compile --standalone
# Cross-compile to a 32-bit Windows machine
agpk compile -w32
# Or target a specific OS / arch combo
agpk compile --target linux-x86
agpk compile --target win-arm64
# Build every binary plus a CLI wrapper into dist/ in one shot
agpk compile-all
# Same, plus ARM64 + ARM32 for linux and win (8 total)
agpk compile-all --arm
# Just refresh the dist/cli.js wrapper, no binaries
agpk compile-all --cli-only
# Add a local package (no npm round-trip, ever)
agpk add ./packages/shared
agpk add file:../sibling-pkg
agpk add link:./local-dev-pkg # symlink instead of hardlink
agpk add myname@file:./other-package # explicit aliasCommands
Package Management
| Command | Description |
|---------|-------------|
| agpk | Install all dependencies (like yarn with no args) |
| agpk init | Initialize a new project - interactive flow with select menus for template, module system and license |
| agpk init -y | Scaffold with defaults, skip prompts |
| agpk init --template <tpl> | Use a template: default, cli, server, bare |
| agpk add <pkg> | Add a registry dependency (npm → yarn → jsr → github fallback chain) |
| agpk add -D <pkg> | Add a dev dependency |
| agpk add <path> | Add a local package by relative or absolute path (no registry round-trip) |
| agpk add file:<path> | Same as above, explicit protocol — hardlinks the package tree into node_modules/ |
| agpk add link:<path> | Symlink the local package into node_modules/ instead of hardlinking. Live edits picked up instantly. |
| agpk add portal:<path> | Alias of link: |
| agpk add <name>@file:<path> | Local install under an explicit dependency name |
| agpk remove <pkg> | Remove a dependency |
| agpk install | Install all from lockfile or package.json |
| agpk <script> | Run any script from package.json directly - yarn-style. agpk test runs the test script, agpk lint runs the lint script, etc. Built-in subcommands still win precedence. |
| agpk run <script> | Explicit form of the above |
Build & Compile
| Command | Description |
|---------|-------------|
| agpk build | Run the project's build script (like yarn build) |
| agpk compile | Auto-detect entry, encrypt, compile to native binary |
| agpk compile <file> | Compile a specific file |
| agpk compile <dir> | Compile a project directory |
| agpk compile-all (agpk ca) | Produce 4 binaries (linux/win × x64/x86) + a generated dist/cli.js Node wrapper in one pass. Prompts to backup or wipe an existing dist/. |
| agpk compile-all --arm | As above plus arm64 + arm32 for both linux and win (8 binaries total). |
| agpk compile-all --cli-only | Skip every binary, only regenerate dist/cli.js using the package name from agpk.json / package.json. |
| agpk compiler (agpk cp) | Interactive picker. Multi-select every architecture (incl. macOS + ARM) plus a CLI-wrapper checkbox, then choose Standard / Standalone / Plain. Missing toolchains trigger the install-or-skip prompt before any compile fires. |
| agpk install-toolchain (agpk it) | Auto-detect package manager and install missing cross-compilers. Interactive multiselect when no target is specified. |
| agpk install-toolchain --all | Install every cross-compiler agpk knows about (linux/win × x64/x86/arm64/arm32). |
| agpk install-toolchain --arm | Install only ARM cross-compilers (linux-arm64, linux-arm32, win-arm64, win-arm32). |
| agpk install-toolchain linux-arm32 win-x86 | Install only the named targets. |
Compile Flags
| Flag | Description |
|------|-------------|
| --out <name> | Output binary name. When omitted and a platform flag is set, the binary is suffixed -<platform>-<arch> automatically (e.g. myapp-linux-x64, myapp-win-arm32). |
| --target <os[-arch]> | Cross-compile target. Accepts plain OS (linux, darwin, win) or compound <os>-<arch> like linux-x86, win-arm64, darwin-x64, linux-arm32. The arch portion is parsed out and applied independently. |
| -l / -w / -m | Shorthand: Linux / Windows / macOS (defaults to x64) |
| -l32 / -w32 / -m32 | Shorthand: 32-bit (x86) Linux / Windows / macOS |
| -l64 / -w64 / -m64 | Explicit 64-bit shorthand - aliases of -l / -w / -m |
| --arm | ARM target. Defaults to arm64; combine with -l / -w for cross-compile. |
| --arm64 / --arm32 | Explicit ARM 64-bit or 32-bit. |
| --arch <arch> | Target architecture independently of --target. Accepts x64 (default), x86, arm64, arm32, plus aliases (ia32, i386, i686, amd64, x86_64, aarch64, armv7, armv7l, armhf, arm). |
| --minify | Minify source before encryption |
| --static | Static linking (musl on Linux) |
| --standalone | Embed Node.js runtime for zero-dependency distribution. Host arch must match target arch - for cross-arch use the default (non---standalone) path, which supports it via gcc / mingw. |
| --no-encrypt | Output bundled JS without encryption (debugging/development) |
| --external <pkg,pkg> | Exclude packages from the bundle |
| --no-cache | Skip the build cache |
| --entry <file> | Override entry-point detection |
| --skip-build | Skip framework auto-detection and pre-build step |
32-bit (x86) toolchain requirements
To produce x86 binaries on a 64-bit host, install the 32-bit cross-toolchain:
| Distro | Install |
|--------|---------|
| Arch / Manjaro | Enable [multilib] in /etc/pacman.conf, then pacman -S lib32-gcc-libs lib32-glibc |
| Debian / Ubuntu | apt install gcc-multilib |
| Fedora / RHEL | dnf install glibc-devel.i686 libgcc.i686 |
| Windows targets | pacman -S mingw-w64-gcc (Arch) - provides both x86_64-w64-mingw32-gcc and i686-w64-mingw32-gcc |
ARM toolchain requirements
To cross-compile to ARM from an x64 host, install the matching cross-toolchain:
| Distro | Install |
|--------|---------|
| Arch / Manjaro | pacman -S aarch64-linux-gnu-gcc arm-linux-gnueabihf-gcc |
| Debian / Ubuntu | apt install gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf |
| Fedora / RHEL | dnf install gcc-aarch64-linux-gnu gcc-arm-linux-gnu |
| Windows ARM targets | Install llvm-mingw (provides aarch64-w64-mingw32-clang and armv7-w64-mingw32-clang) |
Utilities
| Command | Description |
|---------|-------------|
| agpk info | Show project configuration and build settings |
| agpk why <pkg> | Explain why a package is installed |
| agpk list | List all dependencies with installed versions |
| agpk clean | Clear caches and build artifacts |
| agpk clean --store | Also clear the global package store |
Framework Auto-Detection
When you run agpk compile in a framework project, AGPK automatically detects the framework and runs the appropriate build step before compiling:
| Framework | Detection | Pre-build Command |
|-----------|-----------|-------------------|
| Next.js | next.config.{js,mjs,ts} | next build → compiles .next/standalone/server.js |
| Nuxt | nuxt.config.{js,ts} | nuxt build → compiles .output/server/index.mjs |
| Vite | vite.config.{js,ts,mjs} | vite build |
| Vue CLI | @vue/cli-service in deps | vue-cli-service build |
| Create React App | react-scripts in deps | react-scripts build |
| TypeScript | tsconfig.json | tsc → compiles from configured outDir |
If your project has a custom build script in package.json, AGPK uses that instead of the default framework command.
Configuration
AGPK uses standard package.json - no custom config files needed. Drop into any npm project and it just works. Build configuration goes under the agpk key:
{
"name": "my-app",
"version": "0.1.0",
"main": "src/index.js",
"type": "module",
"scripts": {
"start": "node src/index.js",
"compile": "agpk compile",
"dev": "node --watch src/index.js"
},
"agpk": {
"encrypt": true,
"minify": false,
"target": "auto",
"static": false
},
"dependencies": {},
"devDependencies": {}
}The agpk section defines defaults that are applied whenever agpk compile is run. Flags passed on the command line override these defaults. The agpk key is entirely optional - AGPK works with any standard package.json out of the box.
Architecture
Content-Addressable Store
Like pnpm, AGPK maintains a global package store at ~/.agpk/store. Packages are extracted once into the store and hardlinked into each project's node_modules. Installing the same version of a package across 100 projects consumes disk space once.
Parallel Resolution
All dependencies at each level of the tree are resolved concurrently. Combined with HTTP connection pooling (48 concurrent keep-alive sockets) and request deduplication (multiple packages requiring the same transitive dependency result in a single registry fetch), AGPK's resolution speed scales with your CPU and network, not your dependency count.
Build Cache
AGPK hashes your source tree before compilation. If the hash matches a previous build, the cached binary is returned instantly - no bundling, no encryption, no C compilation. The cache is stored at ~/.agpk/build-cache and is keyed on both source hash and build flags (target, minify, static, standalone, encrypt).
Lockfile
agpk.lock uses a JSON format with integrity hashes for deterministic installs. The lockfile includes a top-level integrity hash of the entire dependency tree, enabling fast skip-resolution on subsequent installs when nothing has changed. Local-spec entries store the user-supplied spec (file:./pkg) rather than the resolved absolute path, so a project can move between machines and the local references re-resolve against the new project root.
Local Packages
agpk add skips the registry entirely when given a local path. The package's own package.json is read off disk to pull the name, version, and transitive dependencies, and the resulting tree entry is marked local: true so the installer takes the local-install path. Three protocols are recognised:
file:— copy/hardlink the local package tree intonode_modules/. Default for bare paths (./pkg,../sibling,/abs/path,~/lib).link:— create a directory symlink instead. Live edits to the source pick up immediately. Equivalent tonpm link/yarn linkbut scoped to a single dependency.portal:— alias oflink:.
The local install hardlink skips the source package's own node_modules/, .git/, and .agpk-stored markers so consumers don't recurse into the dependency's dependency tree.
Multi-Registry Fallback
fetchPackument walks an ordered list of registries on every lookup and short-circuits on the first 200. Default chain:
https://registry.npmjs.org(npm)https://registry.yarnpkg.com(yarn — npm mirror with different caching)https://npm.jsr.io(jsr — the JS Registry)https://npm.pkg.github.com(github packages)
404 / 401 / 403 from any registry is treated as "not here, try the next one" — the chain only throws when every registry has rejected the name. A 200 response is cached against the package name (not the registry), so subsequent lookups hit the cache regardless of which registry served the packument.
Override the chain via ~/.agpk/config.json:
{
"registry": "https://my-private-registry.example.com",
"registries": [
{ "name": "company", "url": "https://npm.internal.example.com" }
],
"scopeRegistries": {
"@my-org": "https://npm.internal.example.com"
}
}registry is the primary and prepended to the chain. registries[] is inserted before the defaults. scopeRegistries routes specific scopes (@my-org/anything) directly at a single registry, bypassing the chain.
compile-all and the Generated CLI Wrapper
compile-all produces every binary plus a generated Node script (dist/cli.js) in a single pass. The wrapper detects process.platform and process.arch at runtime and execs the matching binary out of the same directory — install one npm package that ships all four (or eight with --arm) binaries plus the wrapper as the bin entry, and the right binary runs on every platform the user installs it on.
When dist/ already exists, a select prompt asks (the same prompt is shared with agpk compiler):
- Install alongside existing files — overwrite only the targets being built and leave everything else in
dist/untouched. - Backup current dist — copies
dist/to the next freedist_backup_NNN/(zero-padded 3-digit, based on the highest existing number in the project root), then wipesdist/and continues. Default. - Wipe and start fresh — removes
dist/without a backup.
--cli-only skips every binary and just (re)writes dist/cli.js. Useful for refreshing the wrapper after a package rename without rebuilding everything.
The wrapper's platform / arch detection covers all 10 produced targets:
| process.platform | process.arch | Binary name |
|--------------------|----------------|-------------|
| linux | x64 | <pkg>-linux-x64 |
| linux | ia32 | <pkg>-linux-x86 |
| linux | arm64 | <pkg>-linux-arm64 |
| linux | arm | <pkg>-linux-arm32 |
| win32 | x64 | <pkg>-win-x64.exe |
| win32 | ia32 | <pkg>-win-x86.exe |
| win32 | arm64 | <pkg>-win-arm64.exe |
| win32 | arm | <pkg>-win-arm32.exe |
| darwin | x64 | <pkg>-darwin-x64 |
| darwin | arm64 | <pkg>-darwin-arm64 |
Any unsupported platform/arch combination throws a clear Unsupported platform: / Unsupported architecture: error at wrapper startup instead of silently failing.
Before any binary is built, compile-all runs a toolchain preflight check against every requested target. If any cross-compilers are missing, you get a three-way prompt:
- Install missing toolchains and build all — calls
install-toolchainfor the missing targets, then continues. - Skip missing targets, build the rest — drops the targets whose toolchains aren't available and carries on with the ones that are.
- Abort — does nothing.
--yes / -y auto-picks install. Individual compile failures during the loop are warned-and-skipped rather than fatal, so one bad target never kills the rest of the batch.
install-toolchain — auto-install cross-compilers
agpk install-toolchain detects the host OS, distro and package manager and installs the cross-compilers required for any compile target. Supported package managers:
| OS / Distro | Manager | Notes |
|-------------|---------|-------|
| Arch / Manjaro / EndeavourOS | pacman + yay / paru | Repo packages via pacman with sudo; AUR / chaotic-aur via yay/paru without sudo |
| Debian / Ubuntu | apt-get | sudo |
| Fedora / RHEL / CentOS | dnf | sudo |
| openSUSE | zypper | sudo |
| Alpine | apk | sudo |
| macOS | brew | no sudo |
| Windows | scoop → choco → winget | first found, no sudo |
Invocations:
agpk install-toolchain— interactive. Lists every target with installed/missing flags, multiselect to pick what to install.agpk install-toolchain --all— install every cross-compiler agpk knows about.agpk install-toolchain --arm— install only ARM (linux/win × arm64/arm32).agpk install-toolchain --x86— install only 32-bit x86 (linux + win).agpk install-toolchain --win/--linux— install all cross-compilers for that OS.agpk install-toolchain linux-arm32 win-x86 ...— install only the named targets.agpk install-toolchain --yes— skip the confirm prompt.
Targets with no native package on the current distro (Windows ARM on debian/fedora, macOS cross from anything) are reported with a manual-install link rather than silently skipped.
Fallback chain
Each target carries an ordered list of install steps. The installer walks the chain in order, verifies after each attempt, and only moves on if the current step fails or installs without putting the expected binary on PATH. Example: linux-arm32 on Arch tries
- Linaro precompiled binary (
arm-linux-gnueabihf-gcc13-linaro-binfrom AUR) — fast, but depends on snapshots.linaro.org being reachable. - Official ARM GNU toolchain — downloads the
arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-linux-gnueabihf.tar.xzarchive from developer.arm.com, extracts to/opt/agpk-toolchains/arm-none-linux-gnueabihf/, and symlinks both the Arm-official names (arm-none-linux-gnueabihf-*) and the standard names (arm-linux-gnueabihf-*) into/usr/local/bin/. Reusable forlinux-arm64(tripletaarch64-none-linux-gnu) as well. - Build from source (
arm-linux-gnueabihf-gccfrom AUR) — last resort, takes 1-2 hours.
Failed steps print a one-line reason and the chain continues. If every step fails the target is reported as still-missing in the final status section.
macOS native targets
On a macOS host, darwin-x64 and darwin-arm64 are detected as installed when native clang plus xcode-select -p both resolve — those are the prerequisites for clang -arch x86_64 and clang -arch arm64 native compiles. The darwin-x64 / darwin-arm64 install step on a macOS host calls xcode-select --install to trigger Apple's GUI installer for the Command Line Tools. From a Linux host, the same targets fall back to a manual osxcross install step (no automated install path exists for osxcross — it requires the Xcode SDK which can't be redistributed). Apple dropped 32-bit Intel and 32-bit ARM support in macOS Catalina (10.15), so no darwin-x86 or darwin-arm32 target exists.
llvm-mingw post-install symlink hook
On Arch, llvm-mingw from chaotic-aur / AUR installs into /opt/llvm-mingw/bin/ which is not on $PATH. The win-arm64 / win-arm32 install steps chain into a llvm-mingw-postlink post-install method that symlinks every aarch64-w64-mingw32-* and armv7-w64-mingw32-* binary into /usr/local/bin/, so the cross-compilers are immediately resolvable after install with no manual PATH editing.
Security Model
AGPK's encryption is not a DRM system. It is a practical barrier against casual source extraction that raises the effort required to access your code from "open a text editor" to "reverse engineer a compiled binary."
What AGPK protects against:
- Direct source code reading from the distributed binary
- Trivial decompilation (unlike bytecode-based tools)
- Casual copying of proprietary logic
- Source exposure in containerized/cloud deployments where filesystem access may be shared
What AGPK does not protect against:
- A determined attacker with binary reverse engineering expertise and sufficient time
- Runtime memory inspection while the application is executing
- Hardware-level memory dumps
This is the same security model as any compiled C, C++, Go, or Rust application. The source is not in the binary. Recovering it requires the same class of effort as decompiling any native application.
System Requirements
- Node.js ≥ 18 (≥ 20 for
--standalone) - C compiler: gcc, clang, or MSVC (for native compilation)
- Bundler: bun or esbuild (auto-detected)
- postject (only for
--standalonemode)
Platform Support
| Platform | Native Binary | Standalone | Cross-Compile |
|----------|:---:|:---:|:---:|
| Linux x64 | ✓ | ✓ | - |
| Linux x86 (32-bit) | ✓ | - ¹ | ✓ (via gcc -m32) |
| Linux ARM64 | ✓ | ✓ | ✓ (via aarch64-linux-gnu-gcc) |
| Linux ARM32 | ✓ | - ¹ | ✓ (via arm-linux-gnueabihf-gcc) |
| macOS x64 | ✓ | ✓ | - |
| macOS ARM64 | ✓ | ✓ | - |
| Windows x64 | ✓ | ✓ | ✓ (via x86_64-w64-mingw32-gcc) |
| Windows x86 (32-bit) | ✓ | - ¹ | ✓ (via i686-w64-mingw32-gcc) |
| Windows ARM64 | ✓ ² | - | ✓ (via aarch64-w64-mingw32-clang) |
| Windows ARM32 | ✓ ² | - | ✓ (via armv7-w64-mingw32-clang) |
¹ Standalone (--standalone) embeds the host Node.js binary, and Node has not shipped 32-bit Linux or 32-bit ARM builds for years. For these targets use the default encrypted-binary path - it cross-compiles cleanly via the system C toolchain.
² Windows ARM requires the llvm-mingw toolchain; the default MinGW packages from most distros only ship x86_64 / i686 targets.
License
MIT - Agentics
Built by Connor Etherington.
