ptkl forge
Build, bundle, deploy, and manage Forge applications from the command line.
Overview
ptkl forge is the primary command for working with Forge apps during development. It can start
a local dev server, produce production bundles, upload them to the platform, and manage published
versions. It supports three app types:
- Platform apps — multi-view UMD/ESM bundles that run inside the Protokol dashboard. Can expose individual views and services publicly.
- Public apps — standard SPAs with optional SSR that are served on their own domain
- Service apps — headless API-only apps with no UI, accessed exclusively through service domains
Build configuration is defined in a ptkl.config.js file at the root of
your app.
Subcommands
| Subcommand | Description |
|---|---|
bundle |
Build and optionally upload a Forge app |
dev |
Start a Vite dev server for local development |
list |
List all Forge apps in the current project |
remove-version |
Remove a published version |
install |
Run the app's install lifecycle script against the active profile |
uninstall |
Run the app's uninstall lifecycle script against the active profile |
services |
List services declared by a deployed Forge app |
variables get\|set\|add |
Manage a deployed Forge app's variables |
run |
Invoke a deployed Forge service app |
domains add\|verify\|refresh\|remove |
Manage custom domains for a public Forge app |
Note
bundle/dev/list/install/uninstall/remove-version operate on your local app
directory and its ptkl.config.js. services/variables/run/domains operate on an
already-deployed app by reference (name or uuid) and talk to the platform's Forge/appservice
API directly — you don't need to be inside the app's directory to use them.
ptkl forge bundle
Build the app from ptkl.config.js and produce a deployable bundle. Optionally uploads the
bundle to the platform in one step.
Options
| Option | Description |
|---|---|
-p, --path <path> |
Path to the app directory (defaults to current directory) |
-u, --upload |
Upload the bundle to the platform after building |
Examples
# build only
ptkl forge bundle --path ./my-app
# build and upload
ptkl forge bundle --path ./my-app --upload
For platform and service apps, the bundler produces UMD/ESM modules for each view defined
in the config, plus compiled service scripts in services/. For public apps, it builds a
standard SPA and optionally an SSR renderer if ssrRenderer is configured.
ptkl forge dev
Start a Vite development server with platform environment variables injected. Use this for local development with hot module replacement.
Options
| Option | Description |
|---|---|
-p, --path <path> |
Path to the app directory (defaults to current directory) |
Example
The dev server reads your active profile to inject the correct API host, project, and authentication token into the development environment.
ptkl forge list
List all Forge apps in the current project.
ptkl forge remove-version
Remove a specific published version of a Forge app.
Options
| Option | Description |
|---|---|
-r, --ref <ref> |
App reference |
-v, --version <version> |
Version to remove |
Example
ptkl forge install
Run the app's install lifecycle script against the active profile. This executes the install script on the target environment, provisioning any resources the app defines (components, roles, functions, etc.).
Options
| Option | Description |
|---|---|
-p, --path <path> |
Path to the app directory |
--env <env> |
Target environment (dev or live) |
-b, --bundle |
Bundle the app before running the script |
--var <key=value> |
Set one app variable for the run. Repeatable. |
--vars <list> |
Set several at once: 'KEY=value;KEY2=value2'. Repeatable. |
--vars-file <path> |
JSON file of variables — flat, or env-keyed { "dev": {...}, "live": {...} } |
Example
Injecting Variables
On the platform, install scripts read the app's stored
variables for the environment being installed through the
$variables global. Locally there is no app record to read from, so pass them on the
command line:
ptkl forge install --path ./my-app --env dev \
--var WEBHOOK_URL=https://staging.example.com/hook \
--var MAX_RETRIES=3 \
--var DEBUG=true
Values are parsed as JSON when they are valid JSON, and kept as plain strings otherwise
— so MAX_RETRIES=3 arrives as the number 3, DEBUG=true as the boolean true, and
WEBHOOK_URL=https://… as a string. Only the first = splits the pair, so values may
contain =. Use --vars to pass several in one flag:
ptkl forge install --path ./my-app --env dev --vars 'WEBHOOK_URL=https://staging.example.com/hook;DEBUG=true'
For a set you reuse between runs, keep them in a JSON file. A flat file applies to every
environment; an env-keyed file mirrors how variables are stored on the app, and the
matching set is selected per environment — which matters when you omit --env and the
script runs for both dev and live:
{
"dev": { "WEBHOOK_URL": "https://staging.example.com/hook", "DEBUG": true },
"live": { "WEBHOOK_URL": "https://example.com/hook", "DEBUG": false }
}
Sources merge, with later ones overriding earlier: --vars-file, then --vars, then
--var. This lets you keep a base file and override a single value for one run:
The run prints which variable names were injected. Variables not passed are simply
absent from $variables, exactly as on the platform when the app has no value stored
for them.
These variables are local only
Flags affect the local dry run only — they do not write anything to the app's
stored variables. Use ptkl forge variables set to change
what a deployed app sees.
ptkl forge uninstall
Run the app's uninstall lifecycle script against the active profile. This executes the uninstall script on the target environment, tearing down any resources the app provisioned during installation.
Options
| Option | Description |
|---|---|
-p, --path <path> |
Path to the app directory |
--env <env> |
Target environment (dev or live) |
-b, --bundle |
Bundle the app before running the script |
--var <key=value> |
Set one app variable for the run. Repeatable. |
--vars <list> |
Set several at once: 'KEY=value;KEY2=value2'. Repeatable. |
--vars-file <path> |
JSON file of variables — flat, or env-keyed { "dev": {...}, "live": {...} } |
Example
Variables work exactly as they do for
ptkl forge install — uninstall scripts read the same
$variables global, so cleanup logic that depends on a variable can be tested the same
way:
ptkl forge services
List the services declared by a deployed Forge app.
| Argument | Description |
|---|---|
<ref> |
App reference (uuid or name) |
Example
ptkl forge variables
Manage a deployed Forge app's variables (the values injected into its services/scripts at runtime — see Variables).
ptkl forge variables get
Get all variables for a Forge app.
ptkl forge variables set
Replace all variables for a Forge app — a full overwrite, not a merge. Any existing variable
not present in --data is removed.
| Option | Description |
|---|---|
-d, --data <json> |
Full variables object as a JSON string (replaces all existing variables) (required) |
ptkl forge variables add
Add or update a single variable on a Forge app — merges into the existing variables rather than replacing them.
| Argument | Description |
|---|---|
<ref> |
App reference (uuid or name) |
<key> |
Variable key |
<value> |
Variable value — parsed as JSON if it's valid JSON, otherwise kept as a string |
ptkl forge variables add my-app FEATURE_X true
ptkl forge variables add my-app WELCOME_MESSAGE "Hello!"
ptkl forge run
Invoke a deployed Forge service app. A bare name runs a service on the current app; a PRN runs a service on another app.
| Argument/Option | Description |
|---|---|
<service> |
Service name (current app) or PRN: prn:forge:{ref}:service/{name} |
-b, --body <json> |
Request body as a JSON string, sent as the POST payload |
-q, --query <json> |
Query params as a JSON object string |
-H, --headers <json> |
Extra request headers as a JSON object string |
Examples
# run the current app's own service
ptkl forge run send-welcome-email --body '{"userId":"u_123"}'
# run another app's service via PRN
ptkl forge run 'prn:forge:billing-app:service/generate-invoice' --body '{"orderId":"o_456"}'
See Services for the service execution model.
ptkl forge domains
Manage custom domains for a public Forge app.
ptkl forge domains add
Register a custom domain. Returns a DNS TXT validationKey you publish on the domain to prove
ownership.
ptkl forge domains verify
Verify a custom domain's DNS TXT record against its validation key.
ptkl forge domains refresh
Refresh an expired validation key for a domain that hasn't been validated yet.
ptkl forge domains remove
Remove a custom domain.
See Custom Domains for the full domain-verification flow.
Typical Workflow
# 1. Develop locally with hot reload
ptkl forge dev --path ./my-app
# 2. Test install script
ptkl forge install --path ./my-app --env dev --bundle
# 3. Build and deploy
ptkl forge bundle --path ./my-app --upload
# 4. Verify
ptkl forge list
# 5. Configure runtime variables and invoke a service
ptkl forge variables set my-app --data '{"API_URL":"https://api.example.com"}'
ptkl forge run send-welcome-email --body '{"userId":"u_123"}'
# 6. Set up a custom domain for a public app
ptkl forge domains add my-app app.example.com
ptkl forge domains verify my-app app.example.com
See Also
- App Manifest —
ptkl.config.jsconfiguration reference - Services — service execution model and scripting
- Variables — app variables reference
- Lifecycle Scripts — install and uninstall scripts
- Custom Domains — domain verification flow for public apps
- Toolkit Overview — all available toolkit commands