pengelbrecht/skills · Archived

metricly-consume

How to query Metricly correctly to answer analytical questions.

First seen May 6, 2026

Installation

$ npx skills add pengelbrecht/skills --skill metricly-consume

Summary

  • How to query Metricly correctly to answer analytical questions.
  • Use when the user is asking analytical/business questions, when an agent is connected to a Metricly MCP server, when running `metricly query ...` from the terminal, or when scripting against Metricly's REST API.
  • Covers all three surfaces (MCP, CLI, REST) — same principles, different invocations.

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from pengelbrecht/skills · top by installs.

npx skills add pengelbrecht/skills

Browse all from pengelbrecht/skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1
License LICENSE
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Declared agents claude-code

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 9,816 B
  • docs SUMMARY.md 386 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 3 installs

SKILL.md

Querying Metricly to answer analytical questions

You are querying Metricly. Three surfaces are available — pick the one the caller is using:

  • MCP — agent connected to a Metricly MCP server (Claude

Desktop, Claude Code via stdio, etc.). Tool calls.

  • CLImetricly from the terminal. Shell commands.
  • REST — direct HTTP. Scripts, integrations.

The principles below are surface-agnostic. The conventions come from real production traces; departing from them produces misleading numbers.

Surface cheatsheet

Operation MCP tool CLI REST
List metrics list_metrics() metricly metrics list GET /api/semantic-layer/metrics
List dimensions list_dimensions() metricly dimensions list GET /api/semantic-layer/dimensions
Explain one metric explainmetric(metricname) metricly metrics show <name> GET /api/semantic-layer/metrics/<name>
Query query_metrics(params) metricly query -m <name> [-d ...] [-g month] ... POST /query with JSON body
Read business_context metricly://context resource metricly business-context get GET /api/context
Check business_context size businesscontextedit show_size metricly business-context size (no dedicated route — use GET /api/context and measure)
Org's published skill (this skill, served via SKILL.md) metricly skill instructions consume GET /api/v1/skill/consume/instructions

All three surfaces hit the same backend, semantic layer, and authorisation rules. The org's business_context document and each metric's description are the same bytes in all three.

1. The discovery pattern

For any analytical question, start with two calls:

  1. List metrics — every metric in the org, with descriptions.
  2. List dimensions — every groupable dimension, with descriptions.

Then run the actual query. Don't skip the catalog; metric names are not self-describing, and "obvious" metrics like total_revenue differ across orgs in unit, source, and standing filter rules.

You can keep the catalog in conversation context (MCP) or in a shell variable / scripting state (CLI / REST) across follow-up questions. Drilldowns go straight to query; only re-list if the user pivots to a topic the catalog doesn't cover.

2. Read the description fields

The description on each metric and dimension is authoritative — it's the source of truth for unit, computation, source rollup, filter rules, and caveats. Read it. Do not paraphrase from the metric name. Don't infer from the metric name what unit it's in.

What the description tells you:

  • Unit — DKK, count, %, hours. State it back to the user

explicitly in the answer.

  • Source rollup — which systems contribute. If the user asks

"how much revenue from Stripe?" and the metric rolls up Stripe + Shopify, say so.

  • Caveats — temporal discontinuities, methodology changes,

bug-fix dates. Honor them (see §5).

  • Standing filter rules — "for B2B, pair with…". Apply them

unless the user explicitly overrides.

  • Derived-field pointers — "use event_segment, not raw

event_type". Follow them (see §4).

The descriptions are byte-identical across MCP, CLI, and REST — authored once in dbt YAML, served everywhere.

3. Apply standing filter rules from descriptions

If a metric's description says "pair with status='paid' to exclude voided invoices", include that filter unless the user explicitly asks for the unfiltered view. The author wrote it because querying without it is a known footgun.

  • MCP: pass through query_metrics(filter=...) (where supported)

or call out the rule in your answer when the surface can't apply it programmatically.

  • CLI: metricly query doesn't yet expose ad-hoc filters; if a

filter rule applies, mention it in your answer to the user.

  • REST: include the filter in the POST body to /query.

