Getting Started
Install StickCode v6.0.15, activate your license, and encrypt data in one API call.
Installation
Install from npm. Prebuilt native binaries are bundled for most platforms — no compiler required on macOS x64. Linux may compile from source if no matching prebuild exists.
npm install stickcode
Add StickCode to your project with a caret range so future updates work with npm update:
npm install stickcode --save
# package.json will contain:
# "stickcode": "^6.0.15"
Requires Node.js 18+. Verify the CLI:
npx stick --help
Updating StickCode
After the vendor publishes a new release, update your installation with standard npm commands. Patch and minor releases within 6.x stay backward compatible — your existing .scnp files keep working without re-encryption.
1. Use a caret range in package.json
The ^ prefix tells npm it may install newer compatible versions (6.0.15, 6.1.0, etc.) when you run npm update:
{
"dependencies": {
"stickcode": "^6.0.15"
}
}
"stickcode": "^6.0.15"npm update stickcode works automatically
"stickcode": "6.0.14"npm update will not upgrade — you must edit package.json manually
2. Run the update
# Update StickCode only (recommended)
npm update stickcode
# Or update all dependencies in the project
npm update
# Install a specific latest 6.x release
npm install stickcode@^6.0.15
3. Verify the new version
npm list stickcode
node -e "console.log(require('stickcode/package.json').version)"
What you do not need to change
- License file (
*.lic) — same file, same path - Application code —
initFromFile(),encrypt(),decrypt()API unchanged within 6.x - Encrypted archives — existing
.scnpfiles decrypt with the new SDK (version compatibility) - Device activation — local
.device_registryinnode_modules/stickcode/is preserved across updates on the same machine
License activation
Production builds require a signed *.lic file. Place it in your project root, ~/.config/stickcode/, or /etc/stickcode/, then initialize once per process:
const stickcode = require('stickcode');
await stickcode.initFromFile();
// or: await stickcode.initFromFile('/etc/stickcode/license.lic');
The AES key is derived via HKDF-SHA256 from the server-signed activation token — never hard-code keys in production. CLI requires --license or STICKCODE_LICENSE_FILE (no default passphrase).
Processing modes
v6.0.x unifies buffer and stream pipelines under one module. Choose the right path for your payload size.
1. Encrypted (default)
Preprocess → Brotli → AES-256-GCM. Wire format version 0x05. Ideal for PII, backups, and exports.
const packed = stickcode.encrypt(data, { quality: 6 });
const plain = stickcode.decrypt(packed);
2. Compression only
Brotli without AES. Wire format version 0x00. Use when data is already secured or for storage-only pipelines.
const blob = stickcode.compressOnly(data, { quality: 6 });
Streaming large files
For DB dumps, video, and archives — constant memory via stream helpers. Output uses the .scnp convention.
const fs = require('fs');
await stickcode.pipeEncrypt(
fs.createReadStream('backup.sql'),
fs.createWriteStream('backup.sql.scnp'),
{ quality: 6 }
);
await stickcode.pipeDecrypt(
fs.createReadStream('backup.sql.scnp'),
fs.createWriteStream('backup.sql.restored')
);
Versioning & backward compatibility
StickCode uses two separate version concepts. This section explains both, what decrypt() detects automatically, and what you never need to pass as a parameter.
1. npm package version
The SDK release you install, e.g. stickcode@^6.0.15. Upgrading the package does not require re-encrypting existing archives — as long as they were created with the 6.x wire format below.
2. Wire format version byte
The first byte of every .scnp output. Tells the engine whether the payload is encrypted or compress-only. decrypt() reads this byte automatically — you never pass it.
Wire format version bytes (current engine)
| Byte | Meaning | Created by |
|---|---|---|
| 0x05 | Encrypted — Brotli + AES-256-GCM | encrypt() · pipeEncrypt() |
| 0x00 | Compress-only — Brotli, no AES | compressOnly() |
On encrypt — always the current format
Every new encryption uses the latest wire format. There is no option to write an older layout.
encrypt()andpipeEncrypt()always write version byte0x05compressOnly()always writes version byte0x00- Brotli
quality(0–11) is your choice at write time; default is 6
On decrypt — three things detected automatically
Call decrypt(buffer) or pipeDecrypt() with no version or quality parameters. The native engine inspects the payload and decides:
① Wire version byte (byte 0)
0x05 → decrypt AES-GCM, then decompress Brotli. 0x00 → decompress Brotli only. Any other value → decrypt fails.
② Brotli compression level (quality 0–11)
Embedded inside the Brotli bitstream. The decoder reads dictionary and token metadata from the payload itself — you do not pass quality to decrypt(). A file compressed at quality 4 opens correctly even if you now encrypt new data at quality 11.
③ Buffer vs stream layout (CLI only)
Two physical layouts exist for where the GCM auth tag sits:
Buffer: [version][iv:12][tag:16][ciphertext…] ← encrypt()
Stream: [version][iv:12][ciphertext…][tag:16] ← pipeEncrypt()
In application code, use the matching API: decrypt() for buffer output, pipeDecrypt() for stream output. The CLI command stick dec tries buffer layout first, then falls back to stream — automatically.
Behind the scenes — decrypt pipeline
decrypt(input)
│
├─ Read byte[0] → version (0x05 or 0x00)
│
├─ If 0x05 (encrypted):
│ Parse IV (12 B) + auth tag (16 B) + ciphertext
│ Verify AES-256-GCM tag → fail fast if tampered
│ Decompress Brotli → quality read from bitstream (not from caller)
│
└─ If 0x00 (compress-only):
Decompress Brotli directly → quality read from bitstream
Compatibility matrix
| Scenario | Works automatically? |
|---|---|
Decrypt archive created with 0x05 on any 6.x package |
Yes |
Decrypt archive created with 0x00 (compress-only) |
Yes |
| Open file compressed at quality 1 after upgrading SDK to 6.0.15 | Yes — no re-encryption needed |
| Mix quality levels in the same database (some Q4, some Q9) | Yes — each blob self-describes its compression |
CLI stick dec on unknown buffer/stream layout |
Yes — auto-detects layout |
Legacy wire format 0x04 (pre-6.x JavaScript engine) |
No — re-encrypt with 6.x or contact support for migration |
Summary for developers
- Encrypt: always writes
0x05(or0x00for compress-only) — you choosequalityonly. - Decrypt: pass the buffer or stream only — version byte, compression level, and (in CLI) layout are resolved internally.
- Upgrade SDK: existing 6.x
.scnpfiles keep working; no migration step required.
Compression quality & CPU latency
Brotli quality runs from 0 (fastest) to 11 (smallest output). API and CLI default is 6. Quality is write-only — decrypt() reads the bitstream without needing the original level.
The native decoder reads Brotli metadata embedded in the payload. You can rotate quality tiers across datasets without breaking backward compatibility — no quality flag needed on decrypt().
Quick Start
Full production flow — license, buffer encrypt, and CLI equivalent:
const fs = require('fs');
const stickcode = require('stickcode');
// 1. Activate license (once per process)
await stickcode.initFromFile();
// 2. Encrypt JSON / text in memory
const input = fs.readFileSync('report.json');
const packed = stickcode.encrypt(input, { quality: 6 });
fs.writeFileSync('report.json.scnp', packed);
// 3. Decrypt — quality not required
const restored = stickcode.decrypt(packed);
// CLI equivalent:
// npx stick enc report.json --license ./license.lic
// npx stick dec report.json.scnp
💾 Storage & networking
Always treat output as binary — never base64-encode unless your transport requires it.
-
1. Saving to disk
fs.writeFileSync('data.scnp', packed); -
2. Network transfers
await axios.post(url, packed, { headers: { 'Content-Type': 'application/octet-stream' } }); -
3. Database storage
MongoDB (Mongoose):
encryptedData: { type: Buffer }PostgreSQL (Sequelize):
payload: DataTypes.BLOB