bxl-authoring
Use when writing or reviewing a BXL expression in a Boxel card — a computeVia built from expression(), the fx / jq tags, spreadsheet-formula fields…
Skill by cardstack
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/cardstack-bxl-authoring
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: spreadsheets, writing
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/bxl-authoring
What's inside
- Skill name
bxl-authoring- Description
- Use when writing or reviewing a BXL expression in a Boxel card — a computeVia built from expression(), the fx / jq tags, spreadsheet-formula fields, aggregations over linked or query-backed collections. Covers which tag to reach for, what the derive profile refuses outright, the silent traps (a stream where an aggregate was meant, jq interpolation in a plain string, & on a blank field, dates and "today"), and why an indexed computed can differ from the one the viewer sees. Activates on expression(, fx`…`, jq`…`, "BXL", "formula field", "computed field with Excel functions", "sum the linked cards".
- License
- MIT
- Instructions
- 405 lines in SKILL.md · view on GitHub
Files (1)
- SKILL.md
SKILL.md (first lines)
# Authoring BXL in a card
BXL is the workspace's expression language: readable spreadsheet syntax and Excel
formula libraries on top of a jq engine. In a card it drives `computeVia`.
```ts
import { expression, fx, jq } from '@cardstack/bxl';
export class Claim extends CardDef {
@field paidAmount = contains(NumberField);
@field reserveAmount = contains(NumberField);
@field incurredAmount = contains(NumberField, {
computeVia: expression(fx`ROUND((PaidAmount + ReserveAmount) * 100) / 100`),
});
}
```
`expression` is the factory (`bxl` and `expr` are aliases); it compiles the
source once when the class body runs, then evaluates it against the card
instance on each read.
The rest of this skill is the decision layer and the trap list. For the full
syntax surface — labels, row selectors, predicates, the Excel function matrix —
read [bxl.boxel.site](https://bxl.boxel.site).
## 1. Which tag
| Source contains | Reach for | Why |
| ------------------------------------------- | --------------- | ------------------------------------------------------ |
| `\(…)` jq interpolation | `` jq`…` `` | A plain string drops the backslash — see trap 4 |
| Excel functions (`ROUND`, `IFS`, `SUM`) | `` fx`…` `` | Readable-syntax compilation, explicit at the call site |
| Bare PascalCase field labels (`PaidAmount`) | `` fx`…` `` | The compiler resolves them to `.paidAmount` |
| Pure jq (`.claims \| length`) | `` jq`…` `` | Skips the readable-syntax compile step |
| Quoted multi-word labels (`"Line Item"`) | `fx` + `schema` | Label resolution needs the schema — see trap 3 |
A plain string compiles exactly like `` fx`…` ``. Prefer a tag: it tells the next
reader which dialect they are in, and it is the only form that survives `\(…)`.
Mixing dialects inside one source is fine — `` fx`IF(.status == "Open", 1, 0)` ``
and `` fx`if Status == "Open" then 1 else 0 end` `` both work. Case is the
dispatch: `IF(cond, t, f)` is the Excel function, `if cond then … end` is the jq
construct.
## 2. The `derive` profile — what a computed may not do
`expression()` validates against the `derive` profile **when the field is
defined**, so a violation throws while the card module loads rather than
producing a wrong value. The diagnostic names the rule:
```text
computeVia expression violates the derive profile:
derive-call-banned: Profile.derive is for deterministic write/index-time
computation and cannot use call TODAY: volatile calls are not stable write-time
derivations.
```
Refused: volatile calls (`TODAY`, `NOW`, `RAND`, `RANDBETWEEN`, and the two
clock-reading validator helpers `isAfter` / `isBefore`) · request, actor and
mutation context (`@User`, `@Env`, `$new`, `$old`) · user-defined `def` helpers ·
jq `try` / `catch` · `error` · `label` / `break` · assignment (`=`, `|=`) ·
recursive descent (`..`) · format filters (`@csv`) · control and side-effect
calls (`debug`, `env`, `input`, `stderr`, `halt`) · runtime metadata
(`builtins`).
Allowed and useful: `IFERROR` / `IFNA` · optional access (`.a?`) · aggregates
(`SUM`, `AVERAGE`, `COUNT`, `NPV`) · validator helpers (`isEmail`, `isDate`) ·
`LET` · bindings (`. as $x | …`) · explicit folds (`reduce`, `foreach`) ·
structural ops (`keys`, `to_entries`, `group_by`, `unique`, `tojson`).
`isAfter` and `isBefore` are the surprise on that list: they sit among the
validator helpers, they look like ordinary date comparisons, and they default
their second argument to the current time — so the profile classes them with
`NOW`. Compare two stored dates with the operators instead
(`` fx`StartDate < EndDate` ``), which is deterministic and needs no helper.
The boundary is determinism: a derived value comes from the record snapshot, not
from the clock, the viewer, or the request. It is computed once server-side and
stored in the search doc, so anything ambient would bake one viewer's answer in
for everyone.
## 3. An aggregate needs a collected array, not a stream
**The single most expensive trap.** jq function arguments are streams, so
navigating into an array field and handing that straight to an aggregate calls
the aggregate once *per element* — and the field receives an array of per-element
results instead of one number. Nothing errors.
```ts
// WRONG — compiles to SUM(.claims[].paid); with two claims the field gets [10, 5]
computeVia: expression(fx`SUM(Claims[].Paid)`);
// RIGHT — collect first, then aggregate: 15
computeVia: expression(fx`SUM([Claims[].Paid])`);
// RIGHT — the jq spelling, with a fallback for the empty case
computeVia: expression(jq`[.claims[] | .paidAmount] | add // 0`);
```
Same for `AVERAGE`, `COUNT`, `MAX`, `MIN`, `SUMIF`. Collect **the argument that
iterates**, and only that one — the rule is narrower than "wrap everything", and
wrapping the wrong thing is its own bug:
- An iterating path is what needs it: `SUM([Claims[].Paid])`,
`SUMIF([Claims[].Paid], ">6")`.
- A field that already holds an array is a single value. `SUM(Amounts)` over a
`containsMany(NumberField)` is correct as it stands.
- A comma list is collected by the compiler, which is why the multi-argument
spelling has never shown the trap: `SUM(Paid, Reserve)` compiles to
`SUM([.paid, .reserve])`, and even `SUM(Claims[].Paid, 0)` becomes
`SUM([.claims[].paid, 0])`. Write the `[…]` anyway — the single-argument form
is what an author reaches for next.
- **Never wrap a scalar parameter.** `ROUND([1.234], 2)` and
`NPV([0.1], CashFlows)` hand an array to a function that wants a number; each
returns null.
Passing a `schema` is the other way to get this right — with field metadata, the
compiler collects implicitly, so `SUM("Line Item"."Line Total")` compiles to
`SUM([.lineItems[].lineTotal])`. Without a schema, quoted multi-word labels fail
loudly (`Cannot index string with string`) and a bare PascalCase label resolvesFrom cardstack/boxel-skills, MIT.
More from cardstack/boxel-skills
- 0.592score
boxel
cardstack
Use whenever creating, reading, or editing Boxel cards (.gts files), card instances (.json), fields, templates, queries, or anything in a Boxel realm.
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-theme-development
cardstack
Use when the deliverable is a theme ARTIFACT — creating, converting, auditing, or patching Theme, StructuredTheme, StyleReference, DetailedStyleReference, or…
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-ui-component-discovery
cardstack
MANDATORY before writing any UI in a `.gts` template, including a quick fix to an existing card (turning a styled span or div into a button, wiring a dead…
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-ui-guidelines
cardstack
Use when IMPLEMENTING or REVIEWING UI in Boxel templates (writing a template, or reviewing a change, diff or pull request that touches one) — applying…
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
card-motion
cardstack
Use when a card should animate: elements entering and leaving, a list or grid rearranging, a tile opening into a detail view, drag and reorder, scroll-linked…
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
catalog-listing
cardstack
Use when installing, browsing, remixing, updating, or submitting catalog listings (Apps, Cards, Fields, Skills, Themes) from a Boxel catalog realm.
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
catalog-reuse
cardstack
MANDATORY before writing any `.gts`.
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-design
cardstack
Use when DECIDING a Boxel card's visual language — mood, palette, typography direction, asset direction, one visual signature, the design-playbook process.
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-environment
cardstack
Use when running, navigating, or orchestrating tasks inside the live Boxel application — switching between Code Mode and Interact Mode, searching and editing…
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-file-def
cardstack
Use when adding or working with file-typed fields (FileDef, ImageDef, MarkdownDef, PngDef, CsvFileDef).
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-flavored-markdown
cardstack
Use when authoring or editing Boxel Flavored Markdown (BFM) content — content fields rendered as rich markdown with :card/::card directives, mermaid diagrams…
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-markdown-format
cardstack
Use when authoring a `markdown` template (static markdown format) on a CardDef or FieldDef — defaults, markdownEscape, and markdown helpers.
SkillAFreshness: A★ 1Claude Code +9
Signals
- Stars
- 1
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Oct 8, 2026 (21 days ago)
- Last release
- Oct 23, 2026 (6 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/cardstack/boxel-skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from cardstack
- 0.592score
boxel
cardstack
Use whenever creating, reading, or editing Boxel cards (.gts files), card instances (.json), fields, templates, queries, or anything in a Boxel realm.
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-design
cardstack
Use when DECIDING a Boxel card's visual language — mood, palette, typography direction, asset direction, one visual signature, the design-playbook process.
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-environment
cardstack
Use when running, navigating, or orchestrating tasks inside the live Boxel application — switching between Code Mode and Interact Mode, searching and editing…
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-file-def
cardstack
Use when adding or working with file-typed fields (FileDef, ImageDef, MarkdownDef, PngDef, CsvFileDef).
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-flavored-markdown
cardstack
Use when authoring or editing Boxel Flavored Markdown (BFM) content — content fields rendered as rich markdown with :card/::card directives, mermaid diagrams…
SkillAFreshness: A★ 1Claude Code +9 - 0.592score
boxel-markdown-format
cardstack
Use when authoring a `markdown` template (static markdown format) on a CardDef or FieldDef — defaults, markdownEscape, and markdown helpers.
SkillAFreshness: A★ 1Claude Code +9
Cite this page
bxl-authoring skill. Agent Mart. https://agentmart.dev/skills/cardstack-bxl-authoring (last updated 2026-10-24)