See yesterday's Azure spend by service and resource group every morning

Every morning: yesterday's Azure cost against the 7-day average, with the top services and resource groups and the one that moved.

Runs
Every day at 8:00
Uses
Azure
Posts
Stat tile

What lands on your board

Acme AzureAzure cost yesterday$612.48+15% vs previous period, worsevs last report
7-day average$540
Month to date$8,742
Top serviceVirtual Machines
An example with made-up numbers. Your agent posts your real ones.

What it does

Cost analysis in the Azure portal is thorough, and that is the problem: by the time you have picked the scope, the date range and the grouping, the meeting has moved on. Most teams only look when the monthly invoice is higher than expected, three weeks after the change that caused it.

The agent calls the Cost Management Query API once a morning for the last eight days, grouped by service and then by resource group, and compares yesterday with the week before it. A database tier someone bumped for a load test shows up the next day by name, not at month end.

How it works

  1. 1

    1Fix the scope

    Use a subscription (/subscriptions/{subscriptionId}) for one environment, or a billing account or management group to cover several. Costs are in the billing currency of that scope.

  2. 2Query daily cost by service

    POST https://management.azure.com/{scope}/providers/Microsoft.CostManagement/query?api-version=2026-06-01 (for example with az rest) with type: "ActualCost", timeframe: "Custom", a timePeriod covering the last 8 days, granularity: "Daily", aggregation: {totalCost: {name: "Cost", function: "Sum"}} and grouping: [{type: "Dimension", name: "ServiceName"}]. Follow nextLink if present.

  3. 3Query by resource group

    Run the same query grouped by ResourceGroupName, for yesterday only. Some older Enterprise Agreement scopes name the cost column PreTaxCost instead of Cost; use whichever the response lists in columns.

  4. 4

    4Compare

    Yesterday's total against the average of the 7 days before. Rank services and resource groups by cost and by change, and name any that rose more than 30% and $20. If yesterday is far below the average, say the data may still be filling in.

  5. 5

    5Report

    Yesterday's cost, the change, the top five services and top three resource groups with their change, month to date, and one line on what moved.

  6. Post it to the board

    With BRIEFKIN_TOKEN set, the agent sends the result as one card that updates in place every run. Without it, you get the report in the chat.

What you get

  • Yesterday's cost and the change against the 7-day average.
  • Top services with their change.
  • Top resource groups with their change.
  • Month to date in the billing currency.
  • One line on what moved and where to look.

Install and run it

Pick your agent, where the data comes from and how to schedule it; the commands below follow.

Agent
Data
Schedule
  1. Install the skill

    One command. It puts the SKILL.md in ~/.claude/skills and in ~/.agents/skills, which Codex, Cursor, Gemini CLI, Copilot CLI and OpenCode read too.

    shellcurl -fsSL https://briefkin.dev/skills/azure-daily-cost-report/install | sh
  2. Run it

    Ask Claude Code:

    promptRun the azure-daily-cost-report skill

    Or paste the prompt instead of installing:

    promptUsing the Azure Cost Management Query API (POST {scope}/providers/Microsoft.CostManagement/query, through az rest, read only) for my subscription, get ActualCost for the last 8 days with Daily granularity, summed, grouped by ServiceName; then yesterday only, grouped by ResourceGroupName. Use the cost column the response returns (Cost or PreTaxCost). Tell me yesterday's total and its change against the average of the 7 days before, the top five services and top three resource groups with their change, and any service that rose more than 30% and $20. Add month to date. If yesterday looks incomplete compared with the other days, say that the data may still be arriving.
  3. Put it on a schedule

    Every day at 8:00, from cron on any machine where Claude Code is signed in:

    crontab0 8 * * * claude -p "Run the azure-daily-cost-report skill"

    Add it with crontab -e. A laptop asleep at that time runs it when it wakes if you use launchd or Task Scheduler instead; GitHub Actions works for the API route.

  4. Send it to your board

    Connect Briefkin once with curl -fsSL https://briefkin.dev/install | sh and every run lands on your board as a stat tile. How setup works

View the SKILL.mdRaw file
SKILL.md---
name: azure-daily-cost-report
description: "Every morning: yesterday's Azure cost against the 7-day average, with the top services and resource groups and the one that moved. Use when the user asks for this, or when it runs on a schedule."
---

# Azure daily cost report

Every morning: yesterday's Azure cost against the 7-day average, with the top services and resource groups and the one that moved.

Cost analysis in the Azure portal is thorough, and that is the problem: by the time you have picked the scope, the date range and the grouping, the meeting has moved on. Most teams only look when the monthly invoice is higher than expected, three weeks after the change that caused it.

The agent calls the Cost Management Query API once a morning for the last eight days, grouped by service and then by resource group, and compares yesterday with the week before it. A database tier someone bumped for a load test shows up the next day by name, not at month end.

