Skip to content
Back to skills

Query Spec

ASecurity

Filters, selects, and sorts Control Plane resources with the query spec language. Use when the user asks about targetQuery, memberQuery, cpln query commands, tag-based selection, property filtering, or dynamic location selection.

  • 10 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added August 31, 2026
devopsgobashapi

Works with

  • cli
  • api
  • mcp

Security analysis

A100/100

Scanned October 1, 2026

npx -y skills add controlplane-com/ai-plugin --skill query-spec --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Query Spec?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Query Spec
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/controlplane-com-query-spec/badge)](https://www.skillsdirectory.com/skills/controlplane-com-query-spec)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: query-spec
description: "Filters, selects, and sorts Control Plane resources with the query spec language. Use when the user asks about targetQuery, memberQuery, cpln query commands, tag-based selection, property filtering, or dynamic location selection."
---

# Query Spec — Filtering & Selecting Resources

Control Plane has one query language used in two ways: **ad-hoc filtering** of a resource list (CLI / API), and **dynamic targeting** embedded inside three resource fields.

| Where | Field / command | Purpose |
|:---|:---|:---|
| Policy | `targetQuery` | Target resources by tag/property instead of listing `targetLinks` (see **access-control**) |
| Group | `memberQuery` | Assign members dynamically — **users only** |
| GVC | `spec.staticPlacement.locationQuery` | Select locations dynamically instead of listing `locationLinks` |
| CLI | `cpln KIND query` | Ad-hoc filtering — every resource kind |
| API | `POST /org/ORG/KIND/-query` | Ad-hoc filtering — every resource kind |

**Not an MCP list parameter.** `list_resources` has no filter argument (list a kind, then filter the table yourself); `query_audit_events` filters by kind/name/subject/context/time; `query_metrics` takes PromQL. The query spec appears only inside the three resource fields above, set when you create or update that resource.

## Structure

```yaml
kind: workload          # resource kind being selected
fetch: items            # "items" (objects, default) or "links" (references)
spec:
  match: all            # "all" (default), "any", or "none"
  terms:
    - op: "="
      tag: environment
      value: production
    - op: exists
      tag: monitored
  sort:
    by: name
    order: asc
```

## Terms

Each term targets exactly **one** of three fields (mutually exclusive — the schema rejects a term that sets more than one):

| Field | Targets | Example |
|:---|:---|:---|
| `tag` | Resource tags (key/value labels) | `tag: environment`, `value: production` |
| `property` | Built-in properties (`name`, `description`, `status.phase`, …) | `property: name`, `value: my-app` |
| `rel` | Relationships to other resources | `rel: gvc`, `value: my-gvc` |

### Operators

| Operator | Needs `value` | Meaning |
|:---|:---:|:---|
| `=` | yes | Equal (default when `op` is omitted) |
| `!=` | yes | Not equal |
| `>` `>=` `<` `<=` | yes | Numeric / date comparison |
| `~` | yes | Pattern match (schema op name `match`) |
| `=~` | yes | Regex match (schema op name `regex`) |
| `contains` | yes | Substring match |
| `exists` | no | Tag/property is present (any value) |
| `!exists` | no | Tag/property is absent |

`value` accepts a string, number, boolean, or ISO date. **Boolean values are auto-converted to strings on `tag` terms only** — store `monitored=true` and you must query `value: "true"`, not `value: true`, or it silently matches nothing.

## Match modes

| Mode | Behavior |
|:---|:---|
| `all` | Every term must match (default) |
| `any` | At least one term matches |
| `none` | No term may match |

## Sorting

```yaml
sort:
  by: name            # required
  order: asc          # "asc" (default) or "desc"
```

Sort is **API- and manifest-only** — the `cpln KIND query` CLI has no sort flag, so a sort directive passed there is ignored.

Common fields (most kinds): `id`, `name`, `version`, `description`, `created`, `lastModified`. Kind-specific: `location` adds `origin`/`provider`/`region`; `cloudaccount` adds `provider`; `user` adds `idp`/`email`; `policy` and `group` add `origin`.

## CLI

**Ad-hoc filtering** — every kind supports `query`:

```bash
cpln workload query --tag environment=production
cpln workload query --match all --tag environment=production --tag region=europe
cpln workload query --rel gvc=my-gvc
cpln policy query --prop name=my-policy
cpln workload query --tag monitored                       # existence (no value)
cpln workload query --match any --rel gvc=one --rel gvc=two
```

| Flag | Alias | Notes |
|:---|:---|:---|
| `--match` | | `all` / `any` / `none` (default `all`); single value |
| `--tag` | | `KEY=VALUE`, or `KEY` for existence; repeatable |
| `--property` | `--prop` | `KEY=VALUE`; repeatable |
| `--rel` | | `KEY=VALUE`; repeatable |

Results cap at 50 by default — raise with `--max 0` for all records.

**Authoring dynamic targeting** — `gvc`, `policy`, and `group` create/update commands embed a query via `--query-match`, `--query-tag`, `--query-property`, `--query-rel` (group also `--query-kind user`):

```bash
cpln policy create --name img-policy --query-kind image --query-property repository=my-app ...
```

## API

```
POST https://api.cpln.io/org/ORG/workload/-query
```

```json
{ "spec": { "match": "all",
  "terms": [
    { "op": "=", "tag": "region", "value": "emea" },
    { "rel": "gvc", "op": "=", "value": "mygvc" }
  ],
  "sort": { "by": "name", "order": "asc" } } }
```

## Dynamic targeting examples

**Policy `targetQuery`** — applies to matching resources, including ones created later:

```yaml
kind: policy
targetKind: image
targetQuery:
  spec:
    terms:
      - { property: repository, value: my-app }
bindings:
  - permissions: [pull, view]
    principalLinks: [//group/developers]
```

**Group `memberQuery`** — dynamic membership by user tag (users only; service accounts must be added via `memberLinks`):

```yaml
kind: group
memberQuery:
  kind: user
  spec:
    terms:
      - { tag: "firebase/sign_in_provider", value: "microsoft.com" }
```

## Defaults & gotchas

- Omitted `op` defaults to `=`; omitted `match` defaults to `all`; omitted `fetch` defaults to `items`; omitted sort `order` defaults to `asc`.
- Boolean tag values become strings — query `"true"`, not `true`.
- `targetQuery` is retroactive: tag a new resource and matching policies cover it automatically — a scope to watch when granting permissions.
- `memberQuery` ignores service accounts.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.