CLI Reference

Use the opampctl command-line tool to manage OpAMP Commander.

opampctl is a kubectl-style command-line client for the OpAMP Commander apiserver. It manages agents, agent groups, packages, remote configs, certificates, namespaces, users, roles, and role bindings.

Installation

go install github.com/minuk-dev/opampcommander/cmd/opampctl@latest

Or build from source:

git clone https://github.com/minuk-dev/opampcommander.git
cd opampcommander
go build -o opampctl ./cmd/opampctl

Configuration

Initialize a configuration file:

opampctl config init

This creates ~/.config/opampcommander/opampctl/config.yaml. The format follows the kubectl model of contexts, clusters, and users:

currentContext: default-1
contexts:
  - name: default-1
    cluster: default
    user: admin
  - name: default-2
    cluster: default
    user: githubuser
  - name: default-3
    cluster: default
    user: manual
users:
  - name: admin
    auth:
      type: basic
      username: admin
      password: admin
  - name: githubuser
    auth:
      type: github          # browser or device OAuth flow
  - name: manual
    auth:
      type: manual
      bearerToken: "<your-bearer-token>"
clusters:
  - name: default
    opampcommander:
      endpoint: http://localhost:8080

Three authentication types are supported per user:

  • basic — username/password basic auth
  • github — GitHub OAuth (browser or device flow; see --auth-flow)
  • manual — a bearer token you supply directly

View the active configuration:

opampctl config view

Global flags

These flags apply to every command:

FlagDefaultDescription
-c, --config~/.config/opampcommander/opampctl/config.yamlPath to the config file
-v, --verbosefalseVerbose output (equivalent to --log.level=debug)
--log.formattextLog format (text, json)
--log.levelinfoLog level (debug, info, warn)
--auth-flow—Override the GitHub auth flow: browser or device

Command overview

CommandDescription
getList or read resources
createCreate resources (often from a -f manifest file)
setUpdate fields of a resource
deleteDelete resources
templatePrint example manifests (template examples ...)
restartSend a restart command to agents
configManage the local config file (init, view)
contextSwitch between contexts (ls, use)
whoamiShow the authenticated identity
versionShow client version

Resource types

get, create, and delete operate on these resource types:

agent, agentgroup, agentpackage, agentremoteconfig, certificate, connection (get only), container (get only), host (get only), namespace, user, role, rolebinding.

Lookup failures

When you request specific identities, opampctl get prints successful results in request order and reports each failed target with its identity and cause on stderr. Any failed lookup (including invalid UIDs, missing resources, permission errors, or timeouts) makes the command exit with status 1, even if other targets succeeded. JSON/YAML stdout contains only the successful result array, or [] if none succeeded.

Bounded inventory lists

get agent, agentgroup, connection, endpoint, certificate, agentpackage, agentremoteconfig, and remoteconfigschema print one page of at most 100 items by default, including with --all-namespaces (-A). This replaces the previous implicit full-inventory listing. Use --page-size (1–1000) to choose the request size, --continue to resume, or --stream to explicitly traverse all pages.

opampctl get agent -n production --page-size 50
# Copy the cursor printed on stderr, keeping namespace and filters unchanged:
opampctl get agent -n production --page-size 50 --continue '<cursor>'
opampctl get agentgroup -A --stream -o json > groups.json

Text/short output is flushed after each page, with a header per page. JSON is one valid array on successful completion. Streaming YAML is a sequence of documents, each containing one page’s array. All formats retain only a page in memory. Across namespaces, a page covers one namespace; even an empty page may print a resume cursor for the next namespace.

Ctrl+C, an API error, or a failed output write stops traversal with a nonzero exit status. Stdout may contain incomplete JSON or partial YAML/text; stderr reports the cause and a retry cursor. Retrying a failed page can replay items already written from that page. Resume with the same resource, namespace scope, and filters. These are live reads, so inventory changes between pages can affect results; cursors do not provide a snapshot or survive every server-side change.

Filtering

opampctl get accepts four filtering flags on every resource whose list endpoint answers them. The server does the filtering, so narrowing a view is a smaller query rather than a larger fetch.

FlagFilters on
-l, --selectorthe resource’s labels or reported attributes, Kubernetes-style
--field-selectorthe resource’s own fields
--namea case-sensitive name prefix
--name-containsa case-insensitive name substring (a scan — pair it with --name on a large collection)

-l/--selector sends whichever metadata parameter the resource answers — labelSelector for metadata an operator set, attributeSelector for what an agent reported about itself. A command already names its resource, so there is nothing to disambiguate; see the API reference for why the server keeps them apart. Resources with neither kind (roles, role bindings) have no -l flag at all.

# agents in production that are not canaries
opampctl get agent -l 'service.namespace=prod,tier notin (canary,dev)'

# an agent's non-identifying attributes are part of the same attribute domain
opampctl get agent -l os.type=linux

# unhealthy agents
opampctl get agent --field-selector status.healthy=false

# endpoints whose name starts with tempo-
opampctl get endpoint --name tempo-

Expressions are parsed before the request is made, so a typo is a local error naming the flag rather than a round-tripped 400. Which fields a resource supports is not repeated in --help: the server owns that list and names it on rejection. See the API reference for the full syntax and the per-resource field lists.