## Two ways to get the data

Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.

## Route A: API or MCP server

### What you need

- The Cost Management Reader role (or Reader) on the subscription or billing scope, used through `az login`, a service principal, or a managed identity.
- Calls go through `az rest` or any HTTP client with a token for `https://management.azure.com/`.

If something is missing, say what and stop; do not invent numbers.

### Steps

1. **Fix the scope**: Use a subscription (`/subscriptions/{subscriptionId}`) for one environment, or a billing account or management group to cover several. Costs are in the billing currency of that scope.
2. **Query daily cost by service** (Azure): `POST https://management.azure.com/{scope}/providers/Microsoft.CostManagement/query?api-version=2026-06-01` (for example with `az rest`) with `type: "ActualCost"`, `timeframe: "Custom"`, a `timePeriod` covering the last 8 days, `granularity: "Daily"`, `aggregation: {totalCost: {name: "Cost", function: "Sum"}}` and `grouping: [{type: "Dimension", name: "ServiceName"}]`. Follow `nextLink` if present.
3. **Query by resource group** (Azure): Run the same query grouped by `ResourceGroupName`, for yesterday only. Some older Enterprise Agreement scopes name the cost column `PreTaxCost` instead of `Cost`; use whichever the response lists in `columns`.
4. **Compare**: Yesterday's total against the average of the 7 days before. Rank services and resource groups by cost and by change, and name any that rose more than 30% and $20. If yesterday is far below the average, say the data may still be filling in.
5. **Report**: Yesterday's cost, the change, the top five services and top three resource groups with their change, month to date, and one line on what moved.

## Route B: the browser

### What you need

- Signed in to the Azure portal with the Cost Management Reader role (or Reader) on the subscription or billing scope; a billing account scope needs a billing reader role there.

If something is missing, say what and stop; do not invent numbers.

### Steps

Start at https://portal.azure.com/#view/Microsoft_Azure_CostManagement/Menu/~/costanalysis. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.

1. **Pick the scope**: The link opens **Cost Management** > **Cost analysis**. Click the scope name at the top and choose the subscription, or a management group or billing account to cover several. The currency shown is the billing currency of that scope.
2. **Daily cost by service**: Switch the view to **Daily costs** (the customizable view), set the date picker to a custom range covering the last 8 days, keep **Granularity** at `Daily` and set **Group by** to `Service name`. Costs are **Actual cost** by default; leave that.
3. **Download the table**: The chart legend caps the number of services and merges the rest into "Other", so click **Download** and choose Excel or CSV for the per-day, per-service rows. From the file, take yesterday's total, the average of the 7 days before, and each service's change.
4. **Resource groups and month to date**: Change **Group by** to `Resource group name` with the date range set to yesterday only and read the top three. Then switch to the **Accumulated costs** view with the date set to this month for month to date and the portal's forecast line.
5. **Report**: Yesterday's cost and the change against the 7-day average, the top five services and top three resource groups with their change, month to date, and a line on what moved. Flag any service up more than 30% and $20.

Note: Azure services report usage on their own schedules, so yesterday can keep filling in for several hours after midnight, sometimes a day. Cost analysis rounds in the chart; use the download for exact figures. Saved views belong to the person, so an agent changing the view does not affect colleagues, but save nothing.

## The report

- **Yesterday's cost** and the change against the 7-day average.
- **Top services** with their change.
- **Top resource groups** with their change.
- **Month to date** in the billing currency.
- One line on what moved and where to look.

## Post it to Briefkin

When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.

