Repository navigation
wql reference
WQL queries discover notes, sessions, and emitted workout statements, then reduce numeric observations and choose a chart.
:journal{effort:snatch}
:segment{effort:snatch} | :sum{metric:tis} | :value{}
@session | :sum{metric:tis} by {effort} | :bar{}
| Head | Selected records |
|---|---|
:journal{} |
Journal notes |
:feeds{} |
Collection notes |
:playground{} |
Playground notes |
:note{} |
Whole Notes, including prose-only Notes |
:block{} |
Actionable workouts, queries, registered widgets, and interactive embeds |
:effort{} |
Movement registry entries |
:session{} |
Workout statements grouped by session |
:segment{} |
Domain segment statements, outputType === 'segment'
|
:event{} |
The full emitted debug statement stream |
:segment and :event read the same EventRecord store. Debug queries include system, compiler, load, completion, and other emitted statement types, including statements without numeric metrics. Finalized summary records are not emitted debug statements.
The scoped note heads restrict the storage source. :note{source:guides} explicitly selects guides. source: accepts journal, feeds, guides, playground, dashboards, and efforts, plus explicit storage identities such as collection:crossfit-girls and feed:<id> — one feed (source:feed:crossfit-programming) or one quoted feed item (source:"feed:crossfit-programming/2026-01-12"). :feeds selects collection-prefixed storage sources; dated feed: rows remain outside that scope.
:note{tags:benchmark}
:journal{equipment:barbell}
:block{effort:thruster} last 8w | limit 20
:effort{discipline:strength,intensity:high}
:session{result:r1,plane:segment}
:event{result:r1}
Note and block results resolve their parent through the page_notes relationship. Page-bound results link to the parent Page; standalone results link to the Note.
:note{text:recovery} matches a Note's title or its complete authored Markdown body. Headings, prose, and frontmatter remain searchable even when the Note has no actionable blocks.
:block returns only wod, query, widget, and embed occurrences. Prose, headings, frontmatter, and unknown or malformed fences do not create block results. Each result validates its occurrence ID, saved version, source revision, and UTF-16 range against the parent Note map, then reads the exact authored source slice. A stale or missing map cannot hydrate a result. Block links retain the parent route and occurrence anchor.
The persisted source pin is blockId plus blockVersion. Runtime :segment still selects emitted segment statements and does not refer to persisted Note blocks.
Pipelines evaluate left to right. A source selects the input once; each function consumes the preceding result. A chart is the final stage.
:segment{effort:snatch} | :sum{metric:tis} by {session} | :max{} | :value{}
@today | :sum{metric:tis} by {effort} | :table{}
:sum{metric:tis} by {week} last 12w | :timeseries{}
Functions are :sum, :avg, :min, :max, :count, :last, and :delta. The first numeric reducer names a metric with metric:. Later reducers can inherit the preceding metric. :count{} counts projected observations without requiring a metric. It does not count metricless debug statements.
The established numerical syntax remains supported:
sum:totalVolume{} by {week} last 12w
max:resistance{effort:back-squat}
avg:pace{effort:run} by {week}
Metric keys include reps, distance, resistance, elapsed, power, pace, totalVolume, totalDistance, tis, sessionLoad, and calculated fields such as calc.e1rm, calc.acwr, calc.monotony, and calc.strain.
A pipeline cannot introduce a new source after a function, place a stage after a chart, or contain empty stages. Unsupported clauses produce a diagnostic rather than silently starting another database query.
The page loader registers the datasets before child queries execute:
-
@sessioncontains the active workout's live execution statements and segment outputs. No active workout means an empty dataset, not the most recent historical workout. -
@todaycontains telemetry and notes for the current civil day in the captured execution timezone. Day boundaries follow local midnights, including daylight-saving transitions.
Dataset pipelines use the registered in-memory rows. Downstream reducers do not fetch the EventStore again.
@session | :sum{metric:tis} | :value{}
@today | :sum{metric:tis} by {effort} | :bar{}
Chart heads are :timeseries, :bar, :table, :donut, :toplist, and :value. The sink receives the evaluated dataset, not a new query.
```query
@today | :sum{metric:tis} by {effort} | :bar{}
```Fence presentation such as query:table remains available. An explicit pipeline sink chooses the pipeline's chart.
Query documents retain named assignments, formulas, defaults, and ordered show outputs:
defaults by {week} last 12w
work = :sum{metric:tis}
recovery = :sum{metric:sessionLoad}
ratio = work / recovery
show work, ratio
Filters are comma-separated key:value clauses inside braces. Values within one key can use | for alternatives, ! negates a key, and * marks a prefix match where supported. Quoted text preserves spaces and literal pipes.
:segment{effort:snatch|clean,!discipline:recovery}
:note{text:"snatch | clean"}
Common keys include effort, discipline, intensity, origin, tags, source, text, type, catalog, result, block, and note. Typed note tags include domain, format, equipment, quality, and intent. plane: narrows session outputs. Registered custom dimensions are queryable on numeric facts and segment/event tables.
Filter support depends on the target. Unsupported filters and presentation clauses produce advisories. For example, note queries do not implement movement-registry discipline filters; use :effort{discipline:strength} or a note tag instead.
-
last 2wandlast 30dselect relative windows. -
from 2026-09-01 to 2026-09-30selects a civil range, including the end day. -
by {day}andby {week}use civil days and Monday-aligned weeks in the execution timezone. - Note and block grouping is open over note properties:
by {<tag-type>}groups by any configured tag type (domain,equipment, custom types from tag settings), resolving each entry's value from its typed tags; entries without the property group underUnassigned. -
.rollup(2w)and.rollup(7d)select multi-unit buckets. Use grouping instead of.rollup(1d)or.rollup(1w). -
in kgandin lbrequest display-unit conversion.
Time selection uses the observation's domain date. Notes use date, falling back to createdAt; blocks use their parent note date; sessions use completion time; numeric facts use their metric date.
Row presentation pipes remain supported:
:segment{effort:snatch} in lb last 2w | select resistance in lb,effort | order by resistance desc | limit 5 offset 2
:feeds{} | order by title | offset 20
Segment/event tables apply selection, ordering, and pagination. Notes, blocks, and efforts apply ordering and pagination. Sessions apply pagination and retain completion-time ordering.
where joins still connect content discovery to numeric predicates:
sum:totalVolume{} where :note{format:emom}
:note{intent:benchmark} where :sum{metric:totalVolume} > 5000
-
find:<target>is retired. Use:<target>. -
source:collectionsis retired. Usesource:feeds. -
rows:all,rows:segment, androws:eventare retired. Use:session,:segment, or:event; useplane:for session narrowing. -
:pageis not a source head. Use note filters and the parent Page relationship. -
source:page,source:pages, andsource:allare retired.