Command-line interface (ap)
The ap CLI under cmd/cli/ is the developer/operator tool for talking
to a running AuthProxy server: listing connectors and connections, signing JWTs
to drive scripted calls, and running local reverse proxies that route through a
connection’s credentials.
Build/run:
go run ./cmd/cli <command> # from a checkoutgo install ./cmd/cli && ap <command> # installed as $GOBIN/apThe rest of this doc uses ap <command> for brevity.
Configuration
Section titled “Configuration”The config file
Section titled “The config file”ap reads ~/.authproxy.yaml by default. Override with --config <path>.
# Default actor signed onto outbound requests. If omitted, --actorId on# the command line is required (or `--admin` falls back to the current# OS username).adminUsername: bobdole
# Asymmetric signing key (RS256). Use this for the standard dev setup —# the public key lives in the server's systemAuth.jwtSigningKey block.adminPrivateKeyPath: /path/to/private/key
# Optional alternative: HMAC shared secret (HS256). Mutually exclusive# with adminPrivateKeyPath on a given invocation.# adminSharedKeyPath: /path/to/shared.secret
# Base URLs for each AuthProxy service. Only the services you call need# to be set — `api` is the most common for everyday CLI use.server: api: http://localhost:8081 adminApi: http://localhost:8082 auth: http://localhost:8080 marketplace: http://localhost:5173 adminUi: http://localhost:5174
# Defaults for `ap signing-proxy`. Useful when several AuthProxy clones# share one machine — each clone's signing-proxy needs its own port. The# `envVar` form lets one shared ~/.authproxy.yaml pick up the per-clone# value from the clone's .env (AUTHPROXY_SIGNING_PROXY_PORT).signingProxy: port: envVar: AUTHPROXY_SIGNING_PROXY_PORT default: "8888"Every value here can be overridden per-invocation by the flag of the same shape
(--apiUrl, --privateKeyPath, --actorId, --port, etc.).
Signing keys
Section titled “Signing keys”AuthProxy supports two JWT signing modes:
| Mode | YAML field / flag | Server-side counterpart |
|---|---|---|
| RS256 (asymmetric) | adminPrivateKeyPath / --privateKeyPath |
systemAuth.jwtSigningKey.publicKey.path |
| HS256 (shared secret) | adminSharedKeyPath / --secretKeyPath |
systemAuth.jwtSigningKey.privateKey.path (used as the shared secret) |
The dev stack ships a ready-to-use RSA keypair under
dev_config/keys/admin/ (bobdole + bobdole.pub) paired with the matching
public key registered in dev_config/default.yaml. Point adminPrivateKeyPath
at dev_config/keys/admin/bobdole and you’re signed in as bobdole against a
fresh docker compose up -d server.
Actor and scope
Section titled “Actor and scope”Every signed token has an actor (who is making the call) and a service-id allowlist (which AuthProxy services the token is valid against).
- Actor defaults:
--actorId> YAMLadminUsername> current OS username (only when--adminis set). - Service allowlist defaults to
all. Override with--apis admin-api,apito scope a token down. Valid IDs:admin-api,api,public,worker. --adminflips the token’s permissions to match thesystemAuth.actors.permissionsblock on the server (full access in the dev config).
The CLI emits a subject-only token: the selected actor ID is placed in sub,
and the server resolves the existing actor in the selected namespace. It does
not embed or provision an actor resource. Applications that do embed actors
must use the restricted authproxy.net/v1alpha1 Actor claim described in
Authentication and Authorization.
Commands
Section titled “Commands”ap list connectors / ap list connections
Section titled “ap list connectors / ap list connections”Paginates GET /api/v1/connectors and GET /api/v1/connections, printing each
item to stdout. Output includes the human-readable name and immutable ID. Use
the name to recognize a resource, but pass the ID to commands and URLs that
address it directly.
ap list connectors --name salesforce --state activeap list connections --name production-crm --order "created_at DESC"--name is an exact, case-sensitive filter. If the caller can list several
namespaces, the same name can produce more than one result; compare namespace
and ID before acting. Other useful flags are --state, --type (connectors
only), and --order "<field> ASC|DESC". Pagination is automatic and the
complete result is printed as a JSON array.
JSON output contains complete authproxy.net/v1alpha1 resources, including
apiVersion, kind, metadata, spec, and (when available) status.
Scripts that need durable identity should read metadata.id; the display name
is metadata.name, and connector generations use metadata.generation. The
CLI does not yet have dedicated create or rename commands, so use the API for
those operations.
See Resource identity and names
for create, rename-by-ID, conflict, and query examples.
ap sign-jwt
Section titled “ap sign-jwt”Prints a signed JWT to stdout — useful for piping into
curl -H "Authorization: Bearer $(ap sign-jwt)" or for debugging server-side
verification.
ap sign-jwt --admin # sign as the current OS user, all servicesap sign-jwt --actorId alice --apis apiUseful scoping flags:
| Flag | Purpose |
|---|---|
--expires-in 24h |
Adds an expiration relative to now. Durations accept Go units plus d for days. |
--no-expiry |
Leaves the token without an expiration. Mutually exclusive with --expires-in. |
--permissions-file perms.yaml |
Adds top-level JWT permission restrictions from a YAML/JSON array or {permissions: [...]} object. |
--grafana-preset aggregate |
Adds least-privilege permissions for Grafana app-metrics time-series dashboards and live dropdown variables. Defaults expiration to 90 days. |
--grafana-preset logs |
Includes the aggregate preset plus request-events:list for request-log metadata tables. Defaults expiration to 90 days. |
Grafana datasource token examples:
# Metrics dashboards only.ap sign-jwt --actorId grafana --apis api,admin-api --grafana-preset aggregate
# Metrics plus request-event metadata tables.ap sign-jwt --actorId grafana --apis api,admin-api --grafana-preset logs
# Provisioned datasource token with no expiry.ap sign-jwt --actorId grafana --apis api,admin-api --grafana-preset logs --no-expiryGrafana presets use top-level JWT permissions. Those permissions only restrict the token; the backing actor still needs matching normal permissions. The server rejects a token whose top-level permissions are broader than the backing actor’s grants.
Permission namespaces in a permissions file support the same actor templates as
normal actor permissions: {{externalId}}, {{labels.<label>}}, and
{{annotations.<annotation>}}. These render against the backing actor, and
missing label or annotation values make the permission fail to match.
ap verify-jwt
Section titled “ap verify-jwt”Reads a JWT on stdin and verifies it against the supplied public/secret key.
echo "$TOKEN" | ap verify-jwt --publicKeyPath /etc/authproxy/keys/system.pubap signing-proxy
Section titled “ap signing-proxy”Long-running reverse proxy that signs an admin JWT onto every forwarded request, then sends it to one of the AuthProxy services. This is the tool for driving the admin UI / marketplace SPA against a local backend without baking auth into the browser.
ap signing-proxy --proxyTo=api --port 8888ap signing-proxy --proxyTo=admin-api --enableLoginRedirect=true--proxyTo accepts a service id (api, admin-api, public) or an absolute URL.
--enableLoginRedirect adds a /login-redirect handler that simulates the host
application’s session-initiation flow — wire hostApplication.initiateSessionUrl
(or adminApi.ui.initiateSessionUrl) at the printed URL.
--port defaults to 8888. If the CLI config sets signingProxy.port, that value
is used instead when --port is not given on the command line. Multiple clones
on one machine should set AUTHPROXY_SIGNING_PROXY_PORT per clone in their
.env and reference it from a shared ~/.authproxy.yaml via
signingProxy.port.envVar.
ap proxy — connection-scoped streaming proxy
Section titled “ap proxy — connection-scoped streaming proxy”Routes inbound requests through /api/v1/connections/{id}/_proxyRaw using the
original HTTP method so the connection’s credentials are applied and bodies stream
end-to-end (chunked uploads, SSE responses).
Long-running mode. Boots a listener on --port (default 9999). Each inbound
request derives its X-AuthProxy-Upstream-URL from --upstream-base (path +
query appended) or the caller may set the header directly.
# Auto-derive upstream from base.ap proxy --connection cxn_abc --upstream-base https://api.openai.comcurl http://127.0.0.1:9999/v1/chat/completions -d @body.json
# Caller-supplied upstream — no --upstream-base.ap proxy --connection cxn_abccurl http://127.0.0.1:9999/ \ -H 'X-AuthProxy-Upstream-URL: https://api.openai.com/v1/models'One-shot mode — append a literal curl or wget plus that tool’s own argv.
ap proxy boots an ephemeral-port listener in-process, rewrites the URL’s
scheme+host to point at it (path/query preserved), and execs the tool.
Stdout/stderr/exit-code pass through verbatim.
ap proxy --connection cxn_abc curl -i https://api.openai.com/v1/modelsap proxy --connection cxn_abc curl -X POST https://api.openai.com/v1/chat/completions \ -H 'Content-Type: application/json' -d @body.jsonap proxy --connection cxn_abc wget https://api.example.com/files/big.bin -O out.binAll ap proxy flags must come before the curl/wget literal —
Flags().SetInterspersed(false) stops cobra’s flag parser at the first
positional, so curl’s own flags (-X, -d, --config, …) reach the tool
without colliding with ours.
Hop-by-hop headers (RFC 7230 §6.1) are stripped on both legs of the proxy hop. Response bodies are flushed after each write so SSE streams tick out in real time.
ap sign-marketplace-login-url
Section titled “ap sign-marketplace-login-url”Generates a signed marketplace login URL — the URL the host application redirects the user to so the marketplace SPA can establish a session.
ap sign-marketplace-login-url --actorId aliceap login-redirect
Section titled “ap login-redirect”Local stand-in for a host application’s session-initiation endpoint. Hosts
/login-redirect on the configured port and returns the same payload your real
host would. Useful when developing UI changes against a local stack without
spinning up the host app.
ap login-redirect --port 8889Common recipes
Section titled “Common recipes”Drive a probe against a connector with a scratch JWT
Section titled “Drive a probe against a connector with a scratch JWT”TOKEN=$(ap sign-jwt --admin --apis api)curl -H "Authorization: Bearer $TOKEN" \ http://localhost:8081/api/v1/connectors/openai/probes/list-modelsStream an upload to S3-compatible storage through a connection
Section titled “Stream an upload to S3-compatible storage through a connection”ap proxy --connection cxn_s3 --upstream-base http://localhost:9000 &curl -X PUT -T big.bin http://127.0.0.1:9999/bucket/big.binLive-tail an SSE response from an LLM connector
Section titled “Live-tail an SSE response from an LLM connector”ap proxy --connection cxn_openai curl -N \ https://api.openai.com/v1/chat/completions \ -H 'Content-Type: application/json' \ -d '{"model":"gpt-4o","stream":true,"messages":[{"role":"user","content":"hi"}]}'The -N (--no-buffer) is curl’s, not ours — it disables curl’s own line
buffering so the tokens print as they arrive.
Run several AuthProxy clones on one machine
Section titled “Run several AuthProxy clones on one machine”Each clone (~/src/authproxy1, ~/src/authproxy2, …) needs its own port pool
so they don’t collide. The pool lives in each clone’s .env (gitignored) — see
.env.example for the slot table. The AUTHPROXY_SIGNING_PROXY_PORT slot
picks the listen port for ap signing-proxy:
| Clone | AUTHPROXY_SIGNING_PROXY_PORT |
|---|---|
| authproxy1 | 8888 (default) |
| authproxy2 | 8898 |
| authproxy3 | 8908 |
| authproxyN | 8888 + (N−1)·10 |
A single shared ~/.authproxy.yaml picks up whichever clone you ran ap from by
reading the env var loaded from that clone’s .env:
signingProxy: port: envVar: AUTHPROXY_SIGNING_PROXY_PORT default: "8888"cd ~/src/authproxy3 && ap signing-proxy --proxyTo=api # listens on 8908cd ~/src/authproxy1 && ap signing-proxy --proxyTo=api # listens on 8888ap signing-proxy --proxyTo=api --port 9000 # --port always winsThe matching AUTHPROXY_HOST_APP_INITIATE_SESSION_URL in each .env is templated
http://127.0.0.1:${AUTHPROXY_SIGNING_PROXY_PORT}/login-redirect, so the server’s
session-initiation URL automatically matches the port the local signing-proxy
listens on.
See also
Section titled “See also”- Local development — the surrounding source and UI workflow.
- AGENTS.md — Running locally — repository-specific contributor guidance.
- Telemetry — what shows up in traces/metrics when these commands fire
- requests through the server.
Apply resource manifests
Section titled “Apply resource manifests”ap apply creates or updates resources through the configured API service. It
validates the complete input and its prerequisites before writing, then executes
in dependency order. Use --dry-run=client to check resource types, fields,
identity, and namespace selection without contacting the cluster.
ap apply -f ./resources --recursive --namespace root.integrationsap apply -f ./resources --recursive --namespace root.integrations --dry-run=clientap apply -f namespaces.yaml -f connectors.yaml --dry-run=client -o yamlcat resources.yaml | ap apply -f - --namespace root.integrations --dry-run=clientFor example, save this as namespace.yaml:
apiVersion: authproxy.net/v1alpha1kind: Namespacemetadata: name: integrations namespace: rootspec: {}Then run ap apply -f namespace.yaml --dry-run=client. This validates the
namespace root.integrations; it does not create it.
Identity and input rules
Section titled “Identity and input rules”Resources must contain metadata.id or both metadata.namespace and
metadata.name. An explicit namespace takes precedence over --namespace.
If a name-based resource omits its namespace and no flag supplies it, validation
fails. There is no implicit root default. ID-only targets need no namespace;
cluster execution resolves them and checks any supplied identity fields.
An explicit missing ID fails instead of creating a different resource.
For Namespace, metadata.namespace is the parent path. A namespace ID supplies
its canonical path, and any supplied name or parent must agree. name: root
without a parent identifies the root namespace, which does not receive the
flag’s default parent.
Supported kinds are Namespace, Actor, Connector, Key, RateLimit, and
Connection, using apiVersion: authproxy.net/v1alpha1. Connection input is
limited to mutable metadata and an omitted or empty spec; connection setup is
not declarative creation. Status and timestamps are rejected. Only Connector
manifests may address a generation.
The loader accepts YAML, JSON, multi-document YAML, typed resource lists such as
ActorList, and heterogeneous List envelopes. List items must carry their own
API version and kind. Incomplete paginated lists are rejected. Duplicate keys,
YAML aliases/merge keys, unknown fields in strict mode, invalid identity, and duplicate selected
resource identities fail the whole batch. Diagnostics identify the source,
document, and list item. Multiple inputs retain their argument order; directory
files are visited lexically. Symlinks discovered inside directories are skipped.
Supported operations
Section titled “Supported operations”| Kind | Create | Update |
|---|---|---|
Namespace |
Name and parent path | Mutable metadata and namespace settings; the path is immutable. |
Actor |
Name, namespace, and actor spec | Mutable metadata and actor settings, including explicitly supplied signing credentials. |
Connector |
Name, namespace, and definition | Mutable metadata, draft definitions, and publication intent; see generations below. |
Key |
Name, namespace, and key settings | Mutable metadata and supported key settings. Available through both API services; --admin selects the admin API. |
RateLimit |
Name, namespace, and rate-limit policy | Mutable metadata and policy. |
Connection |
Unsupported | Existing connection’s mutable metadata only. Establish connections through the connection setup flow. |
Canonical resource validation still applies: required fields cannot be removed,
and immutable fields cannot be changed. Object fields are merged by child key;
use explicit null to clear a nullable reference such as
spec.encryptionKeyRef, including any ID the server added when resolving it.
Removing a document from your input
does not delete its resource.
Create, edit, and adopt resources
Section titled “Create, edit, and adopt resources”This multi-document file creates a namespace and an actor inside it. Apply orders the namespace first even if the actor appears first in the file:
apiVersion: authproxy.net/v1alpha1kind: Namespacemetadata: name: integrations namespace: rootspec: {}---apiVersion: authproxy.net/v1alpha1kind: Actormetadata: name: worker namespace: root.integrations labels: environment: development temporary: "true"spec: externalId: integration-workerRun ap apply -f resources.yaml, then edit environment and remove temporary
and apply again. Apply updates the managed label and removes the omitted label;
labels added independently are preserved. Server-projected apxy/ labels are
read-only and are never submitted in patches. A later apply with the same desired
state reports unchanged. An initial reapply may update history to include the
server-assigned ID before reaching that steady state.
To adopt an existing resource, use its namespace and name, or supply its ID:
apiVersion: authproxy.net/v1alpha1kind: Actormetadata: id: act_REPLACE_WITH_EXISTING_ID labels: environment: productionspec: {}Replace the placeholder with an actual actor ID. With no previous apply history, apply warns and takes ownership of the supplied fields; it preserves omitted fields. Do not copy a GET response directly into a manifest: remove status, timestamps, and redacted credentials first. Structured apply output also contains result envelopes rather than replayable manifests.
Available options
Section titled “Available options”| Option | Behavior |
|---|---|
-f, --filename |
Repeatable file, directory, HTTP(S) URL, or - for stdin. Stdin may appear only once. |
-k, --kustomize |
Build a local Kustomize directory; mutually exclusive with -f and -R. |
-R, --recursive |
Traverse nested directories. Directory discovery includes .yaml, .yml, and .json. |
-n, --namespace |
Supply a missing namespace or Namespace parent. |
-l, --selector |
Filter input labels using =, ==, !=, existence (key), or nonexistence (!key). |
--dry-run |
none (default) applies to the cluster; client validates without cluster access or signing configuration. |
--validate |
strict (default) rejects unknown fields; warn drops them with warnings; ignore drops them silently. true aliases strict and false aliases ignore. |
--overwrite |
Defaults to true; controls managed-field drift during reconciliation. Has no effect during client dry-run. |
-o, --output |
name, json (an array), yaml (a document stream), go-template, go-template-file, jsonpath, jsonpath-file, or jsonpath-as-json. Execution prints operation results; client dry-run prints desired resources. The default prints human-readable status. |
--request-timeout |
Timeout per cluster request, default 30s; 0 disables it. |
--template |
Expression or file path for a template/JSONPath format. Alternatively use -o 'jsonpath=EXPRESSION' or -o 'go-template=EXPRESSION'. |
--allow-missing-template-keys |
Defaults to true; set false to fail on missing template/JSONPath fields. |
--prune |
After every apply succeeds, delete omitted, previously applied resources in an explicit scope. Defaults to false. |
--prune-allowlist |
Required with prune. Repeatable or comma-separated Actor, Key, RateLimit, or their authproxy.net/v1alpha1/KIND forms. No implicit kind defaults. |
--all |
With prune, select all labels in the exact namespace/kind scope. Mutually exclusive with a nonempty selector. |
--wait |
Prune only; defaults to true. Poll each deleted resource until GET returns HTTP 404. |
--timeout |
Prune only; wait deadline per deletion, default 30s. 0 disables the wait deadline. Independent of per-request timeout. |
The loader checks every resource before producing output, including resources
excluded by a selector. Validation modes never permit malformed identities,
duplicate keys, invalid field types, server-owned fields, or redacted secret
placeholders. Warn/ignore remove unknown fields before output. A selector
matching no resources succeeds with empty output ([] for JSON); input containing
no resource documents fails.
URL downloads use an independent, unsigned HTTP client, a 30-second timeout, and a 16 MiB limit per source. URL credentials and HTTPS-to-HTTP redirects are rejected. Local files and stdin use the same size limit. An HTTP source still requires network access during client dry-run.
Structured output masks schema-declared secrets and retains explicit null and empty values. Redacted output is for inspection, not a replayable manifest; redacted secret placeholders are rejected as input. Dry-run does not verify resource existence, authorization, references, server defaults, or whether a subsequent apply would create or update a resource.
Execution and failures
Section titled “Execution and failures”Cluster execution uses the existing signing and configuration flags, including
--config, --actorId, --privateKeyPath/--secretKeyPath, --apiUrl, and
--admin with --adminApiUrl. It requires read access to namespace and explicit
reference prerequisites as well as the resource read/create/patch permissions.
Logical Connector applies also require connectors:list/generations to inspect
the selected generation, existing draft, and newest generation.
A selector that matches no resources succeeds without connecting to the cluster.
All targets and plans are validated before writes. Newly created namespaces precede their children and contained resources; explicit references precede their dependents. Prerequisites must be in the selected batch or already exist. Missing prerequisites and cycles fail before writes. For example, creating a namespace that references an encryption key being created inside that namespace is a cycle. When the namespace already exists, the key can be created before updating its namespace’s encryption-key reference.
History stored in authproxy.net/last-applied-configuration lets apply preserve
unmanaged fields and remove formerly managed omissions where supported. Secrets
are excluded from history. Explicit secret values are submitted without comparison;
omitted secrets are preserved. Because secrets cannot be compared with their
stored values, keeping an explicit secret in a manifest may cause each apply to
report configured rather than unchanged. History is stored as a resource
annotation: non-secret desired values are visible to readers of that resource.
Do not put credentials in labels, annotations, or other ordinary fields.
--overwrite=false reports managed-field drift
instead of overwriting it. Initial adoption of resources without history emits a
warning.
Execution results use created, configured, unchanged, failed, and skipped
statuses. Failed prerequisites cause dependents to be skipped; independent
resources continue. Any failure or skip returns a nonzero exit status. Cancellation
stops further mutations. JSON output is an array of envelopes containing source,
kind, identity, operation, status, a redacted resource on success, and an error on
failure. YAML emits one envelope per document. Name output prints successful
identifiers, with failures reported on stderr.
Batches are not transactional and successful writes are not rolled back. A mutation that fails to return a valid response may already have succeeded; apply does not retry it automatically. Results are printed after execution, so an output error also cannot roll back writes.
Immediately before each operation, apply reads the target again and recomputes its plan using the same overwrite policy. This preserves unrelated changes visible at that read, including changes to labels, annotations, and apply history. Existing resources remain bound to their resolved IDs. History removed after preparation requires a new batch so adoption is not silent. A resource that appears after a planned create causes a failure rather than automatic adoption; a create conflict is also reported without retry. Review the cluster and rerun apply to prepare a new batch. Mutation errors, including HTTP 409/412 responses, are never replayed because the current API may have performed part of an update already.
These reads are not atomic write preconditions. The API does not enforce
ETags or object revisions for apply, so edits between the final read and write
can still be overwritten, including with --overwrite=false. Connector metadata,
history, and generation changes can also partially succeed within one request.
Serialize applies and other writers when this matters; this command does not
provide strong concurrency guarantees. Server dry-run, server-side apply, field
managers, --force-conflicts, force deletion, cascading deletion, grace-period
and unsupported deletion flags remain unsupported. Scoped prune is described below.
Connector generations
Section titled “Connector generations”Apply inspects the selected generation and available generations before planning logical Connector updates. It reuses an existing draft; if a draft must be created, it merges against the newest generation that the server will clone. Repeated applies omit known-equal definitions and do not manufacture generations. Explicit secret values cannot be compared and may still cause definition writes.
Set spec.release.desiredState: primary to publish a changed definition. With no
release intent, a changed published definition becomes a draft. If a manifest
previously managed desiredState: primary, change it explicitly to draft to
stop publishing edits; omitting a required managed field cannot clear it. A declaration
already satisfied by the primary leaves an unrelated draft alone. Metadata-only
updates do not create generations.
metadata.generation addresses exactly that existing generation. Updates require
a draft; published generations can only return unchanged when no write (including
history adoption) is needed. Apply never calls the force-state endpoint.
Kustomize input
Section titled “Kustomize input”ap apply supports Kustomize as a way to configure
AuthProxy resources without templates. Kustomize is part of the k8s ecosystem
and embedded within the kubectl cli. The AuthProxy cli ap also embeds
kustomize to allow configuration of AuthProxy’s k8s-style resources, but removes
Kubernetes/Helm specific features from Kustomize.
ap apply -k ./overlays/production builds the directory using the embedded
Kustomize engine and then runs the same validation, selection, reconciliation,
and redaction as -f. It does not need an installed kubectl or kustomize
binary. External plugins and Helm execution are disabled; normal Kustomize
file-loading restrictions remain enabled. Remote bases may still require network
access, including during client dry-run. --request-timeout governs cluster
requests, not Kustomize builds.
For example, kustomization.yaml can contain:
resources: - actor.yamlnamespace: root.integrationslabels: - pairs: managed-by: applyAuthProxy’s dotted namespace paths are retained. On AuthProxy Namespace
resources, metadata.namespace remains the parent path, and the Kustomize
namespace transformer leaves metadata.name intact. Kustomize’s default name
prefix/suffix rules also leave Namespace names alone. Set those names directly
or use an explicit patch. Kustomize transformations happen first; --namespace
then fills only namespace fields still missing from the rendered manifests.
Template and JSONPath output
Section titled “Template and JSONPath output”Templates and JSONPath evaluate the same sanitized array as JSON output: result envelopes for cluster execution, desired resources for client dry-run. They never receive unredacted API objects. Template syntax is checked before writes, but execution-time errors (for example, missing fields) can still occur after successful writes and do not roll them back.
ap apply -f resources.yaml -o 'jsonpath={range [*]}{.kind}{" "}{.status}{"\n"}{end}'ap apply -f resources.yaml --dry-run=client -o 'go-template={{range .}}{{.metadata.name}}{{"\n"}}{{end}}'ap apply -f resources.yaml -o go-template-file --template ./summary.tmpljsonpath-as-json encodes selected values as JSON. go-template-file and
jsonpath-file read the expression from the path supplied by --template or
the -o FORMAT=PATH form. An empty selection produces an empty array as the
printer input. JSONPath and Go-template output do not change the process exit
status for failed applies or prune operations.
Inspect and edit apply history
Section titled “Inspect and edit apply history”History commands select existing resources using -f (including -R) or -k,
with the same namespace fallback, selector, signing, endpoint, and request-timeout
flags. They accept no positional resource names. They don’t create a resource or
modify its spec or ordinary metadata; set/edit replace only the sanitized
last-applied annotation.
ap apply view-last-applied -f resources.yaml -o yamlap apply set-last-applied -f resources.yaml --create-annotationap apply edit-last-applied -f resources.yamlView prints sanitized desired manifests, as YAML documents by default or a JSON
array with -o json. Set records the supplied manifests as history without
applying their fields; it requires existing history unless --create-annotation
is supplied. Edit opens sanitized manifests in $KUBE_EDITOR, then $EDITOR,
or vi. Save and exit to update history, or leave the file unchanged to cancel.
Failed edits retain a private temporary file and report its path. Set/edit output
uses result envelopes in YAML or JSON.
Edits must retain the selected resources, their order, identities, and generation selectors. Secret values are removed before history is stored, and existing secret-presence markers are retained. View refuses invalid or secret-bearing history instead of printing it. Set can replace malformed history with a clean manifest. A concurrent history change aborts the affected update; unrelated annotations are preserved. These checks are not atomic write preconditions, and a later failure cannot roll back earlier history updates.
Scoped prune
Section titled “Scoped prune”Prune is opt-in and requires an explicit --namespace, a kind allowlist, and
exactly one of --selector or --all. Every selected manifest must belong to
that exact namespace (the parent namespace for a Namespace manifest). Descendant
namespaces are excluded, even if the server’s list filter includes them. Empty
input or a selector matching no manifests is rejected for prune.
ap apply -f ./team-resources --namespace root.team \ --prune --prune-allowlist Actor,RateLimit --selector managed-by=applyCandidates must be absent from the selected input, match the namespace/kind/label scope, and contain valid last-applied history for their identity. Unmanaged resources are never candidates. The command exhausts every inventory page before applying; incomplete pages, repeated cursors, malformed history, and read errors abort preparation. After all applies succeed, it rechecks candidates and key references before deleting. Candidate changes require another invocation.
Only Actor, Key, and RateLimit deletion is supported. Key pruning requires
namespace-list access and the server’s guarded DELETE /keys/{id}/unused
endpoint. It rejects the global key, namespace references, and any data-encryption
key history, including retired/deleted entries, because old ciphertext can still
need those keys. Older servers without that endpoint fail safely; there is no
fallback to ordinary Key deletion. Namespace destruction, Connector archival,
and Connection disconnection are not generic pruning operations.
Prune is unavailable with client dry-run because offline validation cannot list
or verify deletion candidates. Results append operation: delete, status: pruned
envelopes after apply results. With --wait=false, this means the server accepted
deletion; the default waits for HTTP 404. A failed delete or wait stops subsequent
deletions and returns nonzero without retrying. Earlier applies and deletions
remain committed. There are no atomic list/delete preconditions or locks against
other writers; serialize conflicting changes when using prune.
Apply resources on server startup
Section titled “Apply resources on server startup”For a local development environment, start the server and apply resource manifests
with the same validation, reconciliation, and dependency ordering as ap apply:
go run ./cmd/server serve --auto-migrate --config=./dev_config/default.yaml \ --apply=./dev_config/default-resources.yaml all| Option | Behavior |
|---|---|
--apply PATH |
Local YAML/JSON file or directory; repeat to combine inputs into one batch. Directories are not recursive. URLs and stdin are not supported. |
--apply-actor EXTERNAL_ID |
Optional existing actor whose permissions authorize the apply. Defaults to system in root, created if absent. |
--apply-actor-namespace NAMESPACE |
Namespace for an explicit --apply-actor; defaults to root. The default system actor always uses root. This does not set resource namespaces. |
--apply-timeout DURATION |
Total readiness and apply deadline; defaults to 2m. Must be positive. |
The selected services must include api or admin-api. Comma-separated service
lists and all are expanded and deduplicated once before startup. The server uses its local
listener, preferring the admin API when both are started, and signs short-lived
internal requests using its global encryption key. When --apply-actor is omitted,
startup creates a system actor in root if absent, with full permissions across
all namespaces and no self-signing key. An existing system actor is reused without
changing its permissions, credentials, or metadata. Bootstrap runs after schema
verification/migration and before the listeners start; it does not require a worker.
An explicit --apply-actor must already exist (or be provisioned by an actor source)
and have the permissions required by the manifests. For external actor sources,
include the worker so actor synchronization can run.
TLS listeners require a certificate trusted by the local client for localhost.
Manifests must supply their own namespaces. Input validation occurs before
migration or startup. The server retries read-only preparation while the listener
and actor become available, then executes the batch once. It exits with an error
if preparation times out or apply fails. Successful writes are not rolled back,
and startup apply never prunes resources. --auto-migrate is independent: it
prepares development database schemas, keys, actors, and configured namespaces
and rate limits. Connector provisioning uses the apply batch.