Two listings take no selectors — get agent --agentgroup and get agentgroup --agent, which read a group’s membership. There the label and name filters are applied locally rather than dropped, and --field-selector is rejected, because a caller must never mistake the whole membership for a narrowed one.

--non-identifying-selector is deprecated: -l/--selector reaches an agent’s non-identifying attributes too.

Contexts

opampctl context ls              # list contexts, highlighting the current one
opampctl context use default-2   # switch context

Authentication status

opampctl whoami

Agents

# list agents in the default namespace
opampctl get agent

# output formats: short (default), text, json, yaml
opampctl get agent -o yaml

# filter by agent group
opampctl get agent --agentgroup my-group -n my-namespace

# filter by label, server-side (see Filtering above)
opampctl get agent -l service.name=otel-collector

# across all namespaces
opampctl get agent -A

Update an agent (for example, assign a new instance UID):

opampctl set instance-uid agent/<instance-uid> <new-uid> -n default

Restart agents:

opampctl restart agent <instance-uid>

Agent groups

opampctl get agentgroup
opampctl get agentgroup <name>

# offer an existing certificate to the group's sole agent
opampctl set opamp-certificate agentgroup/<name> <certificate-name>

# create from a manifest file
opampctl create agentgroup -f ./agentgroup.yaml

# print an example manifest to start from
opampctl template examples agentgroup

opampctl delete agentgroup <name>

Most create commands accept -f/--file pointing at a YAML manifest. Use opampctl template examples <resource> to print a starting template for a resource type (agentgroup, agentpackage, agentremoteconfig, certificate, namespace, role, rolebinding).

Connections

opampctl get connection      # active agent connections

Users and RBAC

# create a user, optionally with a basic-auth password
opampctl create user --username alice --email alice@example.com --password-stdin

opampctl get user
opampctl get role
opampctl get rolebinding
opampctl create role -f ./role.yaml
opampctl create rolebinding -f ./rolebinding.yaml

create user flags include --username, --email, --password, --password-stdin, -f/--file, and -o/--output.

Version

opampctl version

Troubleshooting

Config file not found — run opampctl config init to create a default file, or pass --config with the correct path.

Authentication errors — verify your identity with opampctl whoami, check the endpoint with opampctl config view, and confirm the user’s auth block in the config file. For GitHub users, try --auth-flow device if a browser is unavailable.

Connection issues — ensure the apiserver is running and reachable at the cluster’s endpoint, and that the value matches the running server’s --address.

Remote-config schema workflow

A RemoteConfigSchema describes a collector distribution/version and its component catalog. Generate it from the collector you deploy, then create it in the same namespace as your remote config:

opampctl generate remoteconfigschema --binary-path ./otelcol-contrib > schema.yaml
opampctl create remoteconfigschema -n default -f schema.yaml
opampctl get remoteconfigschema -n default

The generator uses the collector’s reported build command and version by default. Use --namespace when generating a manifest for a namespace other than default; create -f uses the namespace in that manifest. You can also read saved or piped components output and choose JSON instead of the default YAML:

./otelcol-contrib components > components.yaml
opampctl generate remoteconfigschema --from components.yaml --namespace collectors \
  -o json > schema.json
opampctl create remoteconfigschema -f schema.json

./otelcol-contrib components | opampctl generate remoteconfigschema --from - > schema.yaml

--binary, --version, and --name override the reported build identity and the default schema name (<command>-<version>). --binary-path selects the executable; --binary only sets the distribution label stored in the schema.

Use the name from the generated manifest’s metadata.name as SCHEMA below. For a hand-written example, run opampctl template remoteconfigschema basic; edit its name, version and component catalog to match your binary before creating it. A catalog without field schemas only describes component availability.

# collector.yaml is a raw collector config, not an AgentRemoteConfig manifest.
opampctl create agentremoteconfig --name my-config -n default -f collector.yaml \
  --schema-ref SCHEMA
# Repeat --schema-ref to target more than one catalog.
opampctl set schemaref my-config -n default --schema-ref SCHEMA --schema-ref SECOND_SCHEMA
# Remove all references without re-sending the collector config.
opampctl set schemaref my-config -n default --clear

set schemaref replaces the complete reference list, or clears it with --clear. It reads the current resource version and sends only that precondition and spec.schemaRefs in a merge PATCH. Config content, content type and attributes are preserved. If another writer changes the resource, the command reports a conflict; re-read the resource before retrying. Clearing references on an existing config does not rerun creation-time auto-resolution.

When creating a remote config without explicit references, the server attempts best-effort matching against the schema catalogs in its namespace. Explicit references take precedence. To opt out, use:

opampctl create agentremoteconfig --name unpinned-config -n default -f collector.yaml \
  --skip-schema-validation

This sets the metadata attribute opampcommander.io/skip-schema-validation: "true", which disables automatic schema matching. It does not remove explicit references. The annotation is the schema validation opt-out marker; a schema reference alone is not proof that an agent has accepted or successfully applied the config.

opampctl get remoteconfigschema shows the component count across catalog classes. opampctl get agentremoteconfig shows schemaRefs and schemaRefsSource: explicit for user-selected references, auto for creation-time matches, none when empty, and unknown for legacy references without recorded provenance. Source is server-managed; reapplying an unchanged list preserves its existing source.