ggui deploy
read as.mdggui deploy provisions and wires a hosted ggui app for the current project in one pass: sign in, create the cloud app, mint a connector key, upload your local blueprint pool and app config, and write the endpoint into .env.local. It is the command form of everything the dev-loop crossover does by hand.
The command is idempotent. Each step is skipped when its gate is already satisfied, so re-running after a partial failure resumes from the first unsatisfied step instead of duplicating work.
Quick start
Section titled “Quick start”From a directory containing (or under) a ggui.json:
ggui deployOn completion it prints the app’s MCP endpoint and where the bearer landed:
ggui deploy complete.
App MCP endpoint: https://mcp.ggui.ai/apps/<appId> Bearer key: in .env.local (GGUI_MCP_BEARER)Your agent picks up the hosted endpoint on its next start — .env.local now carries both GGUI_MCP_URL and GGUI_MCP_BEARER, the same two variables the local ↔ hosted swap is built on.
Without a ggui.json anywhere up the directory tree, the command exits 1 before doing anything — it needs the manifest both to persist the appId and to know what to push.
The steps
Section titled “The steps”Steps run in this order. The first three are gated on current state; the rest always run:
| Step | Runs when | What it does |
|---|---|---|
login |
no valid session in ~/.ggui/auth.json |
Device-flow sign-in to api.ggui.ai — same flow as ggui login. |
create-app |
ggui.json has no appId |
POST /v1/apps, then persists the new appId into ggui.json. If the app was created but ggui.json could not be written, the command stops loudly with the id to add by hand — re-running without it would create a duplicate app. |
mint-key |
.env.local has no GGUI_MCP_BEARER |
Creates a connector key (named ggui deploy) and writes its one-time-reveal secret into .env.local. The secret is shown once; only the prefix is retrievable later on the connector keys page. |
push |
always | Compiles the local blueprint pool and uploads it to the app — the same operation as ggui push --app <appId>. Artifact ids are deterministic (contractHash-variantKey), so re-pushing the same pool is a no-op server-side. |
push-config |
always | Pushes the app config declared in ggui.json: the gadget catalog, app.publicEnv (keys must match GGUI_PUBLIC_APP_<NAME>), and the generation block (model, keySource). Loopback bundle URLs are rejected — a hosted app cannot fetch from 127.0.0.1. |
push-keys |
only with --push-keys |
Pushes your LLM provider API key to the app — see Provider keys below. |
wire-env |
always | Writes GGUI_MCP_URL into .env.local — unless one is already set, which is never clobbered. |
.env.local lives next to ggui.json (not necessarily the invocation directory). Both files are edited in place; other keys and comments are preserved.
The endpoint it writes
Section titled “The endpoint it writes”The per-app hosted endpoint is the bare per-app URL:
https://mcp.ggui.ai/apps/<appId>There is no /mcp suffix — that suffix is the local ggui serve convention, and appending it to a hosted app URL produces a 404. Writing the correct shape automatically is the practical reason to prefer ggui deploy over hand-editing .env.local; the trap is documented in the dev loop.
Two details of wire-env:
- First deploy — the URL comes verbatim from the
connectUrlthe backend returned atcreate-app, so it is correct for whichever environmentGGUI_API_URLpointed at. - Re-deploys — an existing
GGUI_MCP_URLis left untouched, whatever it points at. Delete the line and re-run if you want it rewritten.
Provider keys (--push-keys)
Section titled “Provider keys (--push-keys)”Apps with generation.keySource: "own" render on your model account instead of drawing down ggui credits — but only once the app actually holds your provider key. --push-keys adds that step to the deploy:
ggui deploy --push-keysThe provider is derived from ggui.json#generation.model, and the key is read from that provider’s environment variable:
| Provider | Environment variable |
|---|---|
anthropic |
ANTHROPIC_API_KEY |
openai |
OPENAI_API_KEY |
google |
GOOGLE_API_KEY (falls back to GEMINI_API_KEY) |
openrouter |
OPENROUTER_API_KEY |
bedrock routes are rejected — IAM-only, no plaintext key to push. To name the provider explicitly instead of deriving it from the model string, call the underlying command directly: ggui provider-key set --app <appId> --provider <name>.
If ggui.json declares keySource: "own" and you deploy without --push-keys, the command still succeeds but ends with a warning: cloud renders will reject until a key is pushed. See Credits, billing & BYOK for how the two key sources are charged.
What it does not do
Section titled “What it does not do”ggui deploy provisions the ggui side only — the interface layer. Hosting the agent itself (the process that talks to your users and calls ggui) is a separate concern: run it yourself, or use a hosting platform such as guuey. Nothing in this command deploys, restarts, or configures an agent runtime.
ggui deploy [--push-keys]| Flag | Purpose |
|---|---|
--push-keys |
Insert the push-keys step: push the provider API key from your environment to the cloud app. |
GGUI_API_URL (see CLI configuration) controls which backend the deploy targets; the default is production api.ggui.ai.
See also
Section titled “See also”gguiCLI overview — the full command surface, including standaloneggui pushandggui provider-key.- The dev loop — iterate locally, then cross over to hosted with the two-variable swap this command writes.
ggui login— the device-flow sign-indeployruns when needed.- Connector keys — what the minted
ggui_user_*key is and how to revoke it. - Blueprints & the cache — why uploading a matured local pool makes a fresh hosted app fast on day one.