From semlang
Use when reading, writing, or running SemLang semantic-model files, including reusable ontology changes, query workflows, and one-off SemLang analysis packages.
How this skill is triggered — by the user, by Claude, or both
Slash command
/semlang:semlangThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This is a concise guide for agents that need to read or write SemLang.
This is a concise guide for agents that need to read or write SemLang.
SemLang is best understood as Malloy with a semantic ontology layer. Keep Malloy's mental model for sources, joins, dimensions, measures, views, and queries, then add the SemLang differences below.
source becomes a SemLang concept.concept Sale is event from duckdb.table('transactions').dimension:, measure:, view:, where:, group_by:, aggregate:, and query: ... -> { ... } remain the default shape.query: q is SaleLine -> { ... }.package declaration. include declarations may follow the package and must come before sources, types, concepts, lenses, and queries..semlang file for the task. Put its package first, include the relevant core semantic files immediately after the package declaration, define only the task-specific sources, lenses, views, or queries needed there, and run that file instead of polluting the core model.type: declarations give primitive values semantic meaning, such as Dollars, CustomerId, or BusinessDate. Primitive bases are string, number, date, timestamp, currency, and boolean.description, enum, const, default, examples, bounds, pattern, and format. Use enum, not legacy allowed_values; use description, not legacy semantics.source: declarations name reusable Malloy source expressions. They can wrap a table, SQL expression, another source/concept/query, or a root plus query body: source: active_sales is Sale -> { where: status = 'active' }.concept X is kind/event/situation/relator/phase ... names what a row means, not just where it is stored. A phase names its parent: concept ClosedStore is phase of Store from ....description: metadata is preserved and appears in exported concept JSON Schema.identity declares the semantic key and lowers to Malloy primary_key.field: declarations attach semantic types to source-backed fields. A trailing ? marks nullability; unique records uniqueness metadata.join_one, join_many, and join_cross. join_one and join_many use on or with; join_cross may omit on and cannot use with.? after the join name, as in join_one customer?: Customer on customer_id, marks optional participation metadata without changing the emitted Malloy join kind.join_one inline named-connection sources such as duckdb.table('customer_profiles').role Name when predicate names a meaningful classification when the name adds business meaning. Its canonical name is Concept.Name; use optional label and aliases metadata for business-language discovery.path is Concept.Role or an unambiguous short name such as path is Active.occurrence_time:, valid_time:, observation_time:, and recorded_time: document event time, valid-time state, observed state time, and load/record time.at expression instead of repeating period containment predicates.validation: declarations are data-quality rules. They are not query filters.where: filters restrict the concept source and lower to Malloy source filters.lens: declarations are query-time overlays for contextual filters or vocabulary, similar in spirit to Malloy source extension but applied to existing semantic names. Lenses can inherit parent lenses, add lens-local types, and refine concepts with fields, joins, roles, dimensions, measures, views, validations, temporal axes, identities, and where filters.subject, param:, guard:, edit:, write mappings, logs, effects, and agent: metadata. They do not lower to Malloy reads.writeable only when actions may assign them. A writeable source field implies write: column field_name = value; a writeable derived dimension must declare explicit write mappings.x-semlang-* metadata rather than translated into misleading native validation keywords.where: directly rather than declaring a role for the same predicate.with foreign_key when joining to a concept by its identity and the shorthand preserves the intended relationship.field: blocks and derived values in dimension: or measure: blocks.view: declarations for reusable analytical shapes. Views and queries support where, select, project, group_by, aggregate, having, calculate, nest, index, order_by, and limit/top where valid.project: only as compatibility spelling; expect it to emit as Malloy select:.top: only as compatibility spelling; expect it to behave as a row limit.? alternation, to ranges, ~/!~ matching, and filter strings like f'this week'.with, and parent/named lenses apply left-to-right to a copied query model.where: on the concept, lens refinement, view, or query.agent: metadata as presentation metadata, never authorization.package first except for comments and blank lines.include declarations immediately after the package. Includes are model loading, not textual macros, and cycles are invalid.duckdb.table('orders') or duckdb.sql("""select ..."""). Do not write unqualified table('orders').from clause may reference a table, SQL source, named source, another concept source, or a query result.occurrence_time on events, missing observation_time on situations, suspicious type/join modeling, and Malloy SDK validation problems.requirements/REQ-XX-NAME.md files.01.02.001.// Covers: 06.01.001.semlang mcp.npm install and npm link from your SemLang checkout.{ "command": "semlang", "args": ["mcp"] } under an mcpServers.semlang entry.semlang setup from the agent project before starting agents; it creates .semlang/settings.yml.load_ontology({}); the ontology entrypoint, Malloy config path, and export directory come from .semlang/settings.yml.semlang setup --preview to inspect generated config, --path <file> when entrypoint discovery is ambiguous, and --force to overwrite an existing config.load_ontology still accepts path, configPath, and malloyConfigPath as one-off escape hatches.run_query uses the captured Malloy config, requires a positive integer query_limit_seconds, returns a transaction GUID, and exports row output larger than 10 lines to the managed export directory.Malloy:
source: line_items is duckdb.table('retail_line_items') extend {
primary_key: line_item_id
join_one: sale is transactions on transaction_id = sale.transaction_id
measure:
net_sales is sum(net_sales_amount)
}
SemLang:
concept SaleLine is situation from duckdb.table('retail_line_items') {
identity line_item_id :: SaleLineId
join_one sale: Sale on transaction_id
field:
net_sales_amount :: Dollars
measure:
net_sales is sum(net_sales_amount)
}
Lens filter:
lens: western_region is {
refine: Store extend {
where: region = 'West'
}
refine: SaleLine extend {
where: sale.store.region = 'West'
}
}
Action:
concept SupplierLot is kind from duckdb.table('supplier_lots') {
identity supplier_lot_id :: SupplierLotId
field:
status :: SupplierLotStatus writeable
quarantine_reason :: QuarantineReason? writeable
action quarantine {
subject: single
param:
reason :: QuarantineReason
guard:
this.status in ['received', 'released']
else "Only received or released lots can be quarantined."
edit:
set status = 'quarantined'
set quarantine_reason = reason
agent:
expose: true
risk: high
requires_confirmation: true
}
}
Choose the Malloy-shaped expression first, then add SemLang semantics only where they clarify package structure, source reuse, identity, concept type, role meaning, time, validation, query-time context, JSON Schema metadata, or write intent.
npx claudepluginhub unsupervisedcom/semlangGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.