Claude Code for Cube: Semantic Layer and Headless BI — Claude Skills 360 Blog
Blog / AI / Claude Code for Cube: Semantic Layer and Headless BI
AI

Claude Code for Cube: Semantic Layer and Headless BI

Published: August 23, 2027
Read time: 5 min read
By: Claude Skills 360

Cube is the semantic layer for consistent metrics across all BI tools and apps. Data models in YAML or JavaScript: cube("Orders", { sql: "SELECT * FROM orders", measures: { revenue: { sql: "amount", type: "sum" } }, dimensions: { status: { sql: "status", type: "string" } } }). YAML: cubes: [{ name: Orders, sql_table: public.orders, measures: [{ name: revenue, sql: amount, type: sum }], dimensions: [{ name: status, sql: status, type: string }] }]. Joins: joins: { Users: { sql: "${Orders}.user_id = ${Users}.id", relationship: many_to_one } }. Segments: segments: { completed: { sql: "${CUBE}.status = 'completed'" } }. Pre-aggregations: pre_aggregations: { revenue_by_day: { measures: [revenue, order_count], dimensions: [created_date], time_dimension: created_at, granularity: day, partition_granularity: month } }. REST API: POST /cubejs-api/v1/load with { query: { measures: ["Orders.revenue"], dimensions: ["Orders.status"], timeDimensions: [{ dimension: "Orders.created_at", dateRange: "last 30 days" }] } }. GraphQL: query { cube { orders { revenue { value } status { value } } } }. Multi-tenancy: context_to_roles: ({ securityContext }) => [securityContext.tenant_id], row-level security: sql: \… WHERE tenant_id = ’${SECURITY_CONTEXT.tenant_id}‘`. JavaScript client: import cubejs from “@cubejs-client/core”, cubejsApi.load(query).then(resultSet => resultSet.chartPivot())`. Claude Code generates Cube data models, pre-aggregations, API integrations, and multi-tenancy configurations.

CLAUDE.md for Cube

## Cube Stack
- Version: @cubejs-backend/server >= 0.35
- Models: model/*.yml or model/*.js — cubes with sql_table, measures, dimensions, joins
- Pre-aggs: pre_aggregations block in each cube — critical for production performance
- REST: POST /cubejs-api/v1/load — accepts { query: { measures, dimensions, timeDimensions } }
- GraphQL: GET /cubejs-api/v1/graphql — with Cube GraphQL schema
- Auth: JWT token signed with CUBEJS_API_SECRET — { exp, iat, securityContext: {...} }
- Multi-tenancy: contextToAppId + queryRewrite for row-level security

Data Model

# model/cubes/orders.yml — Cube data model for orders
cubes:
  - name: orders
    sql_table: public.orders
    title: Orders
    description: All customer orders

    joins:
      - name: users
        sql: "{orders}.user_id = {users}.id"
        relationship: many_to_one

      - name: products
        sql: "{orders}.product_id = {products}.id"
        relationship: many_to_one

    measures:
      - name: count
        type: count
        title: Order Count

      - name: revenue
        sql: amount_usd
        type: sum
        title: Total Revenue
        format: currency

      - name: avg_order_value
        sql: amount_usd
        type: avg
        title: Avg Order Value
        format: currency

      - name: refund_rate
        sql: "CASE WHEN {status} = 'refunded' THEN 1.0 ELSE 0.0 END"
        type: avg
        title: Refund Rate
        format: percent

      - name: unique_buyers
        sql: user_id
        type: count_distinct
        title: Unique Buyers

    dimensions:
      - name: id
        sql: id
        type: string
        primary_key: true

      - name: status
        sql: status
        type: string
        title: Order Status

      - name: created_at
        sql: created_at
        type: time
        title: Created At

      - name: created_date
        sql: "DATE_TRUNC('day', created_at)"
        type: time
        title: Created Date

    segments:
      - name: completed
        sql: "{orders}.status = 'completed'"
        title: Completed Orders

      - name: high_value
        sql: "{orders}.amount_usd > 100"
        title: High Value Orders (>$100)

    pre_aggregations:
      - name: revenue_by_day
        measures:
          - revenue
          - count
          - unique_buyers
        dimensions:
          - users.plan
          - users.country
        time_dimension: created_at
        granularity: day
        partition_granularity: month
        refresh_key:
          every: 1 hour
        build_range_start:
          sql: "SELECT NOW() - INTERVAL '90 days'"
        build_range_end:
          sql: "SELECT NOW()"

      - name: revenue_by_status
        measures:
          - revenue
          - count
        dimensions:
          - status
        time_dimension: created_at
        granularity: month

Cube Server Configuration

// cube.js — Cube server configuration
const CubejsServer = require("@cubejs-backend/server")
const jwt = require("jsonwebtoken")

const server = new CubejsServer({
  checkAuth: (req, auth) => {
    if (!auth) throw new Error("No token")
    const decoded = jwt.verify(auth, process.env.CUBEJS_API_SECRET!)
    req.securityContext = decoded
  },

  /** Row-level security: filter data by tenant */
  queryRewrite: (query, { securityContext }) => {
    if (!securityContext?.tenantId) return query

    const userFilter = {
      member:   "users.tenant_id",
      operator: "equals",
      values:   [securityContext.tenantId],
    }

    return {
      ...query,
      filters: [...(query.filters ?? []), userFilter],
    }
  },

  /** Context for pre-aggregation partitioning per tenant */
  contextToAppId: ({ securityContext }) =>
    `tenant_${securityContext?.tenantId ?? "shared"}`,

  /** Scheduled refresh for pre-aggregations */
  scheduledRefreshContexts: async () =>
    ["tenant_a", "tenant_b", "tenant_c"].map((tenantId) => ({
      securityContext: { tenantId },
    })),
})

