Skip to content

Organize and Focus with Filters and Views

As the number of units, spaces, and other entities in your organization grows, Filters and Views help you focus on what matters. Filters select which entities you see; Views control how you see them.

Labels: the foundation for filtering

Labels are key-value pairs attached to entities. They provide a flexible vocabulary for categorizing and selecting entities. Common label keys include:

  • Application: The application a unit belongs to (e.g., frontend, payments)
  • Layer: Infrastructure layer (e.g., Platform, Application)
  • Environment: Deployment stage (e.g., dev, staging, prod)
  • Region: Geographic location (e.g., us-east, eu-west)

Add labels when creating entities or with patch updates:

cub unit update --patch --space my-space --label Application=payments --where "Slug IN ('api', 'worker', 'db')"
cub space update --patch --label Environment=prod --label Region=us-east my-prod-space

Set up a home space for shared entities

Filters, Views, Triggers, Invocations, and ChangeSets can be stored in any space. We recommend creating a dedicated home space for these reusable entities. This keeps them organized and accessible across all your spaces.

cub space create ops-home

Set it as your default space so you don't have to specify --space every time:

cub context set --default-space ops-home

Create Filters

A Filter saves a where expression for reuse. Create filters for entity sets you work with frequently.

Filter by labels

cub filter create --space ops-home payments-units Unit \
  --where-field "Labels.Application = 'payments'"

cub filter create --space ops-home prod-spaces Space \
  --where-field "Labels.Environment = 'prod'"

Quick filters for common workflows

Create filters that identify units in specific states:

# Units with unapplied changes
cub filter create --space ops-home unapplied-changes Unit \
  --where-field "HeadRevisionNum > LiveRevisionNum AND TargetID IS NOT NULL"

# Units needing approval
cub filter create --space ops-home needs-approval Unit \
  --where-field "HeadRevisionNum > LiveRevisionNum AND LEN(ApprovedBy) = 0"

# Units with validation gates blocking apply
cub filter create --space ops-home has-apply-gates Unit \
  --where-field "LEN(ApplyGates) > 0"

# Units that need to be upgraded from their upstream source
cub filter create --space ops-home needs-upgrade Unit \
  --where-field "UpstreamRevisionNum > 0 AND UpstreamRevisionNum < UpstreamUnit.HeadRevisionNum"

Filter by configuration data

For units, you can also filter by the content of their configuration data:

cub filter create --space ops-home high-replicas Unit \
  --where-field "ToolchainType = 'Kubernetes/YAML'" \
  --resource-type apps/v1/Deployment \
  --where-data "spec.replicas > 3"

Use Filters

Every command that supports --where also supports --filter. Reference a filter by space/slug:

# List matching units across all spaces
cub unit list --space "*" --filter ops-home/payments-units

# Approve and apply matching units in a specific space
cub unit approve --space payments-prod --filter ops-home/payments-units
cub unit apply --space payments-prod --filter ops-home/payments-units

# Run a function on filtered units
cub function do --space payments-prod --filter ops-home/payments-units vet

# Bulk patch filtered units
cub unit update --patch --label reviewed=true --space "*" --filter ops-home/unapplied-changes

Filters combine with --where using AND logic, so you can further narrow results:

cub unit list --space "*" --filter ops-home/payments-units --where "Labels.Region = 'us-east'"

Create Views

A View defines which columns to show and how to sort results. Views can optionally include a Filter to control which entities are shown.

Simple view with metadata columns

Create a view that shows units with their space, target, and environment label:

cub view create --space ops-home by-environment --of Unit \
  --column Unit.Slug --column Space.Slug --column Target.Slug \
  --column Unit.Labels.Environment --order-by Unit.Labels.Environment

View with a filter

Attach a filter to a view so it both selects and formats results:

cub view create --space ops-home unapplied ops-home/unapplied-changes \
  --column Unit.Slug --column Space.Slug \
  --column Unit.HeadRevisionNum --column Unit.LiveRevisionNum \
  --column Unit.UpdatedAt

View with computed columns using CEL

Views can include columns computed from entity metadata using CEL expressions. The expression receives the full entity as ExtendedUnit and must return a value.

{
  "Columns": [
    {
      "Name": "Name",
      "ColumnType": "MetadataAttribute",
      "DataType": "string",
      "ColumnSource": { "MetadataAttribute": "Unit.Slug" }
    },
    {
      "Name": "Space",
      "ColumnType": "MetadataAttribute",
      "DataType": "string",
      "ColumnSource": { "MetadataAttribute": "Space.Slug" }
    },
    {
      "Name": "UnappliedChanges",
      "ColumnType": "MetadataExpression",
      "DataType": "string",
      "ColumnSource": {
        "MetadataExpression": "cel:has(ExtendedUnit.Unit) && ExtendedUnit.Unit.HeadRevisionNum > ExtendedUnit.Unit.LiveRevisionNum ? 'Yes' : 'No'"
      }
    },
    {
      "Name": "GateCount",
      "ColumnType": "MetadataExpression",
      "DataType": "int",
      "ColumnSource": {
        "MetadataExpression": "cel:has(ExtendedUnit.Unit) && has(ExtendedUnit.Unit.ApplyGates) ? string(size(ExtendedUnit.Unit.ApplyGates)) : '0'"
      }
    }
  ]
}

Create this view from a JSON file:

cat view-definition.json | cub view create --space ops-home --json --from-stdin computed-status --of Unit

