Skip to content

Open source · Apache 2.0

Open-source BI engine for building trusted analytics with AI agents

anfra lets data and product teams build and customize their own data apps with coding agents, on shared metrics defined once in a semantic layer

Quickstart
Install anfra following https://anfra.ai/docs/local-dev/installation, connect my data warehouse and build me a first app.
  1. anfra

    QueryFunnel, 5 steps, 1-year window

    FilterOrder status: completed, shipped

  2. Semantic layer

  3. Warehouse

“anfra is basically dbt for BI apps. The semantic layer is text in git, a coding agent writes the dashboard, the CLI checks it.” Read more (opens in a new tab)

Mark PhamAnalytics Engineer

“After about 30 minutes of setup, we had key dashboards and apps with built‑in interactions, out of the box, to track our usage.”

Thi NguyenProduct Manager, dbdiagram.io

“AI dashboards always felt like artifacts. anfra feels like production: the semantic layer, the SDK and the visuals all working in unison. Really awesome!”

Nick HernandezCo-founder & Analytics Consultant, sauzi.ai

Custom data apps

Design your own data apps

Any layout, any interaction, one prompt. Every number still comes from your governed metrics.

View all demos (opens in a new tab)
Open the live app: Cashflow sheet (opens in a new tab)

Build a cash flow statement I can switch between quarters and years, add metrics to, and break down by entity.

Open the live app: Cashflow sheet (opens in a new tab)

Inspect

Built by AI. Checkable by anyone

Your agent writes the app, but it doesn’t make up the numbers. Each one comes from a metric your team defined, and anyone using the app can check it

  • What a number means, who owns it and how it’s worked out
  • Its lineage, back to the metrics, fields and tables underneath
  • The rows and queries behind it, and a trust level for the whole app
Acme / Ecommerce overview
Ecommerce overview
MetricProfit $1.45M

Revenue after refunds, less what the goods sold cost us. Built on three other metrics.

Owned by Finance team
Trust level
Level 3Governed
  • From the semantic layerecommerce
  • A defined metricprofit
  • Filters on defined fieldsorders.ordered_at
  • Endorsednot yet
Formularevenue - refunds - cogs
Lineage
RevenueRefundsCOGS
Profit
Underlying data
MonthRevenueRefundsCOGSProfit
Jul 2026$352,980$10,590$211,790$130,600
Aug 2026$376,130$11,280$225,680$139,170
Sep 2026$403,510$12,110$242,110$149,290
  • What a number means, who owns it and how it’s worked out
  • Its lineage, back to the metrics, fields and tables underneath
  • The rows and queries behind it, and a trust level for the whole app

AI analytics via MCP

Your metrics, in the AI chat you already use

Claude, ChatGPT or any MCP client answers from your governed metrics.

  • Nothing new to learn
  • No extra AI bill
  • Trace any metric to its definition and lineage
Claude, ChatGPT and Cursor take turns answering a question about revenue with numbers from anfra. Each of those numbers carries a chip that opens its trace: the metric definition, the query, the SQL and the lineage

Why did revenue drop in January?

anfra · query revenue by month and region

Revenue was in January, down from December. NA fell the most, to , down : about a third of the total drop (Worked out by the assistant). Every region fell by a similar share, so it is the dip after the December peak, not one market.

anfra.acme.com/trace/q_7f3k2Coming soon

Revenue, December 2025 to January 2026

Revenue by month

AML
metric revenue {  label: 'Revenue'  type: 'number'  description: 'What customers paid for the items they ordered'  definition: @aql sum(order_items.quantity * order_items.unit_price) ;;}
  • datasets/ecommerce.dataset.aml
  • Finance data team
  • Last changed in a reviewed pull request, 12 days ago
MonthRevenue
Dec 2025$323,250
Jan 2026$240,990
  • Nothing new to learn
  • No extra AI bill
  • Trace any metric to its definition and lineage

PluginsComing soon

Extend your BI with plugins

Turn on features across every app, or build your own with your agent.

Plugin marketplace

Build with agents

One prompt, from warehouse to governed dashboard

Ask for a dashboard. Your agent turns your warehouse into models and metrics, then builds on top of them.

Read the quickstart (opens in a new tab)
  1. Install the CLI and the agent skills.

    curl -fsSL https://anfra.ai/install.sh | bash then anfra agent setup

  2. Add your credentials to .anfra/data_sources.yml.

    anfra init my-project

  3. It models your tables and defines the metrics, as files you can review.

    cd my-project && claude then Use the anfra-build-data-app skill. Build a revenue overview with a region filter.

  4. Every chart uses those metrics.

    apps/revenue-overview.html

  5. anfra serve runs it locally. anfra publish shares it with your team on anfra Cloud.

    anfra serve then anfra publish

Your prompt

Install anfra, connect it to my warehouse, then build a revenue dashboard with a region filter and publish it

us.anfra.ai/o/acme/apps/revenue-overview

Published

Revenue overview

