Skip to main content
An SDK is a typed package containing only the services and operations one product needs. Authentication, retries, pagination, and provider quirks stay in Fused. Your application code gets methods. By default, fused-cli init also hosts the same App through MCP and REST. Use --sdk when you want the package without hosted MCP. Both choices keep one App identity and immutable version for every method they enable.

Create or update from a goal

Use fused-cli describe --kind sdk to draft an SDK or add capabilities to an existing local App, then review the proposal before apply.

Create all three delivery methods

This selects all operations from Linear and Slack and creates one kind: sdk App with a generated package, a hosted MCP server, and REST execution. The selected scope, version, and token are shared. You can express the same scope in YAML with a nested MCP description:
Use --description to author the MCP summary. When omitted, init derives one from the App name. The package download, hosted MCP URLs, and REST version ID all come from this single apply. The App details page shows the MCP URLs later.

Create an SDK only

For each service, fused-cli init reuses an enabled workspace version or pins the latest public Registry version. Bare services automatically select all physical operations without opening an operation picker. This works in terminals and with --no-input. If activation is needed, init shows one combined confirmation and applies the workspace change under its own receipt. It then builds and validates the SDK candidate in memory and plans the SDK. Missing credentials open the init credential review: set them up, open the bucket in your browser, recheck, proceed anyway, or cancel. Setup and recheck refresh the plan. A successful plan and completed review allow init to create .fused/sdks/support-sdk.yaml, apply the SDK, and download the package. Workspace and SDK changes retain separate receipts.
Adding a service saves its executable contract without archiving SDK generation input. SDK planning acquires that input when you select the service for a generated package, and accepts it only if the saved runtime contract and source revision still match. If they have changed, generated SDK init prints each exact service@version as it refreshes that snapshot and retries the unchanged plan once. It does this deterministically with --no-input too. It never invents a pin, selects another version, or bypasses Registry retention. A failed refresh or retry creates no app config or app receipt, while any completed exact refresh remains explicit. See Recover without guessing for the failure boundaries.
The equivalent YAML uses select_all: true for both services. Init resolves this to explicit operation lists before publishing the immutable App version:
Each service key is the canonical Registry slug selected by the CLI. The provider versions shown here are illustrative; init writes the concrete versions it resolves. operations and select_all: true are alternatives. Exactly one is required per service, never both and never neither.

Choose services and operations

Use one quoted --service '<service>[@<version>][=<operationId>,...];...' value with init or extend. Semicolons separate services, and commas separate operations within a service. Quote the value so your shell does not interpret semicolons as command separators. To find operation IDs before creating an App, use fused-cli service operation list <service> --registry. Repeated service flags, comma-separated bare services, and the older --operation and --select-all flags remain supported. Explicit legacy operation lists, event selections, or imported MCP capability flags keep their selected scope without adding all physical operations.

init fills in the routing for you

Some provider hosts are templated — https://api-{app_id}.sendbird.com needs an app_id before it can be called. init spots those and writes the injection itself:
It reports how many it added. Re-running it never overwrites an injection you wrote yourself.
That value is a reference. If init stops because the matching bucket value is missing, create it with fused-cli bucket value set, then rerun init. The app config is not written until its plan succeeds.

Find the downloaded package

SDK mode plans, applies, and downloads the generated package to fused-sdks/support-sdk. If a later transfer needs to be retried without replaying apply, run:
The first successful initialization or apply prints the SDK execution token once. Capture it immediately — an idempotent apply will not show it again, and it is never written to the config, the receipt, or CLI state.

Need more control?

The initializer composes the ordinary plan and apply functions; it does not bypass them. Use the advanced controlled workflow when you want independent review steps, structured CI output, offline validation, custom receipt paths, or separate retry boundaries.

Skip the package

Some apps call the centralized API over REST and never import a generated package. Use API mode:
API mode is not another resource type. It writes the same kind: sdk config with package generation disabled:
Nothing else changes. Init applies the version and prints a concrete REST request template for POST /v1/apps/{app_id}/executions. Replace the operation placeholder when all operations were selected and provide that operation’s required input. The app remains describable with fused-cli app openapi. Only the package and download are absent: app apply --json reports generation.status: "skipped", and --download is refused before anything is applied. Flipping the field edits the file, which moves the source hash, so switching between the two needs a version bump like any other scope change.

