Skip to content

Releases

Release notes

New features and improvements in anfra and anfra Cloud

  1. Newanfra0.20.0

    Publish with your team: anfra pull and anfra publish status

    A publish replaces everything the organization has. So when someone has published since your folder last pulled or published, anfra publish stops with pull_required, unless their changes are already in your folder.

    anfra publish status   # what a pull would bring in, and what a publish would send
    anfra pull             # merge what others published
    anfra publish --pull   # pull, then publish, in one step

    anfra pull merges file by file. Where you and a colleague changed the same lines, the file gets conflict markers that name who published the other side and when. Resolve them by hand, or keep one side's whole file with anfra pull --take local <path> or --take org <path>. anfra pull --abort undoes the pull.

    To join a repo the organization already publishes, run anfra init, then anfra pull --set-org https://us.anfra.ai/o/<org>.

    With git

    If your team shares work in git, merge to your shared branch and publish from it. anfra publish warns when you're on another branch, or have commits not pushed or files not committed, but never refuses for it. The anfra-publish skill walks your agent through both ways.

  2. Newanfra Cloud

    Set up a new organization, step by step

    Until an organization has a data app, its admins see the setup instead of an empty home. Choose how to go through it:

    • With an AI agent. Copy one prompt into Claude Code, Cursor or another coding agent. It installs anfra, builds a data app from your data, signs in and publishes.
    • By hand. Three steps, each with the commands to copy: install and sign in, build locally, and publish to your organization.
    The Set up Harborline Coffee page with Set up manually chosen: three steps, Install and sign in, Build locally (open, with the anfra init command and a prompt for your AI agent) and Publish, and a Go to app button
    Setting up a new organization by hand

    Each step is ticked off by itself as anfra Cloud sees it done, such as your CLI signing in or the first publish. Signing in is each admin's own step; the others count for the whole organization, whoever did them. Go to the app whenever you like; the setup stays on Home until the first app is published.

    Once the organization has apps, an admin whose CLI isn't signed in sees a "Build your own data apps" card at the foot of the sidebar, with the prompt and the quick start. Dismiss it to hide it.

    Setup is per organization, and only admins see it.

  3. Newanfra0.20.0

    Try anfra on a sample e-commerce project

    anfra init my-project --example
    cd my-project
    anfra serve

    The sample comes from holistics/anfra-sample-ecommerce (opens in a new tab): six models, an ecommerce dataset with its metrics, a 1.8 MB DuckDB file opened read-only, an overview Data App, and a wiki of the business rules. Its data source replaces the Postgres placeholder in .anfra/data_sources.yml, so queries work right away.

    The sample project's Ecommerce Overview Data App in anfra serve, with revenue, orders, average order value, customers and units sold, a revenue and orders chart, and orders by status
    The sample's overview Data App.

    In a terminal, a plain anfra init asks whether to add it, and the default is no. Without a terminal, anfra init never asks, and tells your agent to ask you first.

  4. Improvedanfra Cloud

    A refreshed look, in the app and its emails

    The app takes its fonts, colors and components from the same design as the rest of anfra. Menus, selects and the command palette look and behave as they do in anfra serve, and dark mode has its own fills instead of inverted light ones.

    The emails anfra Cloud sends, for a sign-in code and an invitation, are redesigned to match, with the inviting organization's name standing out.

  5. Newanfra0.19.0

    More relationship types, and AI context, in AML

    Relationships

    • Composite keys: a many_to_one or one_to_one relationship takes extra on key pairs.
    • Ranges: type: 'range' matches a row to the row whose window contains it, such as a price band or a slowly changing dimension (SCD Type 2).
    • Many to many: type: 'many_to_many' joins two models on a condition you write.
    • Filters: where restricts the match on either side, inside the join, so rows on the measure side aren't dropped.

    The relationship(a.x > b.id, true) shorthand still makes a single-key relationship. Write the others in full, with RelationshipConfig.

    AI context

    ai_context on a model, a dataset, a dimension, a measure or a metric holds what an agent should know about it, beyond its description.

    The anfra skills know both, so your coding agent can write them.

  6. Newanfra0.19.0

    See a Data App's runtime errors, and let your agent fix them

    When a Data App throws at runtime, anfra writes the error to anfra.log, along with each time the app mounts and when its file last changed. The anfra block in AGENTS.md points your coding agent at these logs, and the agent skills read them, so the agent can find and fix an error on its own.

    The JS SDK also lists runtime errors among the problems in the app's panel. Each error points at the query or control it came from.

    Set ANFRA_NO_APP_LOGS=1 to keep what a Data App reports out of anfra.log. The panel still lists it.

  7. Improvedanfra0.19.0
  8. Newanfra Cloud

    Connect Claude and other MCP clients to anfra Cloud

    Copy your MCP server URL from Settings → Connections and add it to an MCP client such as Claude or Cursor:

    https://us.anfra.ai/mcp
    

    The client opens anfra Cloud in your browser. Sign in, choose the organization to connect, and authorize. The client then searches, inspects and queries that organization's semantic layer as you, under your role: it sees no more than you can.

    The Authorize Claude page: the signed-in email, the requested permission to read and update the organization's data with your permissions, an Organization picker set to Harborline Coffee, the callback address to trust, and Cancel and Authorize buttons
    Approving Claude for one organization

    Each approval is for one organization. To connect another, add the server again. The client shows in Settings → Connections, where you can revoke its access.

  9. Newanfra Cloud

    Control MCP access for your organization

    In Settings → MCP, an admin decides how AI clients may connect to the organization.

    • MCP access. Turn it off and no one can connect a new MCP client, and connected ones stop working. The CLI keeps working. Turn it back on and members can reconnect.
    • Callback addresses. By default any client may connect. Switch to Only allow listed callbacks and new connections, the CLI's included, are approved only for the callback addresses you list. * matches anything. The list starts with local addresses, such as http://localhost:*/*, and cursor://*.
    Settings, MCP: Allow MCP connections switched on, Only allow listed callbacks chosen, and the allowed addresses http://localhost:*/*, http://127.0.0.1:*/*, http://[::1]:*/*, cursor://* and https://claude.ai/api/mcp/auth_callback

    The allowlist applies to new approvals. Tools already connected stay connected; revoke them from Settings → Connections.

  10. Newanfra Cloud

    Jump anywhere with the command palette

    The command palette lists every data app in the organization, and the view commands, such as toggling the sidebar. On a data app's page, the app's own commands come first, such as Inspect or a download.

    The command palette open over the Ecommerce Overview data app: the app's own commands first (Pick an element, Inspect, Reload Data App), then view commands (Hide sidebar, Switch to dark mode), then the organization's data apps

    Open it with ⌘K on a Mac or Ctrl+K elsewhere, or with the search at the top of the sidebar.

  11. Newanfra0.18.0

    Work in a session with anfra console

    $ anfra console
    > validate
    > \-d sales
    > c query
    query> explore { dimensions { status: orders.status } measures { orders: count(orders.id) } };;
    

    Each line runs a command, typed as after anfra. console query (or c query) switches to typing AQL, each query ending with ;;, and \c goes back. A line of flags, such as \-d sales, sets them for every command in the session.

    An anfra console session in a dark terminal: the dataset flag set with \-d ecommerce, c query switching to AQL, a query's result as a grid of order counts by status, and the framed query prompt above a status line naming the repo, the dataset and the running server

    Output is in the format for people, colored, with query results as a grid. History is kept between sessions, so Up reaches yesterday's entries. The console uses the repo's running anfra serve, or starts one for the session, so each query answers fast.

    \? shows where you are and what you can type, and \q, exit or Ctrl-D leaves. It needs a terminal, so an agent never starts one by accident.

  12. Improvedanfra Cloud

    A rebuilt sidebar, organization menu and settings

    • Search the organization's data apps from the top of the sidebar.
    • Drag its edge to resize it, or collapse it with a keyboard shortcut. While it is collapsed, point at its toggle to peek at it without opening it.
    • A data app's header shows where it sits, as a breadcrumb of its folders.

    Organization menu

    The organization menu at the top of the sidebar lists your organizations with your role in each, and the account you're signed in as.

    Settings

    Settings now has its own navigation in the sidebar, in two groups: Personal (Account, Connections) for everyone, and Organization (Data sources, Members & roles, Data apps, Plugins, MCP, Jobs) for admins.

  13. Newanfra0.17.0

    View the rows behind a chart's point

    The modal is titled by the point's value, and lists the rows that make up that number, with the query's own filters applied. Rows are sorted by every dimension, so pages don't repeat, and Load more fetches the next page until every row is in. Download them as CSV from the modal.

    It shows on the menu a chart opens with query.menu(). When a chart shows several measures, pass the point's measure, so the entry is about that one:

    chart.on('contextmenu', (p) => {
      byRegion.menu(p.event.event, byRegion.result.rows[p.dataIndex], { measure: p.seriesId })
    })

    anfra serve installs the view-underlying-data plugin, and the anfra skills write the menu into new charts.

  14. Newanfra0.17.0

    YAML or JSON from every command, with jq built in

    Core commands write YAML by default, and CLI-only ones such as anfra init, anfra auth and anfra publish write a format for people. Either way, --yaml or --json gives you one document to script against:

    anfra show --jq '.object.datasets[].name'

    --jq runs a jq expression on the answer, with no jq to install. --schema prints a command's input and output as JSON Schema, instead of running it.

    Errors go to stderr with a stable code and a scope (user, client or server), and the exit code is non-zero. --non-interactive asks no questions, and refuses what would need an answer.

    Checks are subcommands now: anfra query validate, anfra query compile, anfra publish check and anfra update check. anfra status reports the repo too.

  15. Improvedanfra0.17.0

    anfra serve gets anfra Cloud's look

    anfra serve and anfra Cloud now share one design: the same fonts, type, colors, icons and components, and the anfra logomark in the sidebar. A Data App looks the same while you build it and once it's published.

    anfra serve showing the Funnel analysis Data App, with the sidebar of apps by folder, the search box with its ⌘K shortcut, the anfra logomark and the app header
    The Funnel analysis app in anfra serve.

    The command palette (⌘K or Ctrl+K) searches your apps as well as commands, so you can open another app from the keyboard. The Inspect panel and the menus and modals that plugins draw take the same theme, in light and dark.

  16. Improvedanfra0.17.0

    Data App errors say what happened and who can fix it

    err.scope says who must act: user for the reader's input or rights, client for the app's own code, and server when the server or host failed. err.code says what happened, such as query_invalid, query_failed, forbidden or connection_failed. err.requestId names the request in anfra serve's log, where the full cause is.

    if (query.state === 'error') {
      const { code, scope, message } = query.error
      if (code === 'forbidden') showNoAccess()
      else if (scope === 'server') showRetry(() => app.execute())
      else showProblem(message)
    }

    Breaking

    QueryError, PermissionError and TransportError are gone. Branch on err.code and err.scope instead of err.name. ValidationError stays for declarations, with code declaration_invalid.

  17. Newanfra0.15.0

    Set up your coding agents with anfra agent setup

    anfra agent setup

    It installs the anfra plugin, with its skills, an AQL-writing agent and hooks, into Claude Code and Codex through their CLIs, and points other agents it finds, such as Cursor, at the install steps for them. Pass --agent to pick agents, and run it again to update. anfra agent setup check reports what it would find, changing nothing.

    anfra init now writes an anfra block into AGENTS.md, telling coding agents to use the skills, and links it from an existing CLAUDE.md.

    Each skill is stamped with its version. anfra version --skills <version> says whether the skills are behind anfra, and commands remind you when they are.

    The skills are renamed with an anfra- prefix, such as anfra-build-data-app, so they don't collide with other skills in your agent. Ask for them by their new names.

  18. Improvedanfra0.15.1

    See what's new after anfra update

    After an update, anfra update prints the changelog of each release since the one you had, skipped releases included: the newest three, then a link to the rest. anfra update check shows the same before you install.

    If the notes can't be fetched, it links to the releases page, and the update still goes through.

  19. Newanfra0.14.0

    A command palette, and a menu on a Data App's content

    The palette lists the commands of anfra serve and of the open app's plugins, such as Reload, Inspect, and Download as PNG or PDF. A command's shortcut works inside the app's frame too.

    The command palette open over a Data App, listing Pick an element, Download as PNG, Download as PDF, Inspect with its Alt+Shift+I shortcut, Reload Data App, view commands and the apps to open

    Right-click a marked block (data-anfra-block) to open its menu, with no code. For a chart's points, report the right-click with the rows under the pointer:

    chart.on('contextmenu', (p) => {
      byRegion.menu(p.event.event, byRegion.result.rows[p.dataIndex], { measure: p.seriesId })
    })

    When nothing is offered, the browser's own menu shows, and Shift+right-click always gives it. Put data-anfra-menu="off" on a block that uses right-click itself.

  20. Newanfra0.14.0

    A new Inspect panel for Data Apps

    Open it from the app's header in anfra serve, or with Alt+Shift+I. It has six tabs:

    • Overview, where it opens: how far to trust each app, the queries' states, the problems, and what the reader changed
    • Queries: every query, control and selection, with its filters, its code and the requests it made
    • Data: each query's latest rows, with a CSV download
    • Declaration: what the app declares, its checks, and how its controls and queries are wired, with the AQL highlighted
    • Lineage: where each number comes from, traced back to its source tables
    • Structure: the parts you marked as a tree

    The tabs link to each other, so a problem in Overview opens the query it names. Tabs that don't fit go behind a More tabs menu.

    The Ecommerce Overview Data App with the Inspect panel open on its Overview tab, showing trust level 3, no problems, six queries ok and five controls applied
    Inspect opens on the Overview tab.

    For hosts

    The SDK's inspect.watch, inspect.highlight, inspect.locate and inspect.pick calls, and the inspect.snapshot and inspect.picked events, are gone. Use mounted.panel instead.

  21. Newanfra0.14.0

    See where a page's numbers come from in the Lineage tab

    Click a card to pin its path through the page: the block or query it belongs to is outlined on the page as well. Hide kinds of cards, pick a preset, or focus on one card's path to cut the canvas down.

    The Inspect panel's Lineage tab with the Revenue block's card pinned: its path runs through the kpis query and its metrics to the E-commerce dataset, and the Revenue card is outlined on the page
    The Revenue block pinned in Lineage, and outlined on the page.

    From the Queries and Data tabs, Show in Lineage opens a query's place in the graph.

    Lineage reads the catalog that anfra ingest builds, so run anfra ingest after you change your AML, or it shows the old definitions.

  22. Improvedanfra0.13.5

    Search LookML projects, and page through results

    List a LookML project in .anfra/context_sources.yml, next to your dbt projects, then run anfra ingest:

    sources:
      - name: looker
        type: lookml
        local: { path: ../looker-project }

    anfra search then finds what it defines along with your AML. Results come a page at a time: --limit sets how many, and --offset skips the ones you've seen. Its output in the terminal is easier to scan, too.

  23. Newanfra Cloud

    Choose what your data apps can do

    In Settings → Plugins, an admin chooses which plugins the organization's data apps get. The change reaches every member the next time they load a page.

    PluginDefaultWhat it adds
    CoreAlways onQueries and filter suggestions
    InspectOnInspect in the app's header: a panel with the app's data, queries, structure and definition
    LineageOnWhere each field comes from, in the panel's Lineage tab
    RenderOffDownload the app, or a part of it, as a PNG or PDF
    ExportOffExport a query's full result. Not available in anfra Cloud yet

    The panel docks beside the app. It remembers its tab, and you can drag its left edge to resize it.

    The Ecommerce Overview data app with the Inspect panel docked on the right, on its Overview tab: trust level 3, semantic layer verified, no problems, six queries and five controls
    The Inspect panel, docked beside a data app
  24. Newanfra Cloud

    Choose where your data apps load from

    Data apps run under a strict content policy: they load scripts, styles and fonts only from jsDelivr, cdnjs and Google Fonts, and send requests only there, so an app can't send your data anywhere else.

    When your apps need another server, an admin adds its origin in Settings → Data apps, such as https://api.example.com. Each must be an https:// origin with nothing after it, up to 20. The page lists the built-in origins, with what data apps use each for, next to the ones your organization added.

    Allowed origins are the organization's choice, not the project's: publishing doesn't change them. The change reaches every member the next time they load a page.

  25. Newanfra Cloud

    Connect your data warehouse

    anfra Cloud connects to PostgreSQL, Snowflake, BigQuery, Amazon Redshift, Databricks, MySQL, SQL Server, ClickHouse, Amazon Athena, Presto and Trino, Oracle, and MotherDuck.

    The Add data source panel: a Name field set to warehouse, a grid of data source types from PostgreSQL to MotherDuck, then Host, Port, Database, User and Password fields, Advanced options, and Test connection and Add data source buttons

    Give a data source the name your project's models refer to, fill in the connection, and save. anfra Cloud tests the connection first and shows what failed on the field it belongs to. Advanced options, such as timeouts and SSL, are tucked away until you need them.

    Saved secrets stay secret

    Once saved, a password or key is never shown again, only that one is saved. When you edit a data source, leave a secret blank to keep it. If you change where the data source connects, such as its host, anfra Cloud asks for its secrets again, so they can't be sent to a new server.

    Only admins manage data sources and can query them in SQL directly. Everyone else queries through the semantic layer.

  26. Newanfra0.13.0

    Copy a DuckDB file to MotherDuck as you publish

    anfra Cloud can't read a DuckDB file on your laptop, so models built on one would publish but fail to query. At a terminal, anfra publish now offers to upload the file to your MotherDuck account, through MotherDuck's CLI, and creates a motherduck data source for the organization under the same name. Your models and .anfra/data_sources.yml don't change.

    The copy never touches what's already there. It goes to a new database under a free name, the local file is only read, and the organization gets a read-only token. Each step asks first, and nothing is offered without a terminal.

  27. Newanfra Cloud

    Create organizations and switch between them

    Create an organization with a name and an address, such as https://us.anfra.ai/o/acme. Everything in it is its own: its data sources, the project you publish to it, its data apps and its members.

    You can belong to more than one organization, with a different role in each. Switch between them from the organization menu. anfra Cloud opens the one you used last.

  28. Newanfra Cloud

    Invite your team to your organization

    Invite people by email and choose their role. The invitation is emailed to them, and only that address can accept it: they sign in or sign up with any method, as that address, and join.

    Settings → Members & roles lists members and invitations, with filters by role and status. From there an admin can:

    • change a member's role,
    • suspend a member, and restore them later,
    • resend an invitation, which starts a fresh seven-day link and stops the old one,
    • revoke an invitation that hasn't been accepted.
    Settings, Members & roles: six members with Admin, Analyst and Explorer roles, one of them Suspended, and a row's actions menu open with Change role and Suspend user
    Members & roles, with a row's actions open

    Roles

    RoleCan
    ExplorerOpen the organization's data apps and query its data through the semantic layer
    AnalystEverything an Explorer can, plus publish the project
    AdminEverything an Analyst can, plus manage data sources, members, settings and jobs, and query data sources in SQL
  29. Newanfra Cloud

    Open your team's data apps in anfra Cloud

    The sidebar lists the organization's data apps as a tree, with the folders they sit in under apps/. Open one and it runs inside anfra Cloud, against the organization's data.

    anfra Cloud with the Ecommerce Overview data app open: the sidebar lists data apps in folders (build-your-own-bi, dashboards, playground), and the app shows revenue, orders and customer totals, a revenue and orders chart and orders by status

    Every member can open every data app. Its queries run as the person reading it, under their role, so an app never shows anyone more than they could query themselves.

    When an app changes under you

    If someone publishes while you have an app open, anfra Cloud says "This app has been updated" and offers a reload. It never reloads by itself, so you keep your filters until you choose.

  30. Newanfra Cloud

    Publish your project to anfra Cloud

    Build locally with anfra, then sign in to your organization and publish:

    anfra auth login https://us.anfra.ai/o/acme
    anfra publish

    anfra auth login opens your browser to approve the CLI for one organization. anfra publish sends your project's .aml files and everything under apps/, and nothing else: no hidden files, no credentials.

    What a publish does

    • It is validated twice. The CLI checks your project before uploading it, and anfra Cloud checks it again. If anything fails, nothing changes.
    • It goes live at once. Your team queries the new version as soon as the publish returns.
    • It replaces the whole project. A file you no longer have is removed.
    • It doesn't overwrite by surprise. If someone else published since you last did, the CLI asks before replacing their work.

    Each publish is kept as a version, with who published it and their message. Browsing earlier versions isn't built yet.

  31. Newanfra Cloud

    See and revoke the tools that use anfra as you

    Every tool that acts as you, such as the anfra CLI or an MCP client, asks you to approve it in the browser first, for one organization. Settings → Connections then lists each one with its organization, when you connected it and when it was last used.

    Your connected apps table with Cursor and Claude, both marked Unverified, and the anfra CLI, each with its organization, permissions, connected date, last used and a Revoke access button

    Choose Revoke access on a tool to cut it off at once. Other tools, and the same tool on another computer, stay connected. A tool anfra didn't verify is marked "Unverified".

  32. Newanfra Cloud

    See and stop your organization's queries

    Admins find Jobs in Settings. Each job shows its kind, who started it, its timeline and the queries it ran. Filter by when a job was submitted or by its status to find one.

    Settings, Jobs: filters for when a job was submitted and its status, and a list of succeeded core.query jobs, each with who ran it, when, and how long it took

    A job that runs too long can be stopped from its page.

  33. Newanfra0.12.0

    Sign in to anfra Cloud and publish from the CLI

    anfra auth login https://us.anfra.ai/o/acme
    anfra publish --set-org https://us.anfra.ai/o/acme

    anfra auth login opens your browser to approve the CLI, and saves the login in ~/.anfra/credentials.json. You can sign in to several organizations: anfra auth status lists them and anfra auth logout removes one. Run without an address, anfra auth login lets you pick.

    anfra publish validates the repo, then sends its .aml files and everything under apps/, nothing else. --set-org saves the organization in .anfra/config.yml, so commit that file and everyone publishes to the same place. anfra publish check lists what a publish would send, without signing in.

    Publishing to anfra Cloud's beta at us.anfra.ai needs anfra 0.19 or later.

  34. Newanfra Cloud

    Sign in with Google, GitHub or an email code

    The sign-in screen offers Google, GitHub and a one-time code sent to your email. Signing in and signing up are the same screen: with no account yet, you get one, then create your organization. The method you used last carries a "Last used" badge.

    The anfra Cloud sign-in screen, Sign in or create an account, with Continue with Google, Continue with GitHub, and an email field with Continue with email

    An emailed code has six digits and lasts ten minutes. It works only in the browser that asked for it.

    Manage your sign-in methods

    Your account settings list your sign-in methods. Add Google or GitHub to an account you made with a code.

  35. Improvedanfra0.12.0

    Data Apps run under a content policy

    A Data App has the reader's query results in hand, so its frame now runs under a content policy. Data comes only from the SDK: fetch, XHR and WebSocket to other servers are blocked, and so are frames and forms.

    A Data App is one self-contained file. Nothing it loads may be another file in your repo, so put your own scripts and styles inline, and images inline as SVG or a data: URI. Load libraries from jsDelivr or cdnjs, the SDK's built-in CDNs since 0.13.1.

    To allow another origin, list it in .anfra/config.yml:

    apps:
      allow_origins:
        - https://cdn.acme.com

    An organization on anfra Cloud keeps its own list, and since 0.13.1 anfra publish says which of your origins it doesn't allow.

  36. Improvedanfra0.11.0

    Data App features come from plugins

    Everything a Data App reaches beyond itself comes from a plugin: core runs queries, export adds query.export(), lineage adds Anfra.lineage(), and render adds Anfra.render(). anfra serve installs them all, but another host may install fewer, so check before you offer one:

    if (Anfra.plugins.has('export')) showDownloadButton()

    A plugin's API is undefined where it isn't installed. Anfra.features still answers, but is deprecated: replace it with Anfra.plugins.has().

    For hosts

    If you host Data Apps in your own app with @holistics/anfra-sdk, createHost(...).mount(...) replaces mountDataApp and serveBridge, and the corePlugin replaces the Backend option. You can write plugins of your own, with build and testing entrypoints in the SDK.

  37. Newanfra0.9.0

    Trace a metric back to its source tables

    Name each field by what holds it, a dataset and its metric or a model and its field:

    anfra lineage --targets '[{"parent":"ecommerce","child":"revenue"}]'

    In a Data App, Anfra.lineage() returns the same trace as a diagram of cards in layers, upstream first, for a definitions panel next to a chart:

    const { results: [revenue] } = await Anfra.lineage([{ parent: 'ecommerce', child: 'revenue' }])

    Lineage reads the catalog that anfra ingest builds, so run anfra ingest again after you change a model or dataset.

  38. Newanfra0.8.0

    Download a query's whole result as CSV

    Add a "Download CSV" button next to a table or chart:

    if (Anfra.plugins.has('export')) {
      downloadButton.addEventListener('click', () => byRegion.export({ filename: 'Revenue by region' }))
    }

    The file holds every row, not only the pages the app has loaded, and runs with the same controls, cross-filter selection, sort and time zone as the result on screen. Values are written raw: numbers with every digit, dates in ISO 8601. formatOptions picks the header row (column labels, names or none) and the byte order mark that Excel needs for non-ASCII text.

    From the terminal, anfra query export does the same for any query.

  39. Newanfra0.8.0

    Save a Data App, or one part of it, as PNG or PDF

    In anfra serve, the Download menu saves the open app as a PNG or PDF, with nothing written in the page. To save only one part, pick a block or container in the Inspect panel's Structure tab and use its PNG or PDF buttons.

    The Download menu open in the header of anfra serve, offering Download as PNG and Download as PDF

    A page that needs its own button calls Anfra.render():

    await Anfra.render({ block: 'trend', format: 'png' })     // a block, by its data-anfra-block id
    await Anfra.render({ container: 'kpis', format: 'pdf' })  // a container
    await Anfra.render({ format: 'pdf' })                     // the whole page

    The picture shows the page as the reader sees it, charts drawn on a canvas or in SVG included. Mark anything that shouldn't be in it, such as a download button or a spinner, with data-anfra-render="skip".

  40. Newanfra0.6.0

    Mark a Data App's parts, and find them in Inspect

    <div data-anfra-container="kpis">
      <div data-anfra-block="revenue" data-anfra-query="totals">…</div>
    </div>
    <section data-anfra-block="trend" data-anfra-label="Revenue over time">
      <div id="trend-chart" data-anfra-query="trend"></div>
      <select data-anfra-control="grain"></select>
    </section>

    A container holds other parts, a block is the smallest part a reader sees as one thing, and data-anfra-query and data-anfra-control say which query or control draws an element.

    The Structure tab of the Inspect panel shows these parts as a tree. Hover a part to see it on the page, click it to scroll there, or pick a spot on the page to find its part. Markup it can't read, such as an unknown query name or a block inside a block, is flagged on the part instead of thrown.

    Copy a part's handle, such as [Revenue over time](data-anfra-block="trend"), and paste it into a request to your coding agent, so it changes the element you mean. In your own page, query.locate() scrolls to the elements a query draws.

    The Structure tab of the Inspect panel showing the Ecommerce Overview's containers, blocks, controls and queries as a tree, with the revenue block hovered and highlighted on the page and its handle and PNG and PDF buttons below
    Hovering a block in the Structure tab highlights it on the page.
  41. Newanfra0.4.1

    Run anfra from its Docker image

    Mount your repo at /repo:

    docker run -p 7878:7878 -v "$PWD:/repo" ghcr.io/holistics/anfra

    The same apps, API and MCP server are then at http://localhost:7878/. Other commands run the same way:

    docker run --rm -v "$PWD:/repo" ghcr.io/holistics/anfra validate

    One image covers x64 and ARM, Apple silicon included. Tags follow the releases, such as 0.4.1, 0.4 or latest. The server has no login, so publish its port only to people who may query the repo's data.

  42. Newanfra0.4.0

    Build Data Apps with the anfra JS SDK

    A Data App is a single HTML file in your repo's apps/ folder. It draws with any HTML, CSS and charting library, and gets its data from the Anfra global, which the host provides before the page's first script runs. There is nothing to install or import.

    const app = Anfra.createApp({ title: 'Sales' })
     
    const status = app.createFilter('status', { dataset: 'ecommerce', field: 'orders.status' })
    const byRegion = app.createQuery('byRegion', {
      dataset: 'ecommerce',
      aql: 'explore { dimensions { region: users.region } measures { revenue: sum(orders.amount) } }',
    })
    app.mapControl(status, byRegion, { field: 'orders.status' })
     
    app.subscribe(() => render(byRegion.result))
    await app.execute()

    Queries name datasets and metrics, never SQL. You declare filters, date drills and cross-filters between queries, and the server turns each into the query it runs.

    anfra serve serves every app under /apps/: apps/revenue.html opens at http://127.0.0.1:7878/apps/revenue, and reloads as you or your agent edit it.

  43. Newanfra0.4.0

    Connect your coding agent to anfra over MCP

    anfra serve serves MCP at /mcp, over streamable HTTP, next to your Data Apps and the API. Add it to your agent:

    claude mcp add --transport http anfra http://127.0.0.1:7878/mcp

    Its tools are anfra's own commands, so the agent can list your datasets with their fields and metrics, validate the repo, search it and run queries.

    The server needs no sign-in and queries with the credentials in .anfra/data_sources.yml, so it listens on 127.0.0.1 only. Pass --no-mcp to turn it off.

  44. Newanfra0.4.0

    Explore your semantic layer with anfra show and anfra search

    • anfra show lists the repo's datasets with their models, fields and metrics, and anfra show <dataset> shows one in full.
    • anfra ingest builds a local catalog from your AML and the context sources in .anfra/context_sources.yml, and anfra search "monthly revenue" searches it.
    • anfra query --lang sql -s <data source> runs SQL on a data source directly, to look at the raw tables before you model them.

    Your coding agent uses the same commands to find the right metric before it writes a query.

  45. Newanfra0.4.0

    Start a repo with anfra init, and teach your agent anfra

    anfra init my-project

    anfra init creates the models/, datasets/ and apps/ folders and a .anfra/data_sources.yml for your warehouse credentials, which it adds to .gitignore so they stay out of Git.

    anfra skills install installs the anfra skills in your coding agent. They teach it to write AML models, write and check AQL, and build Data Apps. Since 0.15.0, the command is anfra agent setup.

  46. Newanfra0.2.0
  47. Newanfra0.1.0

    Validate and query your models from the terminal

    anfra validate checks the models and datasets in your repo and reports what doesn't compile. Pass file globs to see only the problems in those files:

    anfra validate "models/*.aml"

    anfra query -d <dataset> compiles an AQL query, runs it on the dataset's data source, and returns its rows with the SQL that produced them. It can also compile the query without running it, or only type-check it.

    anfra serve starts a warm server for the repo. While it runs, other commands go through it and reuse its database connections, so each one answers faster.