databricks-cost-audit

databricks-cost-audit is a skill for Claude Code from orchestra-hq/orchestra-skills. It costs 126 tokens per session (8,678 once invoked), scanned A, original, MIT.

A one-off audit of Databricks spending and usage. Databricks is a data platform, and the audit checks its system tables, which are built-in records about billing, compute, and queries.

In plain words
What is it for?
It is for running ten cost checks, ranking findings by estimated savings, writing them to a Delta table, and summarising new and unresolved issues.
Why use it?
It helps find expensive or wasteful workloads and keeps a dated record of findings instead of relying on manual cost checks.

Skill for Claude Code

Written for Claude Code: shipped in a Claude Code plugin.

Needs its repository: it runs a file that does not travel with it, so clone the repository first. The line is python scripts/audit.py.

Part of the orchestra plugin — 19 skills, 1 hook shipped together

Good fit It is for running ten cost checks, ranking findings by estimated savings, writing them to a Delta table, and summarising new and unresolved issues.

Compare 6 skills from other repositories ↓
Install

Getting it into your agent

It runs from inside its repository, so the clone comes first — what it calls does not travel with the file alone.

Clone the repo
git clone --depth 1 https://github.com/orchestra-hq/orchestra-skills
agentmods
npx agentmods add skills/orchestra-hq/orchestra-skills/databricks-cost-audit

Made for: Claude Code.

Or install orchestra, the plugin that ships this one along with the rest of its 19 skills, 1 hook.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for databricks-cost-audit

