MetricFlow exposes two CLI interfaces for querying metrics: mf (dbt Core) and dbt sl (dbt Cloud). The commands are equivalent in what they can express; the syntax differs slightly between them. The dbt Cloud semantic layer also adds JDBC, GraphQL, and REST APIs for BI tool connections — those aren’t available in Core.
Generating the semantic manifest
Before any query works, MetricFlow needs a compiled semantic manifest. This is an artifact that tells MetricFlow what semantic models and metrics exist, derived from your YAML definitions.
dbt parseRun this any time you change semantic model or metric YAML. If you query after a YAML change without re-parsing, MetricFlow will work against the previous manifest and won’t reflect your changes.
The manifest lives in target/semantic_manifest.json. You don’t need to touch this file directly — MetricFlow reads it automatically.
Basic query syntax
The core query structure is --metrics plus optional --group-by:
# dbt Coremf query --metrics revenue --group-by metric_time
# dbt Clouddbt sl query --metrics revenue --group-by metric_timemetric_time is a built-in dimension available on any metric. It uses the agg_time_dimension configured on the underlying semantic model and supports automatic granularity handling.
Querying multiple metrics at once works as long as they share compatible semantic models (MetricFlow can join them through shared entities):
mf query --metrics revenue,orders --group-by metric_time,order__channelThe result is a single query with both metrics as columns, sliced by time and channel.
Dimension references
Dimension names in group-by clauses follow the pattern semantic_model__dimension_name. For the orders semantic model with an order__channel dimension:
mf query --metrics revenue --group-by metric_time,order__channelThis resolves to grouping the revenue metric by the order__channel categorical dimension on the orders semantic model.
You can explore what dimensions are available for a given metric:
mf list dimensions --metrics revenueThis is useful when you’re not sure which dimensions are compatible with a metric — MetricFlow only lists dimensions that can be reached through the semantic graph from that metric’s semantic model.
Filtering with —where
The --where flag applies filters using a Jinja-like syntax that references dimensions through MetricFlow’s resolution engine. You don’t write raw SQL column names — you reference dimensions by their semantic path.
mf query --metrics revenue \ --group-by metric_time \ --where "{{ Dimension('orders__order__channel') }} = 'web'"The syntax is {{ Dimension('semantic_model__dimension_name') }}. MetricFlow resolves this to the correct column and table, handling any joins required to reach the dimension.
For time dimensions with a specific granularity:
mf query --metrics revenue \ --group-by metric_time \ --where "{{ TimeDimension('orders__order__created_at', 'month') }} >= '2025-01-01'"The second argument to TimeDimension() sets the truncation granularity. This matters when your filter value is a period boundary — filtering at month grain truncates dates to the first of the month before comparing, which is different from filtering at day grain.
Multiple conditions work with AND:
mf query --metrics revenue,orders \ --group-by metric_time,order__status \ --where "{{ Dimension('orders__order__channel') }} = 'web' AND {{ Dimension('orders__order__status') }} != 'cancelled'"Controlling time granularity
By default, metric_time returns data at the granularity of the underlying time dimension (typically day). You can request coarser granularity:
mf query --metrics revenue --group-by metric_time__monthThe double-underscore granularity suffix works for __day, __week, __month, __quarter, and __year. MetricFlow truncates the time dimension to the requested granularity and aggregates accordingly.
Validation before querying
Before querying, validate that your YAML definitions parse without errors:
# dbt Coremf validate-configs
# dbt Clouddbt sl validateCommon failure modes:
- “ensure that you’ve ran an artifacts…” — Run
dbt parseordbt buildfirst to generate the semantic manifest. - Dimensions not appearing — Every dimension needs a primary entity in its semantic model.
- Metafont conflict on macOS — The
mfcommand can conflict with the Metafont LaTeX package. Uninstall the LaTeX package ifmfgives unexpected output.
The --verbose-issues --show-all flags on validation output more detail when debugging failures:
mf validate-configs --verbose-issues --show-allWhat CLI querying is good for
The CLI is suited for development-time exploration: checking that a new metric definition returns expected values, testing filter syntax before encoding it in YAML, and validating that joins work as expected across semantic models.
For production usage, dbt Core’s CLI is the only interface available besides raw SQL against the warehouse. dbt Cloud adds the JDBC and GraphQL APIs that BI tools connect to — every dashboard tool can then consume the same governed metric definitions through the API rather than writing its own SQL.