Don't argue. Don't substitute your own interpretation. The description is closer to the warehouse than you are.

4. Prefer derived dimensions when descriptions point that way

Descriptions often steer you to a derived dimension over a raw one (customersegment over customer.tier, eventsegment over event_type). The derived version layers business logic the raw field doesn't capture; the raw field is usually stale or misleading.

Use the qualified name verbatim from the dimensions catalog (e.g. posorderline__venuename, not venuename). The prefix names the semantic model the dimension lives on.

5. Honor temporal discontinuities

When a metric description warns "pre-X date is unreliable" or "ETL bug fixed Y date", segment your query and tell the user about the discontinuity in your answer.

Example: if a description says "pre-2024-04-01 numbers exclude refunds; ETL bug fixed 2024-04-15", and the user asks for the year-over-year trend across that boundary, run two queries (before/after) and call out the methodology change rather than silently quoting a single misleading trend.

This applies regardless of surface — same warehouse, same boundaries.

6. Refuse hopeless queries honestly

If a question requires data the catalog doesn't expose, or the business_context warns the relevant system isn't synced, say so. Don't run a query against the closest-named metric and report a misleading number.

Examples of honest refusals:

  • "I can't answer how many emails went out — business_context

notes the org doesn't sync staff mailboxes."

  • "I can't answer attribution by paid-search keyword — there's no

metric or dimension in the catalog that captures search keyword."

7. Tool / response error recovery

Errors come back with a code and a suggestion (the canonical spec name; older paths still expose hint as an alias). Follow the suggestion.

Codes you'll see:

  • METRICNOTFOUND — suggestion lists available metric names.

Don't retry with the same name; pick from the suggestion or ask the user what they meant.

  • QUICKMETRICNOT_FOUND — same pattern for qm: prefixed

derived metrics.

  • NO_DATA — the metric exists but the date range / filter

combination returned nothing. Tell the user; don't fabricate a zero.

  • NOBASEMETRICS — quick metric expression has no dependencies

to resolve. Almost always a config bug; surface it.

  • EXCEEDSINSTRUCTIONSCAPbusinesscontextedit write

rejected because the new content would exceed the 2000-byte UTF-8 cap. The error includes currentbytes and capbytes; trim the content, don't loop.

When the error message is a qualified-dimension complaint (e.g. venuename was rejected, expecting posorder_line__venue_name), retry with the qualified name once. Don't loop on the same error.

Surface differences:

  • MCP: errors come back as a {error, code, suggestion} dict

in the tool response. suggestion is the canonical field; hint mirrors it for back-compat.

  • CLI: the error prints with a friendly "✗ Error: …" prefix

and a hint line. Exit code is 1.

  • REST: HTTP 4xx/5xx with JSON body

{"detail": {"message", "code", "suggestion", ...}}.

8. Multi-turn / multi-call efficiency

After the catalog is loaded once:

  • Drilldowns ("show me the same broken down by region") go

straight to the query call. No re-discovery needed.

  • Comparison questions ("how does this compare to last year?")

are a second query call with adjusted dates.

  • Refinements ("can you exclude internal accounts?") add a

filter; respect any standing rules from the metric description on top of the user's ad-hoc filter.

The catalog is only stale if the user pivots to a brand-new analytical area; in that case, re-list.

9. The org's business_context document

Cross-cutting org orientation lives in business_context — what the org sells, what's synced, what's NOT synced, cross-cutting derivation rules. Hard cap: 2000 UTF-8 bytes.

How it reaches you:

  • MCP: the business_context is appended to the server's

instructions blob at initialize (within Claude Code's 2KB total cap). You see it from turn 1 — no fetch needed. Apply it consistently; refuse honestly when it says a system isn't synced.

  • CLI: metricly business-context get prints it.

metricly business-context size shows the byte budget.

  • REST: GET /api/context returns {"content": "..."}.

Treat business_context as part of the same authoritative layer as metric descriptions. Same provenance (dbt repo via the manifest workflow), same trust level.

That's the working agreement. Same principles, three surfaces — do this and the answers will be right.