server.listen().then(({ port }) => {
  console.log(`Cube server listening on port ${port}`)
})

Next.js Integration

// lib/cube/client.ts — Cube API client for Next.js frontend
import { CubejsApi } from "@cubejs-client/core"

const CUBE_API_URL = process.env.NEXT_PUBLIC_CUBE_API_URL!

let _api: CubejsApi | null = null

export function getCubeApi(token: string): CubejsApi {
  const { default: cubejs } = require("@cubejs-client/core")
  return cubejs(token, { apiUrl: CUBE_API_URL })
}

export type MetricQuery = {
  measures:      string[]
  dimensions?:   string[]
  dateRange?:    [string, string] | string
  granularity?:  "day" | "week" | "month" | "quarter" | "year"
  filters?:      Array<{ member: string; operator: string; values: string[] }>
  limit?:        number
}

export async function runMetricQuery(
  token: string,
  query: MetricQuery,
): Promise<Array<Record<string, string | number>>> {
  const api = getCubeApi(token)

  const cubeQuery: Parameters<CubejsApi["load"]>[0] = {
    measures:   query.measures,
    dimensions: query.dimensions,
    filters:    query.filters,
    limit:      query.limit ?? 5000,
    ...(query.dateRange ? {
      timeDimensions: [{
        dimension: query.measures[0].split(".")[0] + ".created_at",
        dateRange: query.dateRange,
        ...(query.granularity ? { granularity: query.granularity } : {}),
      }],
    } : {}),
  }

  const resultSet = await api.load(cubeQuery)
  return resultSet.tablePivot()
}

// app/api/cube-token/route.ts — generate Cube JWT for authenticated users
import { NextResponse } from "next/server"
import { auth } from "@/lib/auth"
import jwt from "jsonwebtoken"

export async function GET() {
  const session = await auth()
  if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 })

  const token = jwt.sign(
    {
      tenantId: session.user.tenantId,
      userId:   session.user.id,
      role:     session.user.role,
      exp:      Math.floor(Date.now() / 1000) + 3600,  // 1 hour
    },
    process.env.CUBEJS_API_SECRET!,
  )

  return NextResponse.json({ token })
}

For the dbt Semantic Layer alternative when already using dbt Core or dbt Cloud and wanting to define metrics co-located with dbt models using the MetricFlow syntax — dbt Semantic Layer integrates directly into your existing dbt project while Cube is a standalone semantic layer server with its own data model language that can sit on top of any warehouse without requiring dbt. For the Looker/LookML alternative when needing an enterprise BI platform with a 20-year head start in semantic modeling, LookML data language, embedded analytics SDK, and Looker Studio integration — Looker is the de-facto enterprise choice while Cube is open-source, API-first, and better for embedding analytics in custom applications rather than the Looker Explore UI. The Claude Skills 360 bundle includes Cube skill sets covering data models, pre-aggregations, multi-tenancy, and JavaScript client integration. Start with the free tier to try semantic layer generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free