Project administration
These command groups operate the cloud resources a project’s agents run
against. They need a session from
introspection login, and a few of them need a member
role an API key cannot hold — each section says so where it applies.
This page is command reference. Use Agent development lifecycle for the ordered local, staging, and production workflow.
Choose the resource that owns the change:
| You need to | Go to |
|---|---|
| Confirm or override the active project | Projects and --project |
| Create an application credential or identity integration | API keys and applications |
| Supply endpoints, variables, or secrets to a runtime | Bindings |
| Register source an agent may work on | Repositories |
| Connect a customer’s provider account | Connectors |
| Create, inspect, or operate a deployed version | Runtimes |
Orient yourself first — where you are logged in, and what the project holds:
introspection whoami
introspection runtimes list -o table
introspection api-keys listProject and access
Projects and —project
There is no projects command group: projects are created in the dashboard,
and the CLI works inside the project you selected on the login approval
page. Every project-scoped command resolves a project before it runs. The
order is:
- an explicit
--project(-p) on the command, with a project slug or id, - otherwise
INTROSPECTION_PROJECTfrom the environment, - otherwise the project selected when you logged in.
Run introspection whoami to see the active login and its project, and
introspection login again to select a different one.
bindings and api-keys use the login project. Both always act on the
project you logged in to and ignore INTROSPECTION_PROJECT. If the variable
is set to a different project they print a note on stderr and continue against
the login project — so a binding or key you believed you had scoped elsewhere
may have landed in the login project. Neither family accepts --project
either: changing project for them means a new login, not a per-command
selector. When working across projects, log in to the intended project before
running them, and treat that stderr note as a signal to stop rather than
something to override.
Connector commands have their own per-command project rules. See Connectors before combining authorization and binding commands.
API keys and applications
api-keys manages project API keys for application/SDK callers. applications
manages application identities, service-account secrets, identity-provider
federations, and assertion keys. Neither can request the member-only remotes
capability used by dev.
Project API keys are environment-bound credentials for SDK callers. create writes the one-time secret to a new mode-0600 file, acknowledges it only after the write succeeds, and never prints the secret:
introspection api-keys create \
--name staging-sdk \
--environment staging \
--member-id <agent-member-id> \
--secret-file ./staging-api-key
introspection api-keys create --secret-file ./ci-key --expires-at 2026-12-31T00:00:00Z
introspection api-keys list
introspection api-keys list --expiring
introspection api-keys update --key <key-id> \
--name staging-sdk-2 \
--member-id <agent-member-id>
introspection api-keys revoke --key <key-id>--name defaults to cli and --environment defaults to production, so
--secret-file is the only required flag on create. --expires-at takes an
RFC 3339 timestamp; omit it for a key with no fixed lifetime. list returns
active, non-expired keys; add --expiring to include keys with a future expiry
or a grace-period revocation.
If the file write succeeded but acknowledgement failed, retry api-keys acknowledge --key <key-id>. Use revoke --expires-in <seconds> for a grace period.
Applications are organization-managed callers. Choose the type and environment that match the trust model, retain its id, then manage the application and its subordinate auth resources:
introspection applications create --type spa --name web \
--environment staging \
--redirect-uri https://app.example.com/callback \
--allowed-origin https://app.example.com
introspection applications create --type native --name desktop
introspection applications create --type jwks --name backend
introspection applications create --type service-account --name worker \
--agent-member-id <agent-member-id> \
--allowed-scope runtimes
introspection applications list
introspection applications get <application-id>
introspection applications update <application-id> --name web-staging
introspection applications delete <application-id>--environment is set at creation and defaults to production. A service
account acts as --agent-member-id; when omitted, the Control Plane uses the
organization’s system agent. update can replace that agent, or replace or
clear redirect URIs, allowed origins, and allowed scopes.
Manage the auth resources appropriate to the application type:
# Service-account client secrets. The created secret is shown once.
introspection applications secrets create --app <application-id>
introspection applications secrets list --app <application-id>
introspection applications secrets revoke --app <application-id> \
--secret <secret-id> [--expires-in <seconds>]
# Direct JWKS identity federation.
introspection applications idps create --app <application-id> \
--issuer https://issuer.example.com \
[--audience-client-id <audience>]
# Brokered SPA federation, which also needs the OAuth client.
INTROSPECTION_IDP_CLIENT_SECRET='...' \
introspection applications idps create --app <application-id> \
--issuer https://issuer.example.com \
--provider supabase \
--client-id <oauth-client-id> \
--scope openid --scope profile --scope email \
--wait
introspection applications idps list --app <application-id>
introspection applications idps delete --app <application-id> --idp <idp-id>
# Assertion signing keys.
introspection applications keys create --app <application-id>
introspection applications keys list --app <application-id>
introspection applications keys delete --app <application-id> --key <key-id>A jwks application needs only --issuer. A brokered spa application also
needs --provider (for example supabase, auth0, okta, or zitadel),
--client-id, and --client-secret — pass the secret through
INTROSPECTION_IDP_CLIENT_SECRET to keep it out of shell history. --scope is
repeatable and defaults to openid profile email, and --wait polls until the
brokered federation finishes provisioning.
Protect the one-time service-account secret before persisting it; later secrets list never returns the value. Creating applications and federations can require an owner/admin member login.
Runtime configuration
Bindings
introspection bindings is a CLI umbrella over three flat Control Plane resources, plus one composed read over two of them. It is not a separate /v1/bindings API:
| Command group | Resource |
|---|---|
bindings endpoints | llm, api, and mcp upstream targets and their egress header templates. |
bindings variables | Sandbox environment variables. |
bindings credentials | Write-only secrets referenced from endpoint headers. |
bindings mcp | Not a fourth resource: a view composing recipe MCP declarations with the kind=mcp endpoints and credentials that back them. |
Each resource has its own verbs:
introspection bindings endpoints list|get|create|update|delete
introspection bindings variables list|create|update|delete
introspection bindings credentials list|get|create|update|delete
introspection bindings mcp list|connect|disconnectVariables have no get: list already returns their values, while endpoint and
credential reads deliberately withhold header values and secrets.
Endpoints, variables, and credentials can be project-wide, runtime scoped (--runtime <slug-or-group-id>), or scoped to one exact runtime version (--runtime-id <version-id>). On those three, --environment is optional and takes shared, development, staging, or production. Name a lane to scope the row to it, or shared to write the row that applies to every lane; on a list, omitting the flag leaves the listing unfiltered, while shared narrows it to the rows that carry no lane of their own.
bindings mcp list takes a different --environment: required, and only the three concrete lanes (development, staging, production). There is no shared there, because it resolves one runtime version’s effective connections.
--runtime names the stable runtime and --runtime-id one immutable version of it. Both are resolved server-side, so a version id passed to --runtime is rejected and told which flag takes it.
Endpoint create/update accepts a complete JSON or YAML document as positional @FILE (or @- for stdin); flags override document fields. Bindings shows a full endpoint document and the credential it references.
Keep secret values out of shell arguments: --from-env reads the value from an environment variable, and --from-file (a mode-0600 file) and --from-stdin are the other secret-safe sources. Credential reads expose has_secret and secret_set_at, never the value. Endpoint reads return the unresolved ${NAME} template and referenced credential names, never an expanded secret.
MCP connections
bindings mcp connect creates or upserts an endpoint for a stable recipe MCP ID.
list resolves the recipe from the selected runtime and combines its
declarations with applicable endpoints, including missing and stale bindings.
connect does not read the recipe; confirm the declaration with list after
creating the endpoint.
introspection bindings mcp connect \
--mcp-server-id linear \
--name Linear \
--endpoint-url https://mcp.example.com/mcp
introspection bindings mcp list \
--runtime <runtime-slug-or-group-id> \
--environment production
introspection bindings mcp disconnect --endpoint <endpoint-id>list requires --environment and either --runtime or --runtime-id.
disconnect deletes the endpoint row named by bindings mcp list.
To use a connector’s authorized connection, add --connector <id-or-slug> to
bindings mcp connect. Endpoint create and update also accept --connector
for API and MCP endpoints. The connector must belong to the project and allow
the endpoint host. Its reference is stored as metadata.connector_id; the
provider token stays outside endpoint headers. A linked connector cannot be
combined with --authorized-application or a stored Authorization header.
See connector setup for authorization followed by
binding and discovery. --connector chooses the provider definition; it does
not select an arbitrary stored connection for every task.
connect checks that --mcp-server-id is well formed, not that the recipe
declares it. A mistyped id creates an endpoint that no declaration will ever
match. Confirm the connection afterwards with bindings mcp list for the same
runtime and environment and check the declared field on the row.
Repositories
introspection repositories registers the source repositories a project’s
runtimes may work on:
introspection repositories list
introspection repositories add <owner/name>
introspection repositories remove <owner/name-or-id>Registration is what makes a repository addressable. A sandbox asks for its
GitHub credential by repository id (POST /v1/repositories/{id}/access-token
takes no slug), so a repository that is not registered cannot be named in any
request. It is not, by itself, a grant: a recipe still has to list the
repository under runtime.github.repositories, and a task still has to ask for
it. See Work with repositories.
You often will not need add first. Creating a recipe from a GitHub selector — which runtimes create and the dashboard both do — registers the repository
its recipe is pinned in, so this command is for the additional repositories an
agent works on.
add takes a full GitHub URL as readily as an owner/name slug, resolves the
organization’s GitHub installation itself, and is idempotent — a repeat returns
the existing registration. Pass --integration-id only if the organization has
more than one active GitHub installation, which is refused rather than guessed.
remove accepts either the id or the owner/name a recipe grant would name.
add and remove need a member session from introspection login.
repositories:write is a member-role scope, so an API key cannot register a
repository — keys top out at repositories:read, which covers list.
Removing a repository does not edit any recipe, but it is refused with 409
repository_in_use while a recipe is still pinned in it — including the one
runtimes create registered it for. A recipe that merely grants it resolves
to nothing, and its tasks launch without that checkout rather than failing.
Connectors
introspection connectors manages provider definitions and their authorized
connections. Connector arguments accept an ID or slug. See
Connectors for a complete setup example.
Project selection depends on the command:
| Commands | Project selection |
|---|---|
authorize, authorize-url, describe, test | --project (-p), then INTROSPECTION_PROJECT, then the login project. |
list, create, get, update, delete, and every connections command | The login project. These commands do not accept --project. |
Bindings also use the login project. Run introspection whoami before a setup
that combines authorization and binding commands, and log in to the intended
project before creating its connector or endpoint.
Create and update
The resource commands are:
introspection connectors list
introspection connectors create --name <text> --provider <slug> --auth-mode <mode>
introspection connectors get <connector>
introspection connectors update <connector> --name <text>
introspection connectors delete <connector>create accepts --slug, --environment, repeatable --scope and
--api-host, and the provider’s OAuth settings. The authentication mode uses
CLI spelling such as oauth-stored or client-credentials. If the slug is
omitted, it is derived from the name; creating the same slug returns the
existing connector.
For custom OAuth, use --issuer to discover the authorization and token
endpoints. An issuer with dynamic client registration can supply the client
credentials too. Otherwise, pass --client-id and the required
--client-secret at creation. You can also set --authorization-endpoint
and --token-endpoint explicitly. The CLI does not apply the dashboard’s
provider templates when you select a provider slug, so include the endpoints,
scopes, and API hosts your integration requires. See
OAuth discovery for client
registration and PKCE requirements.
A Pipedream connector requires --provider pipedream,
--auth-mode client-credentials, --pipedream-project-id, --client-id, and
--client-secret. The Pipedream example
shows creation followed by application authorization.
update can change the name, scopes, API hosts, status, agent member, webhook
URL, client secret, or signing secret. It cannot change the provider, slug,
environment, authentication mode, client ID, or OAuth endpoints. Omitted
secrets remain unchanged; supplying a secret replaces it. Connector resource
responses never return client or signing secrets.
For a customer-owned Slack app, create the connector with its client ID first.
Register {control-plane-host}/v1/webhooks/slack/{connector-id} with the
provider, then use update --webhook-url ... --signing-secret ... to store the
remaining registration settings. For the organization Slack installation used
by Operator, see Use Operator in Slack.
Authorize an account or generate a link
Choose the command based on who completes authorization:
| Command | Behavior |
|---|---|
connectors authorize <connector> | Requires an interactive terminal, opens the provider in a browser, and waits on a local callback. It emits completion status and connection_id to stdout. |
connectors authorize-url <connector> | Returns authorize_url, expires_in, and expires_at immediately. It does not open a browser or wait. Use it in scripts and customer consent flows. |
For example, authorize an account yourself, or generate a link to hand to its owner:
introspection connectors authorize support-tools
introspection connectors authorize-url support-tools --expires-in 1hInteractive authorization prints the URL and progress on stderr. If opening the
browser fails, you can open that URL yourself. The command waits for the link’s
lifetime, capped at 30 minutes, and reports a failure if completion does not
arrive. Pipedream caps the link lifetime at four hours. authorize-url --query authorize_url selects the URL through the normal output system.
Both commands accept the following options:
| Flag | Effect |
|---|---|
--runtime <slug-or-group-id> | Selects the runtime required by Slack, Linear, and Pipedream. Read requires_runtime from the connector rather than treating every required runtime as an inbound provider. |
--app <slug> | Selects the downstream Pipedream application, such as notion. Required for Pipedream authorization. |
--allow-progressive-scopes | Allows a supported Pipedream application to grant a subset of its configured permissions. Defaults to false. |
--subject app|user|person | Selects the credential subject. Defaults to app; the authenticated principal determines a user or person subject. |
--user-id <id> or --anonymous-id <id> | Records your customer as the grant author through created_by_member_id. The flags are mutually exclusive and do not override credential ownership. |
--expires-in <duration> | Sets the link lifetime from 60 seconds to one day. Accepts seconds or units such as 30m, 1h, and 1d; defaults to ten minutes. Pipedream caps the returned lifetime at four hours. |
Only authorize-url accepts --return-url. Use it when another application
owns the completion page. The URL must be allowed by the deployment’s redirect
policy. Interactive authorize owns its callback instead.
Each authorization request creates a fresh, single-use link. Generate one per
recipient and attempt. Asserting a new customer identity can return 409 when
it would exceed the organization’s member limit.
Inspect and test MCP access
Create the endpoint binding before testing it. For a connector-backed MCP
endpoint, pass --connector to bindings mcp connect, then inspect the binding
for the intended runtime and environment.
introspection bindings mcp list \
--runtime support-agent \
--environment development
introspection connectors describe support-tools
introspection connectors test support-tools --connection <connection-id>
introspection connectors describe support-tools --connection <connection-id>describe without a connection emits a Pi MCP declaration using the connector
slug as the server ID and * as its tool selection. It does not prove that an
endpoint or usable authorization exists. With --connection, it performs MCP
discovery and returns the ID, URL, and discovered tools. test requires
--connection and returns the discovery results, including ok,
connection_id, protocol and server information, tool count, and tool names.
Neither discovery command prints the token.
The current lookup requires exactly one MCP endpoint in the project with a server ID matching the connector slug. The commands have no runtime or environment selector, so several valid environment bindings produce an ambiguity error. Keep those bindings and verify the intended runtime through a representative task.
The discovery request uses the broker’s default app subject. The selected
connection must belong to that subject; user and workspace connections are not
interchangeable with an app connection. Pipedream’s client_credentials mode is
not served by this token broker. A discovery test therefore does not cover every
connector runtime flow or prove authorization for every tool operation.
Manage stored connections
introspection connectors connections list --connector <connector>
introspection connectors connections get <connection-id> --connector <connector>
introspection connectors connections create --connector <connector> @FILE
introspection connectors connections token --connector <connector> [--connection <connection-id>] [@FILE]
introspection connectors connections revoke <connection-id> --connector <connector>connections create reads an already-obtained provider token from a JSON or
YAML document. Use @- for stdin. The document requires access_token and can
include subject_type, scopes_granted, refresh_token, and
token_expires_at. Registered connections currently support app and user
subjects. A user connection is owned by the authenticated member.
connections token returns the token broker’s response, which can contain a
provider credential. Use test or describe --connection when you only need to
check discovery. The optional token request document accepts subject (app,
user, or person), action, and requested_permissions. The --connection
flag supplies an exact connection_id; without one, the broker resolves the
connection from the authenticated subject. Exact selection never overrides the
connector and subject ownership checks.
For person_authorized, the broker can return authorization_pending, a
mission ID, and an approval URL. Approval must cover the requested action and
permissions before retrying the token request.
connections revoke removes the provider credential and its approvals.
Reconnecting requires a fresh authorization link. delete and
connections revoke need a member session from introspection login, because
connectors:delete is not an API key capability. A 404 with “Connectors are
not enabled” means the deployment disabled the feature.
Runtimes
Runtime versions begin with the recipe manifest:
introspection runtimes create --manifest .introspection/<name>.yaml
introspection runtimes list [--runtime <slug-or-group-id>]
introspection runtimes get <runtime-id>
introspection runtimes versions <runtime-id>
introspection runtimes pin <runtime-id> [--environment staging]
introspection runtimes pin <runtime-id> --sha <sha>
introspection runtimes pin <runtime-id> --branch <main|pr/N>
introspection runtimes unpin <runtime-id>
introspection runtimes update <runtime-id> --yank [--reason <text>]
introspection runtimes update <runtime-id> --unyank
introspection runtimes delete <runtime-id>create reads the canonical manifest and Git checkout, creates the immutable recipe pin through the active GitHub integration, and bootstraps the first runtime. The manifest filename is the runtime-group slug. Later versions remain Git-driven.
The first bootstrap must come from a reviewed production commit. Before
running create, make sure:
- the worktree has no uncommitted changes;
mainis checked out and is the GitHub repository’s default branch;- local
mainmatches the pushedorigin/main; and - the repository is available through the project’s GitHub integration.
The resulting version immediately becomes active in both staging and
production. create does not accept a feature branch or pull-request commit: if
you started with a pull request, merge it first and update local main. Once
the runtime group exists, later pull-request commits can become staging
candidates through the normal Git-driven version flow.
pin steers staging; --environment defaults to and accepts only staging.
With no flag it freezes staging on the named exact version, --sha freezes it
on the version built from that recipe commit, and --branch follows future
versions built from main or pr/N. A moving branch ref and a frozen commit
are mutually exclusive, and unpin restores staging to main. Production
normally follows the repository’s default branch and can be pinned only through
the Control Plane API. See
Operating runtimes for
the immutable-source versus movable-lane distinction.
update --yank withdraws a version from resolving for new work without deleting
its history, and --unyank reverses it. delete removes the version from
future use and evicts its baked images, so prefer --yank when you need a
reversible withdrawal.
JavaScript, Python, and Rust SDKs intentionally expose runtime list/get, resolution, and run only. Use this CLI or the dashboard for lifecycle changes.
Recipe records
Cloud recipe records are immutable Git pins. Authoring them is operator work, so these commands have no SDK equivalent; the SDKs read recipes only.
introspection recipes list [--name <name>]
introspection recipes get <recipe-id>
introspection recipes create --name <name> \
[--repository-id <id>] [--git-ref <ref>] [--git-sha <commit>] \
[--sub-path <path>] [--slug <slug>]
introspection recipes update <recipe-id> [--name <name>] [--description <text>]
introspection recipes delete <recipe-id>Runtime bootstrap normally creates the initial recipe pin for you; reach for
recipes create only when operating the record directly. --name is its only
required flag, and --slug overrides the stable slug otherwise derived from the
name and short commit sha.
update changes the operator-facing name and description only. The Git pin
(repository, ref, commit, sub-path) is immutable: pointing at different content
means creating a new recipe. delete is a soft delete, and is refused while
runtimes still reference the recipe.
Related
- CLI setup & login: install,
setup,login, and the output contract. - Production signals & evals: tasks, experiments, and telemetry reads.
- Operating runtimes: runtime groups, versions, and lane routing.
- Bindings: endpoints, variables, and credentials.
- Authentication: which credential each caller type should hold.