```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
  -H "authorization: Bearer $BRIEFKIN_TOKEN" \
  -H "content-type: application/json" \
  -d @- <<'JSON'
{
  "v": 1,
  "event_id": "azure-daily-cost-report/<date of this run, e.g. 2026-10-16>",
  "item_key": "azure-daily-cost-report",
  "project": "Acme Azure",
  "source": "Azure daily cost report skill",
  "kind": "metric",
  "title": "Yesterday cost $612, 13% above the 7-day average",
  "metric": {
    "label": "Azure cost yesterday",
    "value": 612.48,
    "prefix": "$",
    "better": "lower",
    "period_start": "<start of the period, ISO 8601>",
    "period_end": "<end of the period, ISO 8601>"
  },
  "glance": [
    {
      "type": "Grid",
      "props": {
        "columns": 3
      },
      "children": [
        {
          "type": "Stat",
          "props": {
            "label": "7-day average",
            "value": 540,
            "prefix": "$"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Month to date",
            "value": 8742,
            "prefix": "$"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Top service",
            "value": "Virtual Machines"
          }
        }
      ]
    }
  ],
  "widget": [
    {
      "type": "Table",
      "props": {
        "columns": [
          "Service",
          "Yesterday",
          "vs 7-day avg"
        ],
        "align": [
          "left",
          "right",
          "right"
        ],
        "rows": [
          [
            "Virtual Machines",
            "$241.30",
            "+2%"
          ],
          [
            "Azure SQL Database",
            "$118.60",
            "0%"
          ],
          [
            "Azure Cosmos DB",
            "$92.15",
            "+197%"
          ],
          [
            "Storage",
            "$64.20",
            "+3%"
          ],
          [
            "Bandwidth",
            "$28.40",
            "-4%"
          ],
          [
            "Everything else",
            "$67.83",
            "+5%"
          ]
        ]
      }
    },
    {
      "type": "Bars",
      "props": {
        "unit": "USD",
        "items": [
          {
            "label": "rg-prod-app",
            "value": 402.1
          },
          {
            "label": "rg-data",
            "value": 148.25
          },
          {
            "label": "rg-shared",
            "value": 62.13
          }
        ]
      }
    },
    {
      "type": "Callout",
      "props": {
        "text": "Cosmos DB in rg-data went from about $31 to $92 a day. Provisioned throughput on the events container was raised on Oct 15.",
        "tone": "warn"
      }
    }
  ],
  "size": "md"
}
JSON
```

Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.

Set `period_start` and `period_end` to the window the number covers: the tile names it from them ("Last 7 days", "Today", "This month"). For a count right now (open items, a balance), send `"period_label": ""` so no period shows; for another name, send it as `period_label` (at most 24 characters).

## Run it on a schedule

Suggested: Every day at 8:00 (`0 8 * * *`). From cron, with the agent signed in on that machine:

```bash
0 8 * * * claude -p "Run the azure-daily-cost-report skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```

Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/azure-daily-cost-report#schedule

Source: https://briefkin.dev/skills/azure-daily-cost-report

What your agent needs

  • The Cost Management Reader role (or Reader) on the subscription or billing scope, used through az login, a service principal, or a managed identity.

  • Calls go through az rest or any HTTP client with a token for https://management.azure.com/.

Connecting Azure

  1. Azure MCP Server, Microsoft's official server. It runs locally with npx -y @azure/mcp@latest server start and signs in with your local Azure credentials, so run az login first. In Claude Code, install the Azure plugin with /plugin install azure@claude-plugins-official, or add the server directly: claude mcp add azure -- npx -y @azure/mcp@latest server start --read-only. Cursor and Codex run the same command. It covers Advisor recommendations, Monitor logs and metrics, retail pricing and most resource types, but has no Cost Management query tool, so cost totals go through the API below (docs).
  2. Cost Management API with the Azure CLI or a service principal. az rest --method post against the query endpoint runs with your CLI login. For unattended runs, create a service principal and set AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET, with AZURE_SUBSCRIPTION_ID for the scope.

Assign Cost Management Reader (and Reader if the report lists resources) only on the subscriptions or resource groups the report covers. --read-only keeps the MCP server to read tools, but Azure RBAC is what actually limits it.

Questions

Why can yesterday look low and then go up?

Azure services report usage to Cost Management on their own schedules, so a day's cost often keeps filling in for several hours after midnight, sometimes up to a day. The 8:00 run is usually close; if yesterday is far below the average, the card says so instead of celebrating a cheap day.

Can it cover several subscriptions?

Yes. Use a management group or billing account as the scope and add SubscriptionName as the first grouping, or run once per subscription with its own card. Querying a billing scope needs a billing reader role there, not only Reader on each subscription.

Do I need Briefkin to use the Azure daily cost report skill?

No. The skill runs with your own agent and gives you the report in the chat. With a Briefkin token set, each run also posts it to your board as a stat tile, so you can glance at it instead of asking again.

Which agents can run it?

Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, OpenCode, Windsurf and Amp all read SKILL.md files. The install command puts it in ~/.claude/skills and ~/.agents/skills, where they look. ChatGPT, the Claude app and Grok take the prompt instead. Pick your agent under "Install and run it" and the commands change to match.

Can it work without an API or MCP server, from my browser?

Yes. Switch the data source to "Your browser" and the steps change to the Azure pages themselves: the agent opens portal.azure.com/#view/Microsoft_Azure_CostManagement/Menu/~/costanalysis in a browser you are signed in to and reads the numbers off the page. Claude Code, Codex, Cursor, Claude app and ChatGPT can drive a browser out of the box; Gemini CLI, Copilot CLI and OpenCode need a Playwright or Chrome DevTools MCP server first. It is slower than the API and needs you signed in, so it suits a report you run by hand or from a scheduler on your own computer.

Watch azure cost yesterday on your board, run after run

Skills are free to use with any agent. Briefkin is where their results land: one board for every report, number and question your agents send, with a ping when something needs you.

Free during the open beta. No card.