Last 12 months
Revenue
$3.93M +18.2%
Orders
65,410
Avg. order
$60.08

Revenue by region

Monthly trend

Install

Get started with anfra

Install anfra following https://anfra.ai/docs/local-dev/installation, connect my data warehouse and build me a first app.

  • Claude Code
  • Cursor
  • Codex

What you need

  • macOS or Linuxx64 or ARM. Anywhere else, use the Docker image
  • A coding agentClaude Code, Cursor, Codex or any agent that can run commands
  • A warehouse loginPostgreSQL, Redshift, BigQuery, Snowflake, Databricks, ClickHouse, MySQL or a DuckDB file

How it works

The backend your agent builds data apps on

Everything a data app needs under it, open source, on your own warehouse.

JS SDK, docs (opens in a new tab)Your app asks for metrics by name, with filters and drill-downs and no SQL in the page
Your data apps
MCP server, docs (opens in a new tab)Coding and data agents read your models and query your metrics
AI data agents
Agent skills, docs (opens in a new tab)Teach your coding agent to model data, write queries and build data apps
Coding agents
EvalsMeasure how well agents work on your dataRoadmap
Your test set
anfra
Semantic layer, on amql.org (opens in a new tab)Metrics as code in AMQL, reviewed in git, with period comparisons and level of detail
PluginsExtend anfra with your own plugins, without waiting for usRoadmap
Query engine, docs (opens in a new tab)Compiles each request to SQL, runs it live on your warehouse and keeps the SQL that ran
Your warehouse
anfra is one binary with no LLM inside. Your apps and your own agents plug into its ports, and it queries your warehouse live, never copying the data.

AMQL

Built on an open, programmable semantic layer

AMQL, the semantic layer behind Holistics. Define metrics once as code, and every question compiles to SQL on your warehouse.

  • Programmable, not configured

    Metrics build on other metrics, and one AQL expression handles period comparisons, percent of total, running totals and level of detail

  • Open as in yours

    AML and AQL are plain-text files in your git, and every query compiles to SQL you can read

  • One model, every caller

    Apps through the JS SDK and agents over MCP ask for metrics by name and get the same numbers

In AMQL: defined once, works at any grain and filter

ecommerce.dataset.aml

AML
metric revenue {  definition: @aql    sum(order_items.amount) ;;}metric revenue_last_year {  definition: @aql    revenue | relative_period(      orders.created_at, interval(-1 year)    ) ;;}metric revenue_growth {  definition: @aql    safe_divide(      revenue - revenue_last_year,      revenue_last_year    ) ;;}
In SQL: the same, by month only

revenue_by_month.sql

SQL
WITH monthly AS (  SELECT date_trunc('month', o.created_at) AS month,         SUM(oi.amount) AS revenue  FROM orders o  JOIN order_items oi ON oi.order_id = o.id  GROUP BY 1)SELECT curr.month,       curr.revenue,       prev.revenue AS revenue_last_year,       (curr.revenue - prev.revenue)         / NULLIF(prev.revenue, 0) AS revenue_growthFROM monthly currLEFT JOIN monthly prev  ON prev.month = curr.month - INTERVAL '1 year'ORDER BY curr.month

JS SDK

Wire charts to metrics, not SQL

The JS SDK puts your semantic layer in the page. Query metrics as JS objects, bind them to any chart, and wire up filters and click-to-filter in a few lines.

the page asks for revenue by category, by name; anfra compiles the data team’s definitions to SQL

shop-analytics/apps/revenue-explorer.html

JavaScript
const app = Anfra.createApp({ title: 'Revenue explorer' })const byCategory = app.createQuery('byCategory', {  dataset: 'ecommerce',  aql: `explore {    dimensions { category: products.category }    measures { revenue: revenue }  }`,})const country = app.createFilter('country', {  dataset: 'ecommerce',  field: 'customers.country',})app.mapControl(country, byCategory, { field: 'customers.country' })app.subscribe(() => {  if (byCategory.state !== 'success') return  chart.setOption({ dataset: { source: byCategory.result.rows } })})await app.execute()

1 · SQL anfra ran on your warehouse

SQL
SELECT  "products"."category" AS "category",  SUM(("order_items"."quantity" * "products"."price")) AS "revenue"FROM  public.order_items "order_items"  LEFT JOIN public.orders "orders" ON "order_items"."order_id" = "orders"."id"  LEFT JOIN public.products "products" ON "order_items"."product_id" = "products"."id"  LEFT JOIN public.customers "customers" ON "orders"."customer_id" = "customers"."id"WHERE  "customers"."country" = 'Vietnam'GROUP BY  1
2 · Rows, drawn
  1. Services$91,500
  2. Software$68,234
  3. Hardware$23,747
  4. Parts$1,774
  1. No SQL in the pageThe page asks for revenue by name
  2. Filters travel as dataThe page sends a filter beside the query, as data, and anfra builds the SQL from it
  3. SandboxedEach app runs in a sandboxed frame and reaches data only through its host
  4. Your server decidesLog, change or refuse any call the page makes