Point the client at Fused

The generated TypeScript client takes grpcUrl, and Python uses grpc_url. Go uses Config.EngineURL for its gRPC address and Config.HTTPURL for hosted Unified App calls. Set the gRPC address explicitly for physical service calls; it is separate from the HTTP address used by the CLI.
TypeScript and Python resolve the target in this order, first non-empty wins:
  1. grpcUrl / grpc_url passed to the constructor
  2. FUSED_ENGINE_GRPC_URL
  3. FUSED_ENGINE_URL
  4. http://127.0.0.1:50051
Step 3 is the one that catches people. FUSED_ENGINE_URL is the HTTP management URL the CLI uses. If it is set in your environment and you do not pass grpcUrl, the client speaks gRPC at the REST port and the server answers HTTP 405. Set FUSED_ENGINE_GRPC_URL explicitly and the ambiguity goes away.
Each FusedSDK instance opens one gRPC channel that every service on it shares, so there is no per-service connection cost.

What is in the package

Alongside the typed client, generation writes two files from your actual selections: Both are derived from the generated source and validated against it, so the methods they demonstrate exist. Neither is a substitute for this site — they describe your package, not the platform.

Flags

fused-cli init

Omit --sdk, --rest, and --mcp to create the combined App in a terminal or automation. Creating never replaces an existing file. Init writes one App config and any workspace config needed for activation; it does not create three separate Apps. Generated Go packages require Go 1.24 or later. They include a go.mod and a README with the exact module path and local installation commands. See install the package. The same service selectors work in a terminal and with --no-input: bare services select all operations, and inline lists select only those operations. Add a method flag only when you want a single method. Use the explicit plan/apply path when automation needs structured results.

fused-cli extend

Use extend after creation. It finds the existing YAML and infers the app’s delivery configuration, so you do not repeat --sdk, --rest, or --mcp:
The same file is updated additively. Use --service 'slack' to add all Slack operations, or group several services with semicolons. Omitted provider versions inherit existing App pins. Running extend support without selection flags in a terminal opens the operation picker for existing services. An idempotent repeat keeps its version. A real change to a stable SemVer version advances to the next minor version and is shown in terminal confirmation; --no-input uses the same deterministic inference. Pass --version <successor> to override it. Prerelease and non-SemVer versions always require that explicit flag.

Adjust the selection

The service slug comes first, then as many operation IDs as you want:
app operation add accepts --interactive to pick from a list, and --apply (or --download, which implies it) to push the change straight through.

Choosing auth

auth.type picks a Registry-declared scheme — basic, bearer, api_key, oauth, oidc, or mtls — and auth.name disambiguates two schemes of the same type.
Leave it out and Fused picks each operation’s first provider-declared alternative. connect.scopes is a ceiling: an application can request fewer scopes per user, never more. The operation’s imported security requirements are authoritative, and they are an ordered OR of ANDs: alternatives are OR, schemes within one alternative are AND, and an empty alternative permits anonymous execution.
Do not collapse an AND alternative down to the one convenient scheme. A single selector never replaces a secondary credential such as an mTLS certificate or an additional API token — planning reports readiness for every scheme in the chosen AND set.
Where a service declares several named schemes of one type, carry both the type and the exact name. Never rely on declaration order. Credentials themselves never appear in this file. They resolve from the bucket when a connection starts or an operation dispatches. Each service resolves through its own bucket: override when one is set, otherwise it falls back to the top-level bucket::
Webhook secret references still resolve through the top-level bucket, and an auth.ref may only join two services that resolve to the same bucket.

Use a Managed service

For supported OAuth services, select a Fused Managed App instead of storing your own client pair. Your Fused workspace still owns each user’s connection. Add the managed reference before publishing, or publish a new version when changing an existing app.

Store your own credentials

Terminal plans can securely fill readiness warnings and retry once, but setup is optional. Automation receives structured credential_readiness metadata and may pre-provision the exact bucket. If setup is deferred, the first affected call returns bucket_credentials_missing with the exact safe command.