Grouping and sorting

Views support grouping and multi-column sorting. GroupBy implies ascending sort order unless overridden.

cub view create --space ops-home by-target --of Unit \
  --column Unit.Slug --column Space.Slug --column Target.Slug \
  --group-by Target.Slug

For column-level sort control, use JSON input with GroupBy and OrderByDirection fields on individual columns.

Use Views with unit list

The --view flag on cub unit list applies a view's columns and optional filter:

# Apply the view across all spaces
cub unit list --space "*" --view ops-home/unapplied

# Apply a view within a specific space
cub unit list --space payments-prod --view ops-home/by-target

# Combine a view (without a filter) with a where expression
cub unit list --space "*" --view ops-home/by-environment --where "Labels.Application = 'payments'"

When --view is specified, the CLI displays the view's columns instead of the default columns. If the view includes GroupBy or OrderByDirection on columns, results are sorted accordingly.

Note

If a view has an attached Filter, you cannot also specify a separate --filter parameter. Either use a view with a filter, or use a view without a filter and pass --filter separately.

Record configuration values with Triggers

Labels are great for metadata you define yourself, but sometimes you want to surface values extracted from the configuration data — like the current container image or replica count — without writing CEL expressions or using DataPath columns. Readonly functions that return the AttributeValueList type can be used as Triggers to automatically extract values from configuration data and store them in the Unit's Values map.

Because these are Mutation event Triggers, they run after every configuration data change, keeping the stored values up to date automatically.

Create value-recording triggers

Use get-image (or get-image-reference) to record the current image of the first container:

cub trigger create --space ops-home Image Mutation Kubernetes/YAML get-image "@0"

The @0 argument targets the first container. You can also target containers by name (e.g., main).

Other readonly functions work as triggers too:

# Record the replica count
cub trigger create --space ops-home Replicas Mutation Kubernetes/YAML get-replicas

# Record a specific environment variable
cub trigger create --space ops-home DBHost Mutation Kubernetes/YAML get-env-var main DATABASE_HOST

The Values map key is <trigger-slug>/<attribute-name>. Functions return named attributes — for example, get-image returns the container-image attribute, so a Trigger with slug Image stores the value under the key Image/container-image. Similarly, get-replicas returns the replicas attribute, producing Replicas/replicas.

This naming scheme allows a single function to return multiple different attributes, each stored with a distinct key. If there are multiple AttributeValue results with the same attribute name, the first one wins.

Use recorded values in Views

Values map keys are referenced as a MetadataAttribute in View columns, just like Labels:

cub view create --space ops-home images --of Unit \
  --column Unit.Slug --column Space.Slug \
  --column Unit.Values.Image/container-image --column Unit.Labels.Environment \
  --order-by Unit.Labels.Environment

Use recorded values in Filters

Unlike computed View columns (MetadataExpression, DataExpression), Values can be referenced in filter expressions, similar to Labels:

# Find units running a specific image tag
cub filter create --space ops-home old-image Unit \
  --where-field "Values.Image/container-image LIKE '%:v1.2.%'"

# Find units with high replica counts
cub filter create --space ops-home high-replicas-value Unit \
  --where-field "Values.Replicas/replicas > '3'"

This makes Values especially powerful — they give you filterable, queryable data derived from configuration content, without the overhead of DataPath filters that parse configuration on every query.

Example: operational dashboard views

Here are some views useful for day-to-day operations:

# Overview grouped by target (deployment destination)
cub view create --space ops-home by-target --of Unit \
  --column Unit.Slug --column Space.Slug --column Target.Slug \
  --column Unit.UpdatedAt --group-by Target.Slug

# Overview grouped by space
cub view create --space ops-home by-space --of Unit \
  --column Unit.Slug --column Target.Slug \
  --column Unit.HeadRevisionNum --column Unit.LiveRevisionNum \
  --column Unit.UpdatedAt --group-by Space.Slug --column Space.Slug

# Overview grouped by environment label
cub view create --space ops-home by-environment --of Unit \
  --column Unit.Slug --column Space.Slug --column Target.Slug \
  --column Unit.Labels.Environment --group-by Unit.Labels.Environment

# Overview grouped by application layer
cub view create --space ops-home by-layer --of Unit \
  --column Unit.Slug --column Space.Slug --column Target.Slug \
  --column Unit.Labels.Layer --group-by Unit.Labels.Layer

# Units needing attention (attached to unapplied-changes filter)
cub view create --space ops-home needs-attention ops-home/unapplied-changes \
  --column Unit.Slug --column Space.Slug \
  --column Unit.HeadRevisionNum --column Unit.LiveRevisionNum \
  --column Unit.UpdatedAt --order-by Unit.UpdatedAt --order-by-direction DESC

Use them:

cub unit list --space "*" --view ops-home/by-target
cub unit list --space "*" --view ops-home/needs-attention

Managing Filters and Views

List, inspect, update, and delete Filters and Views like any other entity:

# List all filters and views in your home space
cub filter list --space ops-home
cub view list --space ops-home

# List across all spaces
cub filter list --space "*"
cub view list --space "*"

# Get details
cub filter get --space ops-home payments-units
cub view get --space ops-home by-target

# Update a filter's where expression
cub filter update --space ops-home payments-units Unit \
  --where-field "Labels.Application = 'payments' AND Labels.Environment != 'dev'"

# Delete
cub filter delete --space ops-home old-filter
cub view delete --space ops-home old-view