README.md
[![agentmods](https://agentmods.dev/badge/skills/orchestra-hq/orchestra-skills/databricks-cost-audit/github.svg)](https://agentmods.dev/skills/orchestra-hq/orchestra-skills/databricks-cost-audit)
Your own site
<a href="https://agentmods.dev/skills/orchestra-hq/orchestra-skills/databricks-cost-audit"><img src="https://agentmods.dev/badge/skills/orchestra-hq/orchestra-skills/databricks-cost-audit/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for databricks-cost-audit

Your own site · 80×15
<a href="https://agentmods.dev/skills/orchestra-hq/orchestra-skills/databricks-cost-audit"><img src="https://agentmods.dev/badge/skills/orchestra-hq/orchestra-skills/databricks-cost-audit.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 126 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 8,678 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00126 $0.08678
Opus 5.5 $0.00050 $0.03471
Sonnet 5.5 $0.00025 $0.01736
Haiku 4.5 $0.00013 $0.00868

Measured 1mo ago against content hash c8a37916643f, method: parsed. Prices are Anthropic first-party input rates as of 2026-10-07, from the pricing page.

Security

Grade A, and why

databricks-cost-audit scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 1mo ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

skills/orchestra/skills/databricks-cost-audit/SKILL.md · 827 lines

How it starts

The opening of the file, as written. The whole thing — 827 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Requirements:

databricks-sql-connector>=3.0.0

audit.py

#!/usr/bin/env python3
"""
Daily Databricks cost-optimisation audit.

Connects to a SQL warehouse, runs the checks in checks.py against system tables,
persists ranked findings to a Delta table (idempotent per day), and prints a
JSON + markdown summary that highlights what's new today.

Usage:
    python audit.py                 # run all enabled checks, write findings, print summary
    python audit.py --dry-run       # print the SQL for each check, execute nothing
    python audit.py --no-write      # run checks, return findings, don't persist
    python audit.py --check C05      # run a single check by id prefix

Env: see SKILL.md. Requires databricks-sql-connector.
"""
import argparse
import datetime as dt
import json
import os
import sys
import traceback

from checks import CHECKS, CONFIG

# --------------------------------------------------------------------------- #
# Config from environment
# --------------------------------------------------------------------------- #
CATALOG = os.environ.get("AUDIT_CATALOG", "main")
SCHEMA = os.environ.get("AUDIT_SCHEMA", "cost_audit")
TABLE = os.environ.get("AUDIT_TABLE", "findings")
FQ_TABLE = f"{CATALOG}.{SCHEMA}.{TABLE}"

# Threshold overrides (env wins over checks.CONFIG defaults)
_ENV_TUNING = {
    "AUDIT_LOOKBACK_DAYS": ("lookback", int),
    "AUDIT_MIN_COST_USD": ("min_cost", float),
    "AUDIT_IDLE_CPU_PCT": ("idle_cpu", float),
    "AUDIT_MAX_AUTOTERM_MIN": ("max_autoterm", int),
    "AUDIT_BIG_WORKERS": ("big_workers", int),
    "AUDIT_REPEAT_QUERY_RUNS": ("repeat_runs", int),
}
for env_key, (cfg_key, cast) in _ENV_TUNING.items():
    if env_key in os.environ:
        CONFIG[cfg_key] = cast(os.environ[env_key])

ENABLE_C11 = os.environ.get("AUDIT_ENABLE_C11", "0") == "1"

FINDINGS_COLS = (
    "run_date, check_id, check_name, severity, resource_type, resource_id, "
    "resource_name, owner, workspace_id, detail, est_monthly_saving_usd"
)


def connect():
    """Open a Databricks SQL connection from env vars."""
    try:
        from databricks import sql
    except ImportError:
        sys.exit("databricks-sql-connector is not installed. `pip install databricks-sql-connector`")

    host = os.environ.get("DATABRICKS_HOST")
    http_path = os.environ.get("DATABRICKS_HTTP_PATH")
    token = os.environ.get("DATABRICKS_TOKEN")
    missing = [k for k, v in {
        "DATABRICKS_HOST": host,
        "DATABRICKS_HTTP_PATH": http_path,
        "DATABRICKS_TOKEN": token,
    }.items() if not v]
    if missing:
        sys.exit(f"Missing required env vars: {', '.join(missing)}")

    return sql.connect(
        server_hostname=host.replace("https://", "").rstrip("/"),
        http_path=http_path,
        access_token=token,
    )


def ensure_table(cur):
    cur.execute(f"CREATE SCHEMA IF NOT EXISTS {CATALOG}.{SCHEMA}")
    cur.execute(f"""
        CREATE TABLE IF NOT EXISTS {FQ_TABLE} (
          run_date DATE, check_id STRING, check_name STRING, severity STRING,
          resource_type STRING, resource_id STRING, resource_name STRING, owner STRING,
          workspace_id STRING, detail STRING, est_monthly_saving_usd DOUBLE
        ) USING DELTA
    """)


def selected_checks(only):
    checks = [c for c in CHECKS if not c.get("optional") or ENABLE_C11]
    if only:
        checks = [c for c in checks if c["id"].upper().startswith(only.upper())]
    return checks


def run(args):
    checks = selected_checks(args.check)
    if not checks:
        sys.exit(f"No checks matched '{args.check}'")

    if args.dry_run:
        for c in checks:
            print(f"\n-- {c['id']}: {c['name']}\n{c['sql'].format(**CONFIG)}")
        return

    conn = connect()
    cur = conn.cursor()
    ran, skipped = [], []

    try:
        if not args.no_write:
            ensure_table(cur)
            cur.execute(f"DELETE FROM {FQ_TABLE} WHERE run_date = current_date()")

        for c in checks:
            body = c["sql"].format(**CONFIG)
            try:
                if args.no_write:
                    cur.execute(body)  # validates + returns rows, persists nothing
                    n = len(cur.fetchall())
                else:
                    cur.execute(f"INSERT INTO {FQ_TABLE} ({FINDINGS_COLS})\n{body}")
                    n = cur.rowcount if cur.rowcount is not None and cur.rowcount >= 0 else "?"
                ran.append(c["id"])
                print(f"  [ok]   {c['id']}: {n} findings", file=sys.stderr)
            except Exception as e:  # one check failing must not abort the run
                skipped.append({"id": c["id"], "needs": c["needs"], "error": str(e).splitlines()[0]})
                print(f"  [skip] {c['id']}: {str(e).splitlines()[0]}", file=sys.stderr)

        summary = build_summary(cur, ran, skipped) if not args.no_write else {
            "note": "--no-write: findings not persisted, no trend/summary available",
            "checks_ran": ran, "checks_skipped": skipped,
        }
    finally:
        cur.close()
        conn.close()

    emit(summary)


def build_summary(cur, ran, skipped):
    """Refresh the trend view and pull today's ranked findings."""
    cur.execute(f"""
        CREATE OR REPLACE VIEW {FQ_TABLE}_summary AS
        WITH hist AS (
          SELECT check_id, resource_id,
                 min(run_date) AS first_seen, max(run_date) AS last_seen
          FROM {FQ_TABLE}
          GROUP BY check_id, resource_id
        )
        SELECT f.*, h.first_seen, h.last_seen,
               datediff(h.last_seen, h.first_seen) AS days_open,
               (h.first_seen = f.run_date)         AS is_new
        FROM {FQ_TABLE} f
        JOIN hist h ON f.check_id = h.check_id AND f.resource_id = h.resource_id
        WHERE f.run_date = (SELECT max(run_date) FROM {FQ_TABLE})
    """)

    cur.execute(f"""
        SELECT count(*)                              AS n_findings,
               round(sum(coalesce(est_monthly_saving_usd, 0)), 0) AS est_saving,
               count_if(is_new)                      AS n_new,
               round(sum(CASE WHEN is_new THEN coalesce(est_monthly_saving_usd, 0) END), 0) AS new_saving
        FROM {FQ_TABLE}_summary
    """)
    n_findings, est_saving, n_new, new_saving = cur.fetchone()

    cur.execute(f"""
        SELECT check_id, severity, resource_type, resource_name, detail,
               est_monthly_saving_usd, is_new, days_open
        FROM {FQ_TABLE}_summary
        ORDER BY coalesce(est_monthly_saving_usd, 0) DESC, is_new DESC
        LIMIT 15
    """)
    cols = [d[0] for d in cur.description]
    top = [dict(zip(cols, r)) for r in cur.fetchall()]

    cur.execute(f"""
        SELECT check_id, count(*) AS n,
               round(sum(coalesce(est_monthly_saving_usd, 0)), 0) AS saving
        FROM {FQ_TABLE}_summary GROUP BY check_id ORDER BY saving DESC
    """)
    by_check = [dict(zip([d[0] for d in cur.description], r)) for r in cur.fetchall()]

    return {
        "run_date": str(dt.date.today()),
        "table": FQ_TABLE,
        "totals": {
            "findings": n_findings,
            "est_monthly_saving_usd": est_saving,
            "new_today": n_new,
            "new_today_saving_usd": new_saving,
        },
        "by_check": by_check,
        "top_findings": top,
        "checks_ran": ran,
        "checks_skipped": skipped,
    }


def emit(summary):
    """Print JSON (for the agent) + a markdown report (for humans / report file)."""
    print("\n===JSON===")
    print(json.dumps(summary, indent=2, default=str))

    md = render_markdown(summary)
    print("\n===MARKDOWN===")
    print(md)

    try:
        out = os.path.join(os.path.dirname(os.path.dirname(__file__)), f"report_{dt.date.today()}.md")
        with open(out, "w", encoding="utf-8") as f:
            f.write(md)
        print(f"\nReport written to {out}", file=sys.stderr)
    except OSError:
        pass


def render_markdown(s):
    if "totals" not in s:
        return f"_{s.get('note', 'no summary')}_"
    t = s["totals"]
    lines = [
        f"# Databricks cost audit — {s['run_date']}",
        "",
        f"**Est. monthly saving identified: ${t['est_monthly_saving_usd']:,.0f}** "
        f"across {t['findings']} open findings.",
        f"**New today: {t['new_today']}** findings (${t['new_today_saving_usd'] or 0:,.0f}).",
        "",
        "## Top opportunities",
        "",
        "| $/mo | New | Age(d) | Sev | Check | Resource | Detail |",
        "|-----:|:---:|-------:|-----|-------|----------|--------|",
    ]
    for f in s["top_findings"]:
        saving = f["est_monthly_saving_usd"]
        lines.append(
            f"| {('$' + format(saving, ',.0f')) if saving is not None else '—'} "
            f"| {'🆕' if f['is_new'] else ''} | {f['days_open']} | {f['severity']} "
            f"| {f['check_id']} | {f['resource_name'] or ''} | {f['detail']} |"
        )
    if s["checks_skipped"]:
        lines += ["", "## Skipped checks", ""]
        for c in s["checks_skipped"]:
            lines.append(f"- **{c['id']}** — {c['error']} (needs: {', '.join(c['needs'])})")
    return "\n".join(lines)


if __name__ == "__main__":
    p = argparse.ArgumentParser(description="Daily Databricks cost audit")
    p.add_argument("--dry-run", action="store_true", help="print SQL, execute nothing")
    p.add_argument("--no-write", action="store_true", help="run checks but don't persist findings")
    p.add_argument("--check", help="run a single check by id prefix, e.g. C05")
    try:
        run(p.parse_args())
    except SystemExit:
        raise
    except Exception:
        traceback.print_exc()
        sys.exit(1)

Read the full file on GitHub · 827 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 1mo ago First seen · 827 lines · 126 tokens per session scan A c8a37916643f

Subscribe to this mod's changes

databricks-cost-audit is a skill published in the GitHub repository orchestra-hq/orchestra-skills (9 stars, last pushed yesterday), licensed MIT. It adds 126 tokens to every session and 8,678 once invoked, about $0.0005 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-09.

Related

Other skills, from other repositories

local-ai-agents

Build local-first AI agents that run entirely on a developer workstation with Microsoft Foundry Local and Qwen function-calling models. Covers Small Language Models (SLMs), the OpenAI-compatible local endpoint, sandboxed local tools, local RAG with Chroma, local MCP servers, hybrid cloud/local routing, and the…

microsoft/ai-agents-for-beginners · 200 tokens

systematic-debugging

Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes.

obra/superpowers · 21 tokens

next-cache-components-adoption

Turn on Cache Components in a Next.js app and resolve the blocking routes it surfaces. Use when the user wants to enable, adopt, or migrate to Cache Components, flip the cacheComponents flag, work through a flood of blocking-prerender / instant validation errors, run the cache-components-instant-false codemod, or…

vercel/next.js · 95 tokens

chat-pet-sprite-creation

Use when creating or changing VS Code chat pet sprite art, sprite sheets, state animations, eye treatments, Stable/Insiders variants, or pet transitions under src/vs/workbench/contrib/chat/browser/widget/media/chatPet.

microsoft/vscode · 53 tokens

cpu-profile-analysis

Analyze V8/Chrome CPU profiles (.cpuprofile) and DevTools trace files (Trace-.json). Use when: profiling performance, investigating slow functions, comparing code paths, finding bottlenecks, analyzing timeToRequest, understanding call trees from sampling profiler data, analyzing layout/paint/rendering, investigating…

microsoft/vscode · 71 tokens

insight-error-page

Write or audit an insight-kind error page for the Next.js dev overlay. Use when creating a new errors/ .mdx page, auditing an existing one, or checking that a page matches the framework fix cards. Covers page structure, title alignment, FixCard cards with Copy prompt button, code snippets, terminology verification…

vercel/next.js · 83 tokens