CLI Reference¶
Complete reference for the pylocket command-line tool (v1.1.19).
Install: pip install pylocket
Global Options¶
These options apply to all commands:
| Option | Description | Default |
|---|---|---|
--api-url <URL> |
Override the PyLocket API base URL | https://api.pylocket.com |
--token <TOKEN> |
Override the session token (the JWT from pylocket login) |
Read from ~/.pylocket/credentials |
--help, -h |
Show help for any command | — |
--version |
Show the CLI version | — |
The PYLOCKET_TOKEN environment variable can also be used instead of --token.
The PYLOCKET_API_URL environment variable can be used instead of --api-url.
--token is not your API key
It takes the session token issued by pylocket login, which expires
after 30 minutes. An API key passed here is rejected with 401, because the
CLI sends it as a Bearer credential and the server cannot decode it as a
JWT. API keys are for calling the REST API with the X-API-Key header; see
CI/CD Integration.
pylocket login¶
Authenticate with the PyLocket API.
Options¶
| Option | Description |
|---|---|
--email <EMAIL> |
Account email (prompted interactively if omitted) |
--password <PASSWORD> |
Account password (prompted interactively if omitted) |
--token <TOKEN> |
Authenticate directly with an existing session token, not an API key (skips interactive login) |
--sso |
Authenticate via browser (opens your default browser to the PyLocket portal) |
Behavior¶
- On success, stores credentials at
~/.pylocket/credentials - If 2FA is enabled, prompts for a TOTP code after password (or handles it in the browser with
--sso) - The stored token is reused for subsequent commands until it expires
Not for CI/CD
Every option here yields a session token that expires after 30 minutes, and the password form stops working once 2FA is enabled. For pipelines, use an API key against the REST API instead; see CI/CD Integration.
Browser-Based Login (--sso)¶
The --sso flag opens your default browser to the PyLocket portal for authentication. This is recommended if you:
- Have 2FA enabled and prefer entering your TOTP code in a browser
- Use a password manager that auto-fills browser forms
- Are on a shared machine and prefer not to type credentials in a terminal
After you sign in (including 2FA if enabled), the browser redirects back to the CLI automatically — no copy-pasting required. The CLI stores the credentials the same way as interactive login.
If the browser can't be opened (e.g., SSH session), the CLI prints the URL for you to open manually in any browser on the same machine.
Examples¶
# Interactive login (email/password in terminal)
pylocket login
# Browser-based login (recommended for 2FA users)
pylocket login --sso
# Non-interactive login (local scripts; fails once 2FA is enabled)
pylocket login --email dev@example.com --password "s3cret"
# Reuse a session token you already hold (expires after 30 minutes)
pylocket login --token "eyJhbGc..."
pylocket apps¶
Manage registered applications.
pylocket apps create¶
Register a new application.
| Option | Description | Required | Default |
|---|---|---|---|
--name <NAME>, -n |
Application display name | Yes | — |
--description <TEXT>, -d |
Application description | No | None |
--platform <PLATFORM>, -p |
Target platform | No | python |
pylocket apps list¶
List all registered applications.
| Option | Description | Default |
|---|---|---|
--page <N> |
Page number | 1 |
--page-size <N> |
Items per page | 20 |
pylocket apps update¶
Update an existing application.
| Option | Description |
|---|---|
--app <APP_ID> |
Application ID (required) |
--name <NAME> |
New display name |
--description <TEXT> |
New description |
Platform targets are fixed at creation time. The offline grace period and device limit live in the app's license policy, which is edited in the Developer Portal — updating it through the API replaces the whole policy object, so it is not exposed as a CLI flag.
pylocket apps delete¶
Delete a registered application.
Warning: Deleting an app revokes all associated licenses and removes all builds. This action cannot be undone.
pylocket protect¶
Upload and protect an application artifact.
Options¶
| Option | Description | Required | Default |
|---|---|---|---|
--app <APP_ID> |
Application ID | Yes | — |
--artifact <PATH> |
Path to the artifact to protect | Yes | — |
--platform <PLATFORM> |
Target platform (e.g. win-x64, linux-x64, darwin-arm64) |
No | Auto-detected from your OS |
--python <VERSION> |
Python version used to build the artifact | No | Engine-detected from the artifact |
--version <LABEL> |
Build version label | No | 1.0.0 |
--wait / --no-wait |
Wait for the protection build to complete | No | --wait |
--out <DIR> |
Auto-download to this directory when ready (implies --wait) |
No | — |
Valid Python versions: 3.12, 3.13, 3.14
Platform auto-detection
If --platform is not specified, the CLI reads your current platform from sysconfig.get_platform() and maps it to a PyLocket platform token: win-amd64 becomes win-x64, linux-x86_64 becomes linux-x64, and Apple Silicon Macs become darwin-arm64. You only need to specify --platform when cross-protecting for a different OS.
Python version auto-detection
If --python is not specified, the protection engine detects the Python version from the uploaded artifact itself (for example the PyInstaller archive header or embedded interpreter markers). Pass --python only as a hint when that detection fails.
Supported Artifact Types¶
| Extension | Description |
|---|---|
.py, .pyz, .pyw |
Python scripts |
.whl, .egg |
Python packages (wheels, eggs) |
.zip |
ZIP archives (must contain Python files) |
.tar.gz, .tgz, .tar.bz2 |
Compressed tar archives |
.exe |
Windows executables (PyInstaller, cx_Freeze) |
.elf |
Linux ELF executables (PyInstaller onefile) |
.app |
macOS application bundles (zipped .app directory) |
Note
PyInstaller onefile builds on Linux and macOS emit an extensionless binary. Rename it to .elf before running pylocket protect (the engine reads the real format from the bytes; for macOS GUI apps, upload the .app bundle instead).
Examples¶
# Protect an application (platform and Python version auto-detected)
pylocket protect \
--app 3f8a1c22-9b4e-4d17-a6f0-2c5e7d90b114 \
--artifact dist/myapp.exe
# Protect with explicit platform and Python version
pylocket protect \
--app 3f8a1c22-9b4e-4d17-a6f0-2c5e7d90b114 \
--artifact dist/myapp.exe \
--platform win-x64 \
--python 3.13
# Protect and auto-download when ready
pylocket protect \
--app 3f8a1c22-9b4e-4d17-a6f0-2c5e7d90b114 \
--artifact dist/myapp.exe \
--out dist/protected/
# Protect without waiting (check status later)
pylocket protect \
--app 3f8a1c22-9b4e-4d17-a6f0-2c5e7d90b114 \
--artifact dist/myapp.exe \
--no-wait
pylocket status¶
Check the status of a protection build.
Options¶
| Option | Description |
|---|---|
--build <BUILD_ID> |
Build ID to check |
--app <APP_ID> |
App ID (used with --latest) |
--latest |
Show the most recent build for the app |
--format <FORMAT> |
Output format: table (default), json |
Build Statuses¶
| Status | Description |
|---|---|
pending |
Build created and waiting for the protection worker |
processing |
Protection in progress |
ready |
Protection complete and ready for download |
failed |
An error occurred during protection |
rejected |
Artifact was flagged by the malware scan; the developer account is automatically suspended pending review |
Fine-grained progress (extraction, encryption, packaging) is reported in the separate processing_stage field of the build payload, not in status.
Examples¶
# Check a specific build
pylocket status --build 7c2d5e91-0a36-4b8f-9e14-8d63f2a70c55
# Check the latest build for an app (JSON output)
pylocket status --app 3f8a1c22-9b4e-4d17-a6f0-2c5e7d90b114 --latest --format json
pylocket fetch¶
Download a protected artifact.
Options¶
| Option | Description | Required |
|---|---|---|
--build <BUILD_ID> |
Build ID to download | Yes |
--out <DIR> |
Output directory | Yes |
--app <APP_ID> |
App ID (optional, improves lookup speed) | No |
Example¶
The command creates the output directory if it does not exist.
Tip
The --app flag is optional. You can use just --build and the server will look up the build automatically.
pylocket distribute¶
Generate a one-time direct download link for your application.
Options¶
| Option | Description | Required |
|---|---|---|
--app <APP_ID> |
Application ID | Yes |
Example¶
pylocket distribute --app 3f8a1c22-9b4e-4d17-a6f0-2c5e7d90b114
# Returns: https://get.pylocket.com/a1b2c3
The generated link is single-use and expires after 30 days. When an end user visits the link, they enter their details, download the app, and receive an auto-generated license. The first 10 downloads per app are free.
See Distribute Your App for the full distribution workflow.
pylocket licenses¶
Manage end-user licenses.
pylocket licenses create¶
Create a new license key.
This creates a billable license
Each license you create is charged the per-license fee on your next
invoice. The command asks for confirmation first; pass --yes to skip the
prompt in scripts.
On the Free plan you are not charged, but every license is issued as a
trial regardless of --type, and counts against your free-tier allowance.
Without --expires it expires in 30 days; an explicit --expires is
honored.
| Option | Description | Default |
|---|---|---|
--app <APP_ID> |
Application ID | (required) |
--email <EMAIL> |
End-user email | (optional) |
--device-limit <N> |
Max devices | 2 |
--expires <DATE> |
Expiration date (YYYY-MM-DD) | None (no expiry on Pro; 30 days on the Free plan) |
--type <TYPE> |
License type: standard, demo |
standard |
--channel <CHANNEL> |
Sales channel recorded on the license, used for billing reconciliation: manual, api, stripe, appsumo, gumroad, paddle, lemonsqueezy |
manual |
--yes, -y |
Skip the billing confirmation prompt | off |
pylocket licenses list¶
List licenses. Omit --app to list across every app you own.
| Option | Description |
|---|---|
--app <APP_ID> |
Filter to one application (optional) |
--type <TYPE> |
Filter by type: trial, paid |
--format <FORMAT> |
Output format: table, json |
pylocket licenses get¶
Get details for a specific license.
pylocket licenses revoke¶
Revoke a license.
pylocket licenses reset-devices¶
Clear all device activations for a license.
pylocket licenses extend¶
Extend a license expiration date. Requires an active Pro subscription — on the Free plan this returns "Active Pro subscription required to edit license expiry dates or download caps".
pylocket auth¶
Manage authentication and security settings.
pylocket auth api-keys rotate¶
Generate a new API key and invalidate the old one.
pylocket auth 2fa setup¶
Start 2FA setup. Returns a QR code URI for your authenticator app.
pylocket auth 2fa confirm¶
Confirm 2FA setup with a TOTP code.
pylocket auth 2fa status¶
Check 2FA status and remaining backup codes.
pylocket auth 2fa disable¶
Disable 2FA.
pylocket webhook¶
Configure build event webhooks for CI/CD integration.
pylocket webhook set¶
Configure a webhook URL to receive build event notifications.
Returns a webhook secret that must be saved immediately — it cannot be retrieved again. PyLocket will POST a signed JSON payload to this URL when a build completes, fails, or is rejected.
pylocket webhook remove¶
Remove the webhook configuration for an app.
pylocket webhook test¶
Send a test ping event to verify the webhook URL is reachable.
pylocket webhook status¶
Show webhook configuration and recent delivery attempts.
Environment Variables¶
| Variable | Description | Equivalent Option |
|---|---|---|
PYLOCKET_TOKEN |
Authentication token | --token |
PYLOCKET_API_URL |
API base URL | --api-url |
PYLOCKET_LICENSE_KEY |
License key for protected apps (used at runtime) | — |
PYLOCKET_FORCE_INCLUDE |
Comma-separated module names to always protect | — |
PYLOCKET_FORCE_EXCLUDE |
Comma-separated module names to never protect | — |
PYLOCKET_DEBUG |
Set to 1 to enable verbose bootstrap debug logging |
— |
Exit Codes¶
| Code | Meaning |
|---|---|
0 |
Success |
1 |
General error |
2 |
Timeout waiting for build completion |
130 |
User abort (Ctrl+C) |
Credential Storage¶
Credentials are stored at ~/.pylocket/credentials in JSON format. The file contains:
- Access token (JWT, expires after the configured TTL)
- Refresh token
- API URL
The file permissions are set to 600 (owner read/write only).
To clear stored credentials: