English | 简体中文 | 日本語 | Português (Brasil)
An open format and embeddable engine for relational reporting — where every report is a portable query graph, a materialized SQLite table, and a parametric layout.
MAD is a relational reporting platform built from scratch in Objective-C for ad hoc query, reporting, and design: the MAD Designer app for iOS and native macOS (AppKit), where queries and layouts are built visually or from SQL; the MAD Viewer app, where reports are read and refreshed; the headless mad CLI and engine that run on Linux and macOS; and the open .mad specification.
A .mad file holds a report's entire definition — the database schema snapshot, the relational query graph (tables, joins, predicates, groupings), and the banded layout tree — in a single file under 100 KB, cleanly separated from the data it displays. A report is an executable file, not a server: any runtime that speaks .mad can inspect the schema, compile deterministic SQL for the target database, materialize the result set into a local SQLite table, and render it to native AppKit/UIKit views, paginated HTML, PDF, CSV, or JSON.
The repository is one self-contained project: the iPad/iPhone apps, the native macOS (AppKit) desktop app (Mac/), fourteen frameworks (twelve multiplatform across iOS, iOS Simulator, and native macOS; eleven headless on Linux), the headless Linux build and test suite (126 test executables, 1,303 tests), the mad command-line tool, and the build system (Compressor) that compiles the third-party C libraries from pinned sources. The code is published under the MIT licence; the .mad format is an open specification (see docs/), though the project's names and app artwork are not covered by the licence grant (see NOTICE).
Try MAD Designer on macOS (macOS 12.0+, Apple Silicon):
- Homebrew:
brew install --cask mthomason/tap/mad-designer- Direct Download: MAD-Designer-macOS.dmg | MAD-Designer-macOS.zip (for direct downloads, run
xattr -cr "/Applications/MAD Designer.app"once after copying to/Applications)
Today, any developer can ask an LLM to generate a one-off SQL script and a React table in ten minutes. Six months later, the organization has forty bespoke mini-apps, forty incompatible definitions of an INNER JOIN between customers and invoices, hardcoded database credentials, hallucinated aggregate math, and zero interoperability between mobile, desktop, CI pipelines, and external partners.
MAD solves the reporting problem at the format and engine level:
- Interoperability through a shared contract. Instead of scattering ad hoc SQL and UI glue code across bespoke scripts, a
.maddocument packages the schema contract, the query AST, and the presentation layout into one inspectable, diffable, versioned artifact. The same 80 KB file opens natively on macOS and iPad, runs headlessly in a Linux Docker container, executes in GitHub Actions, or embeds inside another application — producing byte-identical SQL and exports across Apple and Linux. - Deterministic SQL and two-pass local math. Neither the end user nor an AI model needs to hand-write dialect-specific SQL or compute totals in application code. The engine validates the query graph against the document's schema snapshot, compiles deterministic SQL for the wire driver, pulls the result set once into a local SQLite row cache (
MADDataTableFast), and computes groupings, sort keys, and header/footer aggregates locally in two passes. - Written, not assembled. The SQL generator, the SQL parser, the data-table engine, the portable store, the layout model, and the page renderer are first-party Objective-C across fourteen frameworks. Third-party code is strictly limited to the wire — MariaDB Connector/C, FreeTDS,
libpq, and SQLite — pluslibarchive/bzip2andzintfor barcodes. No proprietary reporting SDK is being resold. - Mobile-first means memory-budgeted. Because the result set is materialized into an indexed SQLite table on disk and pages are formatted into a geometry-keyed cache, a phone or a small container can paginate and aggregate hundred-thousand-row reports without holding the dataset in RAM.
The technical documentation and format specification are also served at https://docs.everydayapps.com.
MAD Designer for macOS — the native AppKit desktop application (Mac/), showing the MAD Query visual relationship canvas and the MAD Designer banded layout workspace:
MAD Designer for iOS, from choosing a data source to reading the finished report in MAD Viewer (28 seconds; video):
The same engine running headlessly on Linux: inspect, schema, query, refresh, and export through the mad CLI, with no reporting server:
The recording's exported report is plain HTML, opened in any browser.
A .mad file is not a static printout like a PDF, and it is not a dump of row data. It is a declarative program that turns a database connection into a typed table and a formatted view.
The architecture splits a report into the portable definition (inside the .mad file, typically 15–80 KB) and the derived companion caches (generated locally on refresh and disposable at any time):
| Layer | File / Member | Format | Role |
|---|---|---|---|
| 1. Container | <Name>.mad |
16-byte MADFILE\0 v1 header + pax restricted bzip2 tar archive |
Content-identifiable outer archive (tar xjf compatible for v0, header + bzip2 tar for v1). |
| 2. Definition Store | StoreContent/analyitics |
Portable SQLite (MADStoreSchema, versioned via PRAGMA user_version) |
Holds the Rptq* object graph: the imported database schema snapshot, the query graph (tables, aliases, joins, predicates, groupings, and optional sqlSourceText), and the banded section/element layout tree. Zero Core Data or Apple dependencies. |
| 3. Metadata & Preview | meta.plist, AdditionalContent/ |
XML Property List + optional thumbnail@2x.png |
Generator metadata, format version, and optional document preview. |
| 4. Materialized Table (companion) | <hash>.maddb + <hash>.mdcache |
SQLite row database (t<tag>) + column schema plist (MADDataColumn) |
The report's output as a database table. Holds the fetched rows, group-key indexes, and column type metadata so two-pass aggregates (SUM, COUNT, AVG, MIN, MAX), sorting, and re-rendering never re-query the remote database. |
| 5. Page Cache (companion) | <hash>{ih,lh}{w,h}.madac |
SQLite index (ih) and layout (lh) databases keyed by page geometry |
Pre-calculated page breaks and element frames for a target viewport (e.g., {612, 792} US Letter), keeping scrolling and export instantaneous. |
The full specification — container layout, store tables, companion schemas, known quirks (including why the inner store filename is historically spelled analyitics for backward compatibility), and cross-platform digest verification — is documented chapter by chapter in docs/.
Because MAD already separates the query graph, the materialized SQLite result table, and the presentation layout, the architecture unlocks four major capabilities that are actively being designed and queued (see docs/vision.md, docs/project/MAD_DATA_OBJECT.md, and docs/project/TODO.md):
- A
.madreport as an ad hoc database table (Composable Data Objects). In a traditional database, youSELECTfrom base tables likeemployeeorsales_data. A.madreport joins and filters multiple tables, and its output (.maddb+.mdcache) is already a physical SQLite table with a typed schema (MADDataColumn). By making a report's output addressable as a table source inside the query designer, a.madfile becomes a virtual/materialized database table. Other reports, queries, or tools canSELECTfrom andJOINagainst a.madreport just like any table in a database. - Multiple data sources in a single report (Federation without a server).
Every database driver (
MADMySQL,MADPostgres,MADTdsClient,MADSqlite3) materializes its query result into the same local SQLite table representation (MADDataTableFast). Once a report can hold multiple query objects and treat each materialized output as a local table, a single.madreport can join acustomerstable from PostgreSQL with anorderstable from SQL Server and a local SQLite table — federated locally over SQLite without a heavyweight federation server in the middle. - Beyond the paper paradigm: native UIKit & interactive data views.
Banded page layout (Report Header, Page Header, Group Headers/Footers, Detail, Page/Report Footer) was born from printing on paper. In MAD, paper pagination is becoming just one view paradigm over the document's data object. When you are not printing or exporting a paged facsimile, the same layout and local
.maddbtable will drive rich, interactive native UIKit components and raw data exploration views — design once, render either as paginated paper or as native interactive UI. - Converting legacy Crystal Reports (
.rpt) and enterprise report files to.mad. Thousands of companies are still locked into decades of Crystal Reports (.rpt) files that nobody wants to rewrite by hand and no modern SaaS dashboard can import cleanly. Because MAD shares the classic banded-section + relational-query-graph DNA of Crystal Reports — while storing everything in an open, inspectable SQLite-in-tar format — MAD is building importers to convert legacy.rptdefinitions directly into open.madfiles.
The headless engine runs the mad CLI in Docker. Pull the published image and inspect one of the checked-in sample documents:
docker run --rm -v "$PWD/CLI/Fixtures":/docs:ro ghcr.io/mthomason/mad \
mad inspect /docs/London.portable.madEvery verb works the same way — schema, query, refresh, export (HTML paged facsimile and reflowable html-flow, plain text, CSV, JSON data contract, and json-report; PDF runs natively on Apple and is deferred on Linux by design):
docker run --rm -v "$PWD/CLI/Fixtures":/docs:ro ghcr.io/mthomason/mad \
mad refresh /docs/Music.portable.mad
docker run --rm -v "$PWD/CLI/Fixtures":/docs:ro -v "$PWD/out":/out ghcr.io/mthomason/mad \
mad export /docs/London.portable.mad --format html --out /out/london.htmlThe published tags are latest and the commit's short SHA, built for linux/amd64 by the publish workflow on every push to master. On Apple silicon add --platform linux/amd64 — Docker Desktop runs the tag under emulation, and without the flag the pull fails (no matching manifest). Building a native arm64 image locally (mad-cli:latest) and running the full cross-platform verification suite is one command:
./Linux/build.sh --verify # build the toolchain and run the checks (~20 min first time)The sample documents refresh against the Sqlite3 sample database that ships inside the image; the MySQL, SQL Server, and PostgreSQL fixtures expect the test servers from docs/project/DEVELOPER.md.
The mad-action GitHub Action runs a checked-in .mad in a workflow and uploads its export as an artifact:
- uses: mthomason/mad-action@v1
with:
command: export
document: reports/sales.madIt runs the published image, so the action and the CLI are the same engine. The action is generated from satellites/mad-action/ here; docs/project/SATELLITE_REPOS.md records how the satellite is kept current.
MAD talks to databases through MADDatabase subclasses. Four drivers ship today:
- MySQL / MariaDB —
MADMySQL, over MariaDB Connector/C; - SQL Server —
MADTdsClient, over FreeTDS; - PostgreSQL —
MADPostgres, overlibpq; - SQLite —
MADSqlite3, for sample documents, local databases, and internal materialization tables.
A driver is a framework that subclasses MADDatabase and registers itself with MADDatabaseDriverRegistry — the query designer and the engine never see the wire protocol. Writing one is the intended first contribution (see the driver-authoring tutorial under docs/tutorials/driver-authoring.md). The seam is real: users can build a query visually or paste SQL (MADSQLParser), the engine generates the dialect-specific statement, and the driver only has to execute it and stream rows into id<MADDataTableWriting>.
Eleven of the fourteen frameworks are UIKit-free and build headlessly. The mad CLI above is that engine wearing a command line: the verb set — inspect, schema, query, refresh, export, write — is the embedding surface, and an application that links MAD, a driver framework, and MADSqlite3 has relational reporting with no server in the loop. Drivers and export formats (<MADReportExporting> / MADReportExporterRegistry) self-register, so adding a data source or an output format is a subclass, not a fork.
The native macOS desktop app (docs/macos.md, Mac/) is built directly with AppKit (macosx SDK, MACOSX_DEPLOYMENT_TARGET = 12.0) over the twelve multiplatform MAD frameworks and the ten universal (arm64 + x86_64) static C libraries compiled by Compressor:
- Native
NSDocumentarchitecture (MADMacDocument/MADMacDocumentController): Opens and saves.madarchives natively from Finder or the standard Open Panel (with an integrated New Document button), automatically migrates legacy Core Data.madfiles viaMADStoreConverter, and integratesMADDesignerLayoutdirectly withNSDocument.undoManager(Cmd+Z/Cmd+Shift+Z). - Database Connection & Schema Import Assistant (
MADMacConnectionWindowController): Connects to SQLite, MySQL / MariaDB, Microsoft SQL Server, or PostgreSQL, verifies connectivity, stores credentials in the macOS Keychain (MADKeyChain), and imports table and column schemas into a new.maddocument. - Three integrated workspaces (
Cmd+1,Cmd+2,Cmd+3):- MAD Query (
MADMacQueryViewController): Toggles between the interactive Query Designer (draggable table cards, Bezier join connectors with clickable join-type badges,WHEREfilter andGROUP BYpopovers) and the SQL Query editor (MADSQLParser+MADSQLQueryCompiler). - MAD Designer (
MADMacDesignerViewController): Three-pane split view with an interactive Page & Section Minimap, Report Bands outline, searchable Query Fields drag source, zoomable/ruled design canvas (MADMacDesignerCanvasView) with cross-section drag-and-drop and smart alignment guides, and a dual-card Page & Element Inspector. - MAD Viewer (
MADMacViewerViewController): Live data refresh (Cmd+R), instant Page Size re-pagination (US Letter,Legal,Tabloid,A3,A4,A5,B4,B5,JIS B4,JIS B5), framedPDFViewpreview, nativeNSPrintOperationprinting (Cmd+P), and export (Cmd+E) to PDF, HTML, HTML Flow, CSV, JSON, JSON Full Report, and Plain Text.
- MAD Query (
See docs/macos.md for the full guide and docs/project/MAD_MACOS.md for the multiplatform portability audit.
The workspace (Reports.xcworkspace) builds the fourteen frameworks, the iOS apps, and the native macOS app (MAD Designer Mac).
Build, run the end-to-end smoke test suite, and package .zip and .dmg release artifacts from the repository root:
./Mac/build.sh # build 12 macOS frameworks + Mac/build/MAD Designer.app
./Mac/build.sh --no-frameworks # rebuild only MAD Designer.app (fast iteration)
./Mac/build.sh --smoke-test # build and run the end-to-end macOS smoke suite
./Mac/build.sh --package # create Mac/build/MAD-Designer-macOS.zip and .dmgYou can also build and debug interactively in Xcode using the shared MAD Designer Mac scheme, or run any framework's unit test suite natively on macOS:
xcodebuild test -workspace Reports.xcworkspace -scheme MAD \
-destination 'platform=macOS,arch=arm64' \
-derivedDataPath ~/Library/Developer/Xcode/DerivedData/Reports-cozeiyczmvgrbeapplwfuygymqciRun a framework's suite against the iOS Simulator:
xcodebuild test -workspace Reports.xcworkspace -scheme MADFoundation \
-destination 'platform=iOS Simulator,id=94952340-7629-4EBB-BBD3-6FEE068793B8' \
-derivedDataPath ~/Library/Developer/Xcode/DerivedData/Reports-cozeiyczmvgrbeapplwfuygymqci(MADMySQL, MADTdsClient, and MADPostgres also carry live suites that talk to a real database server and skip when one is not reachable — see docs/project/DEVELOPER.md.)
The headless engine is verified the same way on Linux. From the repository root, with Docker installed:
./Linux/build.sh # build the toolchain image, compile the eleven frameworks, run the suitesThis runs 126 test executables and 1,303 tests inside the container, and --verify adds the CLI's end-to-end checks against the checked-in fixtures and their pinned digests. See Linux/README.md for the image, the pins, and the GNUstep divergences the port found.
MAD is free software and stays free. One maintainer keeps it: the design documents, the two-platform test matrix, and the agent-driven development all run on real time and API tokens. If MAD saves your team time, here is how to give some of it back — and thank you either way:
- Sponsor the maintainer — one-time or monthly, GitHub Sponsors.
- Send API credits. The project is developed with AI agents; OpenAI, Anthropic, or agent-token credits go straight back into the work. Get in touch through the sponsor page or an issue.
- Contribute. A database driver, a document element, an export format, a legacy importer, or a fix — the seams are the point.
MIT — see LICENSE. The licence covers the software; the names "MAD", "MAD Designer" and "MAD Viewer", the app icons and other product artwork, and the app preview media are the author's and are excluded from it (see NOTICE). Every third-party component, its licence, and what shipping it obliges us to do is recorded in docs/project/THIRD_PARTY_LICENSES.md.
The MySQL, FreeTDS, and PostgreSQL drivers use OpenSSL/TLS; no custom encryption is implemented. Under Apple's export compliance guidelines this is exempt encryption, and the app sets ITSAppUsesNonExemptEncryption = NO.



