Open-source Semantic Layer analytics for cubes — drag-and-drop in the browser, SQL through Mondrian + Calcite, and a typed REST surface so AI agents can query without ever seeing MDX.
saiku.bi · Live demo · Issues · Discussions
docker run -d -p 8080:8080 --name saiku -e SAIKU_DEMO=true ghcr.io/spiculedata/saikuThen open http://localhost:8080/ui/ and log in with admin / admin. Demo
mode ships a self-contained H2 + FoodMart cube — drag fields onto rows, columns,
or filters and the SPA writes MDX for you.
For a real deployment, drop
SAIKU_DEMO=trueand set an admin password:-e SAIKU_ADMIN_PASSWORD='a-strong-password'(or-e SAIKU_ADMIN_PASSWORD_FILE=/run/secrets/saiku-admin-password). Saiku refuses to start on the defaultadmin/adminonce it's network-reachable, so one of those two is required — and the password must itself clear the policy (≥ 12 characters, not a well-known weak password), soSAIKU_ADMIN_PASSWORD=adminis refused too.
Demo fixtures follow demo mode (saiku#1953). A boot without
SAIKU_DEMO=truestages no demo content: no FoodMart/Bank/TPC-DS/Flights schemas, no H2 fixtures, no datasource descriptors — a fresh home comes up with an empty datasource list. SetSAIKU_SEED=trueto install the fixtures on a non-demo boot, orSAIKU_DEMO=true SAIKU_SEED=falsefor the demo login against your own cubes. Seeding is seed-if-absent, so an existingsaiku-homeis never rewritten or emptied.
The container runs as a non-root user (uid/gid
10001:10001). A fresh named/anonymous volume works out of the box. Any pre-existingsaiku-homefrom an older root container — bind mount or named volume — must be re-owned once:sudo chown -R 10001:10001 <host-dir>, or for a named volumedocker run --rm -v saiku-home:/app/saiku-home --user 0 --entrypoint chown ghcr.io/spiculedata/saiku:latest -R 10001:10001 /app/saiku-home. The container fails closed with aFATAL:message (naming the fix) rather than silently rotating its encryption key. On Kubernetes setsecurityContext: { runAsUser: 10001, fsGroup: 10001 }. See the CHANGELOG upgrade note for details.
A hosted instance is always live at https://demo.saiku.bi (auto-reset nightly).
Saiku started in 2010 as an open-source OLAP browser for Mondrian. In 2026 it was rebuilt as a modern Semantic Layer on top of:
- Mondrian 4.8.1.x (Spicule fork) — with a Calcite-based SQL planner
alongside the legacy
SqlQuerybuilder. Calcite is the default; force legacy with-Dmondrian.backend=legacy. The Calcite planner reaches modern engines too — seeexamples/lakehouse-demofor a Saiku → Mondrian → Calcite → Trino → Iceberg walkthrough. - Apache Arrow wire format for cellsets, so the browser and any programmatic consumer share a zero-copy result envelope.
- Jetty 12 EE10 + Jersey 3.1 + Spring 6 + Spring Security 6.5 in a single-JAR Picocli launcher.
- SvelteKit 5 + Vite for the SPA (separate repo, served from inside
the same JAR at
/ui/).
Saiku 4.x exposes a typed REST surface — /rest/saiku/api/ai/* — designed
for LLM agents. Hierarchies, levels, measures and synonyms are discoverable
via /ai/cubes and /ai/schema, and a single POST /ai/query translates
a JSON description of a question into validated MDX, runs it, and returns
typed {value, formatted, unit} cells. Every validation failure carries
a {status, field, available} envelope so an agent can self-correct
without scraping logs.
The same self-describing, self-correcting contract has a SQL-side twin at
/rest/saiku/api/ai/ossie/* for datasets modelled with the Ossie semantic
layer — same list → schema → query shape, same VALIDATION_ERROR envelope,
plus POST /ai/ossie/ask for a plain-language question. Anomaly and forecast
endpoints (/ai/anomaly, /ai/forecast) share the same typed envelope.
The container also bundles saiku-mcp, a stdio
Model Context Protocol wrapper so Claude
Desktop / Cursor / Cline can wire to a running Saiku with one line of
config:
{
"command": "docker",
"args": ["exec", "-i", "saiku", "saiku-mcp"]
}See docs/AI-QUERY-API.md and
docs/schema-annotations.md for the typed
contract and the saiku.semantic.* annotation namespace cubes use to
describe themselves to agents.
Reviewing a schema change before it lands:
# What does this edit break?
saiku model diff --from-git origin/development --from-git HEAD \
--before saiku-launcher/src/main/resources/seed/FoodMart4.xml \
--after saiku-launcher/src/main/resources/seed/FoodMart4.xml \
--repository ./saiku-home/repository/dataDiffs two models (Mondrian XML or Apache Ossie YAML), detects renames as renames,
and lists every saved query, dashboard and app still pointing at a member the change
removes — as Markdown, JSON, or POST /rest/saiku/api/admin/model/diff. On a pull
request that touches a model, the model-diff workflow posts the same report as a
sticky comment. See docs/MODEL-DIFF.md.
Point Saiku at a warehouse and it will build a starting Ossie semantic
model — cubes, dimensions, measures, joins — plus a rationale document
explaining every decision. See
docs/OSSIE-MODEL-GENERATION.md.
Admins can extend the AI surface without code:
- Skills (
saiku-home/skills/*.md) — markdown workflows with YAML frontmatter, discoverable from/ai/ask. Invoke one explicitly by prefixing an ask with/<skill-name>, or ask naturally and let the LLM route via the skill catalogue. - Spaces (
saiku-home/agent-spaces/*.json) — named personas that scope an ask to a system prompt, a cube allowlist and a skill allowlist.POST /ai/spaces/{id}/askenforces the persona server-side, so a cube outside the allowlist is a 403 the user can't override.
See docs/SKILLS-SPEC.md and
docs/AGENT-SPACES-SPEC.md.
Build shareable dashboards of chart / table / KPI / text / image tiles over your
cubes — with cross-tile filters, click- and brush-cross-filtering,
drill-down/through, conditional formatting, combo charts, anomaly/forecast
overlays, auto-refresh, PDF/PNG export and read-only share links. See the
docs/dashboards-user-guide.md for the full
walkthrough, and saiku-ui/src/embed/README.md
to embed a dashboard in your own app via the <saiku-embed> web component.
Saiku speaks the SCIM 2.0 core profile, so Okta, Microsoft Entra ID or
OneLogin can own the user lifecycle: an admin mints one bearer token per
connector, and create / update / deactivate / group-assignment all flow into
the Saiku user directory without anyone touching the admin console. SCIM
handles lifecycle; OIDC/SAML handles authentication — a provisioned account has
no usable local password. See
docs/SCIM-PROVISIONING.md for the connector
walkthrough, the attribute mapping and its limits.
A first-party Sheets add-on (integrations/google-sheets/, #1436)
queries the semantic layer from a spreadsheet sidebar — cube picker, measure
and dimension shelves, Insert as table, and a Refresh that rewrites the
same block in place so your formatting survives. It talks to the same typed
/saiku/api/ai/* surface as the MCP server and the Excel add-in. See
docs/sheets.md.
Saiku ships opt-in OpenTelemetry instrumentation via the OTel Java
agent — zero code changes, zero overhead when off. Setting
OTEL_EXPORTER_OTLP_ENDPOINT activates auto-instrumentation for Jetty,
Jersey, JDBC (every Mondrian-emitted SQL becomes a child span),
outbound HTTP, JVM metrics, and DBCP2 connection pool metrics. Trace
context is injected into the Saiku log pattern automatically.
docker run -d -p 8080:8080 \
-e OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318 \
-e OTEL_SERVICE_NAME=saiku-prod \
ghcr.io/spiculedata/saiku:latestWithout the endpoint env var the agent is never loaded. See
docs/observability.md for the full env-var
reference, sampling guidance, and what's not yet covered (Tier 2
custom spans for ThinQueryService etc.).
Two guardrails an operator is expected to tune, both documented in
docs/operator-hardening.md:
- SMTP relay host — the admin mail wizard's host is put through the same
resolve-and-range SSRF gate alert webhooks use, plus an SMTP port allowlist
(
saiku.mail.smtp.*). Prefer an ops-managed relay viaSAIKU_MAIL_SMTP_HOST, which makes the wizard read-only. - AI ask cost budget — per-principal and per-instance daily ceilings
charged from the token usage the provider actually reports, plus a cap on
concurrent chained asks (
saiku.ai.budget.*).
Quality signals — per-module test-count and line-coverage floors, UI type
checks, UI tests — are declared as files (.github/test-floors.json,
.coverage-thresholds.json) and gated on every PR by the ci workflow.
A separate weekly run, .github/workflows/quality-report.yml, renders the same
signals as one Markdown quality dashboard in its job summary: where each
module stands, and by how much headroom. That run is read-only and is not a
gate — the gates stay in CI. See docs/quality.md. For how
CI, the merge queue, images, previews and the demo deployment fit together, see
docs/ci-overview.md.
JDK 21 + Maven 3.9+ required.
Set up GitHub Packages auth first, or the build fails before it compiles. Saiku's Mondrian fork, olap4j,
saiku-query and Ossie artifacts are published to GitHub Packages, which requires an authenticated token even
though the packages are public. Without it you get a bare 401 Unauthorized on pentaho:mondrian that never
mentions tokens:
- Create a classic personal access token with only the
read:packagesscope (Tokens (classic)). It must be classic — GitHub's Maven registry does not accept fine-grained tokens, and the UI defaults to fine-grained. Our packages are public, so noreposcope or org membership is needed. - Add five
<server>entries to~/.m2/settings.xml—github-mondrian-saiku,github-olap4j,github-olap4j-xmlaserver,github-saiku-query,github-ossie. Copy the block from.github/workflows/ci.yml; one token covers all five.
Still getting a 401? A fine-grained token and a classic token missing read:packages produce an identical error,
so check what the token actually has before minting another —
curl -sI -H "Authorization: token $PAT" https://api.github.com/user | grep -i x-oauth-scopes. A classic token's
scopes are editable in place, and the value doesn't change, so settings.xml needs no edit.
# Compile, unit tests, Spotless format check (CI gate):
mvn verify
# Build the runnable fat-JAR:
mvn -pl saiku-launcher -am -Dmaven.test.skip=true package
# Run:
java -jar saiku-launcher/target/saiku-*.jar serve --port 8080 --home ./saiku-homeWhole-API integration tests (boots Jetty + the launcher's WAR in-process against the seeded FoodMart H2 datasource):
mvn verify -P integrationSee CLAUDE.md for the full layout, the dependency catalog
(saiku-bom), and the GitHub Packages auth gotcha for local builds.
The fat JAR, dist zip, SBOM, container image and npm packages carry
keyless Sigstore-signed SLSA build provenance,
and each release ships a SHA256SUMS file. See
Verifying release artifacts
for the commands per artifact type (gh attestation verify,
cosign verify-attestation, sha256sum -c, npm audit signatures).
saiku-bom/ # central dependency-version catalogue
saiku-core/
saiku-olap-util/ # olap4j helpers
saiku-service/ # Semantic Layer service, AI Query, schema gen, async, cache
saiku-semantic/ # YAML semantic layer
saiku-web/ # JAX-RS REST resources
saiku-webapp/ # Servlet webapp (Spring XML wiring)
saiku-launcher/ # Picocli CLI + embedded Jetty serving the WAR
saiku-mcp/ # stdio JSON-RPC MCP wrapper
saiku-ui/ # SvelteKit SPA (independent versioning)
The SvelteKit SPA lives in saiku-ui/ and is built independently; the
launcher serves the static dist/ under /ui/.
- Bugs and feature requests: open an issue.
- Questions, ideas, walkthroughs: GitHub Discussions.
- Chat: Saiku Cloud Slack.
- Stack Overflow tag:
saiku. - Commercial support, hosted, training: hello@saiku.bi.
The old groups.google.com/a/saiku.meteorite.bi lists and ##saiku IRC
channel are no longer monitored.
See CONTRIBUTING.md. Short version:
feature/<name>branch offdevelopment— see the Gitflow note in CLAUDE.md.- Run
mvn spotless:applybefore committing (a pre-commit hook is available via./scripts/install-hooks.sh). - Tests live in
**/src/test/java/; integration tests insaiku-launcher/src/test/java/org/saiku/launcher/it/. - Open the PR against
development, notmain.mainis the release branch — only release/* and hotfix/* PRs go there.
Saiku is dual-licensed under Apache 2.0 and EPL 1.0. See
LICENSE. A summary lives at
https://saiku.bi/#license.
The original Saiku project was started by Tom Barber and Paul Stoellberger in 2010 at Meteorite BI and now lives at Spicule. Contributors are listed on the GitHub contributors page.
For release notes see Releases.