Git workflow

BI as code, in your own repo

Every connection, model, metric and app is a plain file in git.

  • Reviewed in pull requests
  • Full history, easy rollback
  • Your agent checks its work before it ships
analyticsrevenue-metric
sales.dataset.amldatasets/sales.dataset.aml
YAML
# your warehouse; this file stays out of gitdata_sources:  warehouse:    type: postgresql    connection:      host: db.acme.internal      port: 5432      user: anfra      password: ••••••••      dbname: analytics
AML
Model orders {  type: 'table'  label: 'Orders'  data_source_name: 'warehouse'  table_name: 'public.orders'  dimension id { label: 'ID' type: 'number' primary_key: true }  dimension user_id { label: 'User ID' type: 'number' }  dimension amount { label: 'Amount' type: 'number' }  dimension created_at { label: 'Created at' type: 'datetime' }}
AML
Model users {  type: 'table'  label: 'Users'  data_source_name: 'warehouse'  table_name: 'public.users'  dimension id { label: 'ID' type: 'number' primary_key: true }  dimension region { label: 'Region' type: 'text' }}
AML
Dataset sales {  data_source_name: 'warehouse'  models: [orders, users]  relationships: [    relationship(orders.user_id > users.id, true)  ]  metric revenue {    label: 'Revenue'    definition: @aql sum(orders.amount) ;;  }  metric order_count {    label: 'Orders'    definition: @aql count(orders.id) ;;  }  metric aov {    label: 'Avg. order'    definition: @aql revenue / order_count ;;  }}
HTML
<h1>Revenue overview</h1><div id="kpis"></div><div id="by-region"></div><script>  const app = Anfra.createApp({ title: 'Revenue overview' })  const byRegion = app.createQuery('byRegion', {    dataset: 'sales',    aql: `explore {      dimensions { region: users.region }      measures { revenue: revenue }    }`,  })</script>
Markdown
# Agent instructionsThis is an anfra project. Metrics live indatasets/; apps query them by name and neverwrite their own SQL.Before you finish a change, run:- anfra validate- anfra query, to check the numbers- anfra serve, to open the app
AML
Dataset sales {  data_source_name: 'warehouse'  models: [orders, users]  relationships: [    relationship(orders.user_id > users.id, true)  ]  metric revenue {    label: 'Revenue'    definition: @aql sum(orders.amount) ;;  }  metric order_count {    label: 'Orders'    definition: @aql count(orders.id) ;;  }  metric aov {    label: 'Avg. order'    definition: @aql revenue / order_count ;;  }}
An anfra project: plain files in git. anfra validatePassedReviewApproved by the data team
  • Reviewed in pull requests
  • Full history, easy rollback
  • Your agent checks its work before it ships

Use cases

What you can build with anfra

Your coding agent builds the apps, as many as your team needs, in your own code and on your own warehouse

  • Your own BI tool

    The dashboards and apps your team asks for. The layout and the charts are yours, and the metrics are your data team’s.

    See live demos (opens in a new tab)
  • A backend for your AI data agent

    The agent searches your datasets and queries metrics by name, so its answers come from your definitions, not SQL it guessed

    Agent skills on GitHub (opens in a new tab)
  • Embedded analytics

    Apps inside your own product through the JS SDK, under your own login and look

    Host example on GitHub (opens in a new tab)

Deployment

Run it your way

Start on your laptop, then run the same project on your own server, or publish it to anfra Cloud

  1. On your machine

    Runs your apps while you and your agent build them, and reloads on every change. It’s for you: there are no logins.

    anfra serve
    Quickstart
  2. On your own server

    The same engine in a Docker image, on your infrastructure. It has no logins or permissions of its own, so put it where everyone who can reach it may see the data.

    docker run -p 7878:7878 -v "$PWD:/repo" ghcr.io/holistics/anfra
    Run it with Docker (opens in a new tab)
  3. On anfra CloudPublic beta

    Publish the project as it is. One command, no server.

    anfra publish
    Try the beta (opens in a new tab)
Public beta

anfra Cloud

anfra, hosted, with batteries included. The project you build locally publishes to it unchanged, and your team signs in to use it.

About anfra Cloud
  • Hosted for youNo server to run yourself
  • Users and rolesAdmins decide who builds and who views. SSO is on the way.
  • PermissionsOn the wayRow-level and viewer-level, so access to data follows each user
  • Sharing and auditOn the waySharing links and public links, with an audit trail of who did what

Community

Build it with us

Ask questions, share what you’ve built and tell us what anfra should do next.

anfra is the open-source framework you build BI with: the AMQL semantic layer, the query engine, the JS SDK and the MCP server. You run it yourself, on your machine or your own infrastructure.

anfra Cloud is anfra hosted for you, with what a whole team needs on top: sign-in, invitations and roles today, with SSO, row-level permissions, sharing and an audit trail on the way. It’s in beta in the US region, at us.anfra.ai, and projects you build locally run on it unchanged.