Server CLI
gestaltd manages server lifecycle and provider releases.
Server commands
| Command | Purpose |
|---|---|
gestaltd | Local-friendly startup. Generates a config if needed and serves. |
gestaltd serve --config PATH | Start the server. Repeat --config to layer overrides. |
gestaltd serve --locked --config PATH | Start from lock state. Uses prepared artifacts when present and can materialize missing artifacts from the lockfile. Repeat --config to layer overrides. |
gestaltd serve --artifacts-dir DIR | Directory for prepared provider artifacts. |
gestaltd serve --lockfile PATH | Override the lockfile location. PATH resolves like a normal CLI path. |
gestaltd init --config PATH | Resolve published plugin sources and write lock state. Repeat --config to layer overrides. |
gestaltd init --artifacts-dir DIR | Directory for prepared provider artifacts. |
gestaltd init --lockfile PATH | Override the lockfile location. PATH resolves like a normal CLI path. |
gestaltd validate --config PATH | Validate config without serving. Repeat --config to layer overrides. |
gestaltd validate --lockfile PATH | Accept the same explicit lockfile path used by init and serve without mutating it. |
gestaltd --version | Print the server version. |
For production deployments, strongly prefer gestaltd init followed by
gestaltd serve --locked. The lockfile pins resolved provider artifacts and
verified hashes so startup cannot silently pick up new artifacts or mutate
deployment state.
Provider commands
| Command | Purpose |
|---|---|
gestaltd provider dev --path PATH | Run a local source plugin or UI bundle inside a synthesized Gestalt config. Serves /admin and any configured or inferred public UIs. |
gestaltd provider dev --config PATH | Layer supporting providers, plugins, and UI mounts on top of the synthesized local baseline. Repeat --config to merge left-to-right. |
gestaltd provider dev --remote URL --path PATH | Attach one local source plugin to an authenticated remote gestaltd session. The remote server matches by manifest source and keeps its configured auth, authorization, connections, plugin config, and host services. |
gestaltd provider dev --remote URL --config PATH | Attach every source-backed plugin in the layered config. Use repeated --config files when you need explicit local config overrides or multiple local plugins. |
gestaltd provider attach list --remote URL | List your active remote provider-dev attachments on that server. |
gestaltd provider attach show --remote URL ATTACH_ID | Inspect one active remote provider-dev attachment. |
gestaltd provider attach detach --remote URL ATTACH_ID | Detach a stuck remote provider-dev attachment owned by your authenticated principal. |
gestaltd provider validate --path PATH | Validate a local source plugin or UI bundle inside the same synthesized Gestalt config used by provider dev. |
gestaltd provider validate --config PATH | Validate the target provider together with selected supporting providers and null deletions from layered config overlays. |
gestaltd provider release --version VERSION | Build and package a provider release. Go, Python, Rust, and TypeScript source plugins default to the host platform. Pass --platform ... with os/arch[/libc] targets or --platform all for multi-platform builds. |
gestaltd provider release --output DIR | Output directory for the release archive. Defaults to dist/. |
Examples
gestaltd
gestaltd init --config ./config.yaml
gestaltd serve --locked --config ./config.yaml
gestaltd validate --config ./config.yaml
gestaltd init --config ./config.yaml --lockfile ./local/gestalt.lock.json
gestaltd serve --config ./config.yaml --lockfile ./local/gestalt.lock.json
gestaltd serve --locked --config ./config.yaml --lockfile ./local/gestalt.lock.json
gestaltd init --config ./base.yaml --config ./overrides/local.yaml
gestaltd serve --locked --config ./base.yaml --config ./overrides/prod.yaml
gestaltd provider validate --path ./plugins/support
gestaltd provider validate --path ./ui/dashboard
gestaltd provider validate --path ./plugins/support --config ./dev/support.yaml --config ./dev/local.yaml
gestaltd provider dev --path ./plugins/support
gestaltd provider dev --path ./ui/dashboard
gestaltd provider dev --path ./plugins/support --config ./dev/support.yaml --port 8080
gestaltd provider dev --remote https://gestalt.example.com --path ./plugins/support
gestaltd provider dev --remote https://gestalt.example.com --path ./plugins/support --name support
gestaltd provider dev --remote https://gestalt.example.com --remote-token <token-with-provider_dev.attach> --path ./plugins/support
gestaltd provider dev --remote https://gestalt.example.com --config ./remote.yaml --config ./local-overrides.yaml
gestaltd provider attach list --remote https://gestalt.example.com
gestaltd provider attach show --remote https://gestalt.example.com att_123
gestaltd provider attach detach --remote https://gestalt.example.com att_123
gestaltd provider release --version 0.0.1-alpha.1
gestaltd provider release --version 0.0.1-alpha.1 --platform all
gestaltd provider release --version 0.0.1-alpha.1 --platform linux/amd64,linux/arm64When repeated, --config files merge left-to-right. Maps deep-merge, later
scalar values win, lists replace inherited lists, and null deletes inherited
keys. By default, lockfiles and artifact paths stay rooted at the leftmost
config file. --lockfile overrides only the lockfile path. --artifacts-dir
keeps its existing config-relative behavior for backward compatibility.
provider dev --remote is environment-agnostic: the URL is just the remote
gestaltd instance to attach to. The local command only replaces source-backed
plugin implementations for the authenticated principal that created the session.
The remote server must opt in with server.providerDev.remoteAttach: true and
server.providerDev.attachmentState: processLocal; otherwise the command fails
before local code is attached. attachmentState: processLocal acknowledges that
remote attach v1 stores attachments in the gestaltd process that accepted the
create request. Only enable it on a single-replica server or behind sticky
routing that keeps attach creation, CLI poll/complete traffic, provider
invocations, and provider-owned UI requests for the same authenticated owner on
the same gestaltd process.
For the interactive happy path, provider dev --remote creates a short-lived
attach approval request and opens the remote server in your browser. Approving
that page with your normal browser session creates an owner-scoped attachment
only when your resolved role is allowed by the plugin’s provider-dev attach
configuration. The terminal prints a verification code, and the browser approval
page requires that code before approval succeeds. --remote-token and
GESTALT_API_KEY are the non-interactive path; those API tokens must include
permissions[].actions: ["provider_dev.attach"] for every attached plugin. If a stored CLI token exists
for the same server, the CLI first tries it for direct attach and falls back to
browser approval when it is not attach-scoped. Stored CLI tokens are not sent to
a different remote URL, including a different path prefix on the same host.
With --remote URL --path PATH and no --config, the local command sends the
manifest source and the local implementation only; the remote server chooses
the configured plugin with the same manifest source and preserves that
remote plugin’s config. If multiple remote plugins share the same source, or the
manifest has no source, pass --name to choose the configured remote plugin.
All non-local plugins and remote host services continue to resolve through the
remote instance.
After browser approval or attach-token authentication, the remote creates an
attachment and the CLI uses the returned attachId plus a one-time dispatcher
secret for poll/complete traffic. The dispatcher secret is not shown by list/get
diagnostics and is not needed for owner cleanup detach. Use
gestaltd provider attach list --remote URL,
gestaltd provider attach show --remote URL ATTACH_ID, and
gestaltd provider attach detach --remote URL ATTACH_ID to inspect or clean up
attachments owned by your authenticated principal. These diagnostic commands use
--remote-token, GESTALT_API_KEY, or a matching stored Gestalt CLI
credential, and they do not require provider_dev.attach because they cannot
create a new attachment.
API-token attach creation requires an explicit token action permission:
{
"name": "slack local dev",
"permissions": [
{
"plugin": "slack",
"actions": ["provider_dev.attach"]
}
]
}Normal provider scopes and operation permissions do not grant remote attach, and
provider_dev.attach does not grant normal invocation access. Subject-owned API
tokens are not accepted for remote attach v1.
When --config is present, source-backed plugin entries in the layered local
config are treated as explicit local overrides. Their plugin config is sent to
the remote session instead of inheriting the remote server’s config. Remote mode
allows missing local environment substitutions while loading config so unrelated
deploy-only env vars do not block attach.
Remote mode tunnels plugin RPC, catalog, post-connect, host-service calls, and
plugin-owned UI assets for mounted UIs that already exist on the remote server.
Raw GraphQL surfaces are not tunneled in v1.
For TypeScript source plugins, provider dev installs dependencies with
bun install when a package.json is present and node_modules is missing.
Source UI release builds use the same bootstrap for Bun-managed build workdirs
before release.build.command when dependencies are missing.
See Configuration for the relationship between init, serve --locked, and validate.