Skip to Content
ReferenceServer CLI

Server CLI

gestaltd manages server lifecycle and provider releases.

Server commands

CommandPurpose
gestaltdLocal-friendly startup. Generates a config if needed and serves.
gestaltd serve --config PATHStart the server. Repeat --config to layer overrides.
gestaltd serve --locked --config PATHStart 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 DIRDirectory for prepared provider artifacts.
gestaltd serve --lockfile PATHOverride the lockfile location. PATH resolves like a normal CLI path.
gestaltd init --config PATHResolve published plugin sources and write lock state. Repeat --config to layer overrides.
gestaltd init --artifacts-dir DIRDirectory for prepared provider artifacts.
gestaltd init --lockfile PATHOverride the lockfile location. PATH resolves like a normal CLI path.
gestaltd validate --config PATHValidate config without serving. Repeat --config to layer overrides.
gestaltd validate --lockfile PATHAccept the same explicit lockfile path used by init and serve without mutating it.
gestaltd --versionPrint 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

CommandPurpose
gestaltd provider dev --path PATHRun 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 PATHLayer 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 PATHAttach 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 PATHAttach 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 URLList your active remote provider-dev attachments on that server.
gestaltd provider attach show --remote URL ATTACH_IDInspect one active remote provider-dev attachment.
gestaltd provider attach detach --remote URL ATTACH_IDDetach a stuck remote provider-dev attachment owned by your authenticated principal.
gestaltd provider validate --path PATHValidate a local source plugin or UI bundle inside the same synthesized Gestalt config used by provider dev.
gestaltd provider validate --config PATHValidate the target provider together with selected supporting providers and null deletions from layered config overlays.
gestaltd provider release --version VERSIONBuild 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 DIROutput 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/arm64

When 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.