LumiCode help
Every command and topic /help knows, from LumiCode v1.22.X.
Commands and topics
Query
/run- find SQL and run it, or load it into the editor/recent- browse recent queries: run, recall, save, schedule/results [text]- reload a past run's results, still held server-side/pretty- print the last query, formatted/copy [what]- put the last query, result or record on the clipboard/feedback- print the last run's full feedback log/ai [text]- talk to Candela in this prompt; /sql returns to SQL/sql- leave a Candela conversation, back to running SQL
Results
/rows- browse the last result: every row and column, paged/chart [kind]- draw the last result as a chart, into the transcript/group [columns]- browse the last result grouped, with a total per group/lineage [what]- how the last result was arrived at, as a tree/stats- min/median/max/avg + sparkline per numeric column/save- export the last result, or create a Saved Query
Explore
/catalog [text]- browse providers and their fields/history- search and browse query history under a histogram/api-history- search and browse the API request log under a histogram/access-history- search and browse the entitlement log under a histogram/diagnose [id]- all the platform recorded about one query run/queries- browse Saved Queries: run, edit, move, delete/drive- browse Drive: download, move, copy, delete/schedules [job]- scheduled query jobs and when they ran (read-only)/cfg- browse and edit the Configuration Store
Executables
/certificates- list and download client certificates/whats-new [all]- what a newer LumiCode would bring, and take it if you like/update- update LumiCode itself to the latest published version/binaries- download a Luminesce binary, and optionally install it
Session
/select- select the transcript by keyboard and copy it/clear [what]- clear the output area, or the record with it/transcript [file]- write the session as Markdown, or as an HTML page/usage [what]- how much LumiCode has been used, this session and in total/set [option]- change a setting; bare /set shows them all with values/help [topic]- this list, or one command or topic in full/exit- leave LumiCode
Topics
keys- running, editing and recall keysrunning- what the keys do while a query is runningsets- named queries run together, each reading those aboveselection- selecting text with the mouse, and who is selecting itglyphs- what the markers in a list or a heading mean
/run
find SQL and run it, or load it into the editor
Also /open.
Asks where the SQL comes from first.
local files - the file browser, starting where it last was and filtering as you type. Default glob *.sql; anything with * or ? sets a new one, and a leading . reveals dotfiles. ⏎ opens a folder · ⇥ completes · ⌫ goes up · ^R re-listsLUSID Saved Queries - pick a workspace, then a query. Both filter as you type.
Query sets are offered too: *.lumiq.json files, and the ⧉ rows of a workspace. One opens as its --- @Name buffer, keeping its settings, last-used values and export settings for its next run and save (/help sets).
See also /recent · /queries.
/recent
browse recent queries: run, recall, save, schedule
Also /mru.
On a query: run it, discuss it with Candela, recall it into the editor, delete it, copy it to the clipboard, save it to a file, save it into LUSID Workspaces as a Saved Query, or run it on a schedule - the LUSID Scheduler's Luminesce Query Runner job. Several can be pruned at once.
⧉ copy it to the clipboard copies the query as it ran, not as it is drawn - ^P is how you ask for it formatted. Dragging it off the screen works too (/help selection): its heading is a SQL comment, so it runs.
Running one from here puts it under ↑ too, so carrying on with it means pressing ↑ and editing rather than coming back for it. The prompt only remembers what was typed at it, which a recalled query never was - so ✎ put it under ↑ is for the times you want it there and do not want to run it.
Typing a number at the prompt still recalls that query directly, without opening the list.
See also /history · /ai · /schedules · selection.
/results [text]
reload a past run's results, still held server-side
Lists your completed queries whose results have not yet expired, newest first, with how long ago they ran and how long they are kept for. /results text lists only the queries containing text; typing filters further.
On one: load the results, run it again, discuss it with Candela, put it under ↑, or copy it to the clipboard.
A query set (⧉) is listed once: load all of its results, each under its name, or just one. With all of them, /save offers them as one file.
Loading makes it the last result, as if it had just run - /rows, /stats, /chart, /group, /save and /lineage all work on it. /feedback fetches its log from the server.
See also /recent · /feedback · /history.
/pretty
print the last query, formatted
^P does the same to the buffer you are editing, in place.
See also keys · /copy.
/copy [what]
put the last query, result or record on the clipboard
/copy or /copy sql - the query that ran last, as it ran rather than as it is drawn. /pretty formats it; /recent and /history have older ones.
/copy result - every row of the last result, as values: no thousands separators, a boolean as true, an empty cell for ∅. All of it, not the twenty rows shown - esc gives up on a long fetch.tsv by default, for pasting into a spreadsheet · csv · md for a pipe table. It stops at 50,000 rows and says so; /save writes the lot to a file.
/copy transcript - the session's record as Markdown, the same one /transcript writes and with the same question about which parts of it.
Over SSH your terminal is asked to copy instead (OSC 52), since the clipboard programs are on the wrong machine. A terminal that refuses says nothing, so the line says which route was taken.
Dragging across the transcript copies it too (/help selection), but these come out tidier: no panel borders, and a result as values rather than as it was drawn.
See also /pretty · /recent · /transcript · /save · selection.
/feedback
print the last run's full feedback log
The same log is on f while a query is running, and on f in a /history detail - where it is fetched from the server for that run, however long ago it was.
After a run of several queries - a query set, or a buffer split on \ - each query's feedback is under its own line from the live block: how it ended (✔ ✗ ⤼, ⏸ detached), its name and its first line - and a set's ends with what failed and what was skipped. A set reloaded by /results has its feedback fetched too.
A query set's starts with which query reads which: each under those it reads, those reading none at the top. One reading several is drawn under the first, and named again under the others as shown above.
See also /history · running.
/ai [text]
talk to Candela in this prompt; /sql returns to SQL
Also /candela.
/ai resume reopens a recent conversation./ai last [question] asks about the query you just ran - its failure too, if it failed./ai <anything else> is simply the first thing you want to say.
/recent → ✦ discuss it with Candela does the same for any query already in the history.
/sql is the way back, and so is esc on an empty prompt - with something typed, esc clears the line as it always does. Every form of /ai opens a conversation and none of them closes one, so the command you reach for to talk to Candela cannot hang up on you.
^C stops waiting on a turn. The turn itself carries on server-side - it is the watching that stops, as detaching from a running query does.
While a turn runs, the tool it is using opens out under its own name and the one before it collapses to a line; the conversation's token counts stay pinned underneath, with this turn's own share of them beside each. That trace is thrown away when the turn ends unless /set ai-tools collapsed or full asks for it to be kept.
See also /sql · /recent · /lineage.
/sql
leave a Candela conversation, back to running SQL
The conversation is not lost by leaving it - /ai resume reopens it, and /ai on its own opens a new one.
esc on an empty Candela prompt does the same thing, and is the shorter way to say it.
See also /ai.
/rows
browse the last result: every row and column, paged
Also /grid.
Paged server-side, so the whole result is reachable however large it is.
↑↓ rows · ←→ the column cursor · ⏎ one row in full · s sort · c pick columns←→ moves a cursor rather than just panning - the ▸ in a heading is the column s orders by and ⏎ opens on. The view pans when the cursor reaches the edge.⇧s orders by a column as well as the ones already in hand, so ▲1 ▼2 on the headings reads as "by the first ascending, then the second descending". Pressing it again on a column turns that one around, and again drops it./ filters with raw SQL, e.g. strftime('%Y-%m', SomeDate) = '2026-06'/group opens the same grid grouped, with a total per group and the rows inside it.
In the c column picker, s orders by the marked column - easier than panning the grid until it is the leftmost one - x explains it and t the whole query.
In the ⏎ record view, ↑↓ move between that row's fields and [ ] move between rows. c copies the marked field to the clipboard - the value itself, so a timestamp copies as the round-trip form the server sent rather than the tidied one on screen. ⏎ again opens one field wrapped and scrollable, which is the only place a large value can be read in full, and c there copies the lot.
A value whose provider gives it a link is clickable wherever it is drawn: the result printed after a query, this grid, and the ⏎ record view, where it is marked ↗.
See also /group · /lineage · /stats · /save · glyphs.
/chart [kind]
draw the last result as a chart, into the transcript
A chart of the rows /rows would page through: pick a kind, a column to group by and a column to measure, and it is drawn into the transcript where it stays beside the query that produced it.
/chart gallery draws a small example of every kind from canned data - what each one looks like, before you point one at a result. It needs no query, so it is there to browse whenever, and it lands in the record with the rest of the charts - which is the quickest way to see what any of them looks like in a file.
column and bar group rows by a category and sum the measure, so a bar is a total. Column is vertical with the categories along the bottom, for a sequence; bar is horizontal, one per row, for a ranking - and the only kind that can hold long names.
stacked and grouped split each category by a second one, so they ask a third question. Stacked is the bar chart with its length divided up - what each total is made of, and the answer to "can we have a pie chart": twenty parts fit where a pie holds five, and lengths along a shared baseline are read more accurately than angles. Grouped puts the series side by side instead, one cell each, for comparing them category by category - which a stack cannot, since only its bottom segment starts from the same place.
pie draws shares of a total as a ring, with the total in the hole - for a dashboard that has a pie in it. Six slices at most, the rest summed into other, and the key carries each slice's name and its percentage, because there is nowhere to write a name around a circle this size and an angle cannot be read to better than "about a third". A slice worth nothing or less has no angle to take and is left out, and the line above says how many were. Where the reading matters more than the resemblance, stacked is the better chart: it holds twenty parts, costs one row against this one's twelve, and lengths on a shared baseline are read more accurately than angles by everybody.
treemap draws shares of a total as nested rectangles, each one's area its share, with its name and percentage written inside it. It is the only kind that draws two levels at once: give it a column to group by and each group gets a rectangle of its own with its tiles inside it, so one chart answers which desk is the big one and what that desk is made of. Give it a second measure to colour by as well and the tiles are shaded from pink through grey to green - a signed scale, so grey means nothing much happened and the line under it marks where zero sits. Both of those are optional and it is the only kind with anything optional: press return on (none) to leave one out. A tile too narrow for its name gets a number, keyed underneath. Area is the weakest way to carry a number, so where the rows are a handful of comparable shares stacked or bar reads better - what this is for is a hierarchy, and a long tail that a bar chart would draw as forty hairlines. A negative measure has no area at all: those rows are left out and the line above says how many.
boxplot draws the spread within each category as a box and whiskers: the middle half of the values in the box, the median solid inside it, the range out to the caps. It is the one kind that says something no total can - a bar chart of averages cannot tell a tight category from one that runs from nothing to everything. Every row shares one scale, so the boxes are comparable down the page.
calendar lays a measure per day out as weeks - a column a week, a row a weekday, shaded by how much. It takes a date column, and text counts as one: select date(Timestamp) d, count(*) from … group by d is the query it is nearly always drawn from, and that d arrives as text. It is drawn as wide as the rows span rather than as wide as the terminal.
waterfall runs a signed measure up into a total: each step starts where the last finished, and the last row draws the total from zero. Drawn as rows rather than floating columns, because a column three cells wide has nowhere to write unrealised gain underneath. A green bar rises and a pink one falls, and the figure carries the sign. Its steps stay in the query's order however they are sorted - reorder them and the running total describes a history that did not happen.
dumbbell joins two measures per row - before against after, left against right - so the gap is what you read rather than the difference between two lengths. ● is where the row started and ○ where it ended, whichever way round they fall.
histogram cuts one numeric or date column into bins and counts them - how the values of one thing are spread, which the same numbers in a table never show. It is the one kind that asks a single question: its bars are how many rows fell in each bin, so there is no measure to name.
heatmap crosses two categories and shows the measure as colour. Twenty columns of squares fit where forty bars would not, and the hot corner is visible without reading a figure. Its columns are numbered and named beneath - a square is two cells wide and text cannot be rotated - with the colour scale on the last line.
multiline is line split into one line per category, on one shared pair of axes - which is the point of drawing them together. It caps the lines it will draw, and lower than the bar charts cap their series: a character cell carries one colour, so where two lines cross, one of them loses its colour for that cell.
line and scatter place every row as a point at its own coordinates. Nothing is summed, both axes are numbers or dates, and the y axis starts at the smallest value rather than at zero - a plot shows the shape of a change, and durations between 400ms and 420ms drawn from zero are a flat line.
The two axes have to be different columns, so a result with only one column that can go on either is charted some other way rather than plotted against itself. A date x with a single number to measure is the common case and still a plot - the rule is a pair, not two numbers.
Those two are drawn with braille dots, eight to a character cell, which is what makes a line a line rather than a staircase. If they come out as blanks or boxes your font has no braille: /set chart-dots blocks draws them with quadrant blocks instead - four dots to a cell, so steppier, but in every font. Bare /set shows a sample of each, which is the quickest way to tell what your font has.
Each question is asked with the likeliest answer first, so ⏎ takes it. Naming the columns skips them altogether - /chart bar ResourceType Requests - which is what makes a chart repeatable from ↑. The words are split on spaces and nothing else, so a column whose name has a space in it is picked from the questions rather than named here.
esc steps back one question at a time - off the columns to the kind, and only off the first one out of the command - so a chart can be redrawn a different way without starting again. A kind this result cannot take says so and returns you to the list rather than ending the command.
Either way it works over every row rather than the page on screen, so it fetches the whole result first, under a spinner that esc gives up on.
The line above the chart says what it is of, and owns up to anything it left out: categories beyond the fortieth are summed into other, and rows with nothing to measure or nowhere to place are counted rather than treated as zero.
Nine colours, which is as many as stay properly distinguishable - past that the bars are shaded as well as coloured, so a repeated colour never repeats its shading with it, and the key's swatch carries both. Nine categories or fewer are drawn solid throughout.
In the record, where there is no colour, each of those is drawn as a shade instead - █ ▓ ▒ ░ for a series, and light to dark for a heatmap's steps or a calendar's busier days. The key is shaded with them, so a chart written to a file still reads. Four shades against nine colours, so it is the coarser picture of the two, and the plots keep out of it: their marks say where a point is rather than fill anything.
A plot is drawn with blocks in the record whatever /set chart-dots says, so that it lines up with its own axis - see /help set. A line comes out solid rather than dotted, which reads better in a file anyway.
Charts are worth writing as /transcript html rather than Markdown: they keep their colours there, and a Markdown viewer's line spacing breaks a bar into stripes where a page does not.
What each column may be comes from the result's schema, so a numeric column whose first rows are all null is still offered. Text, date and boolean columns can be grouped by; numeric and date columns can be an x axis; only numeric ones can be measured.
⇥ offers the columns for whichever argument the caret is on, and only the ones that can play that part - so the same key that lists the kinds after /chart lists the categories after /chart bar and the measures after /chart bar ResourceType. Each row says which part it would play, since a list of column names cannot. A column an earlier argument took is not offered again, and once the kind's questions are all answered there is nothing more to offer. It needs one result to read, as /group does.
See also /rows · /stats · /save.
/group [columns]
browse the last result grouped, with a total per group
Also /groups.
Groups the rows /rows would page through and opens them as a tree you can walk: one line per group, ⏎ to open one, and the rows themselves at the bottom of it.
Every figure is worked out by the server over every row of the group, the way /stats's are - a group row comes back already summed, so opening a group of a million rows costs the same as opening a group of ten. Nothing is added up here, which is also why a total is right rather than nearly right: an average of averages is not an average.
It asks what to group by and what figures to put on each group row, likeliest answer first so ⏎⏎ takes a whole grouping. A second level nests inside the first, a third inside that, and there is no limit but the columns you have worth nesting.
Every group row carries # - how many rows are in the group - whether or not you ask for any other figure. What else a column can be asked depends on what it is: a number takes sum avg min max median and a count of its different values; a date takes min and max only, because everything else returns a number and a number in a date column reads as 1970.
A date grouped as it stands gives one group per distinct instant, so a date level is bucketed instead - by year, year-month, week or hour. The same date column can be used twice at different resolutions, which is how you get months inside years.
↑↓ lines · ←→ pans the columns and the tree column stays put · ⏎ opens or closes a group, and on one of the rows underneath opens that row in full · s orders every level by the leftmost column on screen · g asks the questions again · / filters with raw SQL
s orders by whichever column it is on, and what that means depends on the column. The tree, # and the figures are values a group row has, so those order the groups - biggest first to begin with, since that is what a grouped grid is usually opened to find. Every other column is a value only the rows have, so those order the rows inside each group and leave the groups where they are. A ▲ or ▼ on a heading says which column an order is on, and both can be set at once.
A filter or a new group order throws the whole tree away and asks again: every figure in it was summed over the rows the old filter left, so keeping an open branch would show you a total of a set you had stopped asking about. A new row order asks only for the rows that are actually on screen - it says nothing about the groups, so it leaves the branches you opened to get there alone.
One request fetches up to two hundred groups or rows for a group; past that the line says (+n more) and narrowing with / is how you reach them. A level with more groups than that is usually a level grouped by the wrong column.
Naming the columns skips the questions - /group Currency Type sum:MarketValue - which is what makes a grouping repeatable from ↑. A bare word is a level, fn:column is a figure, and column:year is a bucketed level; column:%Y-%m-%d takes any strftime format, which is how a bucket the questions do not offer is asked for. A word that names no column is reported rather than dropped.
⇥ offers them, so they need not be remembered or typed in full: the last result's columns at every word, and what is already on the line taken out of the list. A column comes first - the figures appear alongside the remaining columns once something is being grouped by, since a figure is a number carried on a group row and there are no group rows until then. sum: and the rest come as half a word, and ⇥ again finishes it with the columns that figure can be asked of; after a date column's colon it offers the buckets. It needs a result to read, and one result - a script that ran several queries has not been asked yet which of them is being grouped.
esc steps back one question at a time, and only the first one leaves.
See also /rows · /stats · /chart.
/lineage [what]
how the last result was arrived at, as a tree
Also /explain.
Tables, joins and filters as a tree, read downwards. all expands the filter expressions too.
/lineage <column> explains one column instead - what it is calculated from. A ƒ, Σ or ∂ on a heading marks a column that has one, and /rows → c → x opens it there./lineage [column] ai asks Candela for the same thing in words, once, into the transcript - or a in the /rows lineage screen.
/set lineage off stops queries asking the engine for any of it.
See also /rows · /ai · /set.
/stats
min/median/max/avg + sparkline per numeric column
The figures are exact over every row - asked of the server, not counted from the page on screen.
See also /rows.
/save
export the last result, or create a Saved Query
Export the rows to a local file or to FINBOURNE Drive - browse to the folder either way, and pick a file in it to overwrite one.
Or put the query into LUSID Saved Queries, where /run finds it again and /queries moves, renames or deletes it.
After a query set ran: its results as one file - a workbook for Excel, a database for SQLite, otherwise a zip of a file each - locally or into Drive, or each result as its own file as above. Drive's location may hold {executionId}, {date:yyyyMMdd} and {param:name}, filled in by the server. Or the set itself, into LUSID Workspaces or a .lumiq.json file - the same JSON either way, where it was loaded from offered first. The format, Drive location and overwrite answer are remembered for the next save.
See also /drive · /queries · /transcript.
/catalog [text]
browse providers and their fields
Type to filter, ⏎ drills into a provider's fields./set catalog tree draws them as folders instead: ↑↓ moves, →/⏎ opens one, ← steps out, and ⏎ on a provider pages its fields.
s hands the editor a select over every column of the provider, with a placeholder for each parameter it takes, and leaves - ↑ recalls it. Not offered for a provider that decides its columns from the query that calls it; that one's syntax is on the page instead.
d trees what depends on the provider.x explains a provider marked ⌥ - it registered its own lineage.
For a provider that is a view: v shows its definition, e hands the query that last wrote it to the editor, to change and re-run, and u trees what it is built out of.
See also glyphs · /lineage · /set.
/history
search and browse query history under a histogram
Search the last hour, day, week or month, or an exact range - esc steps back a question and then out again.
In QA it asks which Environment first, and can read any other environment's query logs - the same choice /diagnose offers, and d on a run diagnoses it in the environment it came from. Everywhere else there is only this domain, so the question is not asked.
Failed only keeps just the runs that errored. It costs a window of the error log however few rows come back, so a wide window on a busy domain takes a while - the feedback block shows it working and ^C stops it. Answering yes also asks Error contains, to narrow the failures by their error message - blank keeps every error.
Show Extra widens what the search can see. For those with special entitlements that means everyone's queries; for most users it only adds the Internal: runs - a session's own searches, the coordinator's, and a view's. That half of it works for another environment too, which has no ShowAll to ask for.
Then browse the runs under their histogram: ↑↓ + ⏎ for the full detail of one · / filters on the SQL · d swaps SQL for the completion details · h hides the histogram. Its columns are split by status in the Status column's colours, failures at the base.
In a detail, f fetches the server's feedback log for that run, c copies its query to the clipboard as it ran, and t keeps it in the transcript.
The runs arrive a page at a time as you scroll, up to /set history-cap of them - which is also the query's own limit, so the cap is paid for once at Athena. Filtering loads the rest first, so a count is never of part of the search.
It runs as an ordinary query over the three query logs (HcQueryStart, HcQuery, HcQueryError), so it reports the usual feedback and ^C cancels it server-side. Your answers are pushed down to Athena as filters, not applied to rows already fetched.
Closing always leaves the search and its table in the transcript.
See also /recent · /feedback · /api-history · /diagnose · /copy.
/api-history
search and browse the API request log under a histogram
Also /apihistory.
Every API call made against the domain, not just the queries you ran - who called what, how long it took, and what it answered.
Search the last quarter of an hour, hour, day or week, or an exact range, and narrow to one application - esc steps back a question and then out again.
In QA it asks which Environment first, and can read any other environment's request log. The environments on offer are the ones registered for this log, which are not quite the same set /history can reach.
The log records every request twice - once as it arrives and once as it finishes - and the arrival carries no status code and no duration. Include Started asks for those rows too; leaving it off halves the search.
Errors only keeps just the requests that errored or failed, and then asks Error contains - text the error's or failure's message or details must contain, blank for any. Include Started is not asked alongside it: an arrival is never an error.
Show Extra widens what the search can see. For those with special entitlements that means everyone's requests; for most users it only adds some less interesting ones. Not asked of another environment, whose view has no such parameter and hands back everything either way.
Then browse the requests under their histogram: ↑↓ + ⏎ for the full detail of one · / filters on the url, endpoint, user or error text · d cycles the wide column through the url, the controller and method, the error and the failure · h hides the histogram. Its columns are split by event type in the list's colours, failures at the base.
In a detail, c copies the request id and t keeps the request in the transcript.
d on a detail diagnoses the run the request started - the same report /diagnose gives, with no id to paste and no range to choose, and esc brings you back to the request you pressed it from. Offered on very few requests, because very few of them start a query: honeycomb's Sql, SqlBackground.StartQuery and MultiQueryBackground.StartQueries. On anything else it says why not rather than doing nothing - the requests that fetch a result or a progress report carry a request id too, and it names no run. Where the search was of another environment, that environment's query logs have to be readable from here as well, which is not true of every environment this log covers.
The requests arrive a page at a time as you scroll, up to /set history-cap of them - which is also the query's own limit, so the cap is paid for once at Athena. Filtering loads the rest first, so a count is never of part of the search.
It runs as an ordinary query against Lusid.Logs.AppRequest.Athena, so it reports the usual feedback and ^C cancels it server-side.
Closing always leaves the search and its table in the transcript.
See also /history · /access-history · /feedback · /diagnose.
/access-history
search and browse the entitlement log under a histogram
Also /accesshistory.
Every entitlement decision made for the domain - who reached for what, which entitlement was asked about, what decided it, and whether it was granted or denied.
Search the last quarter of an hour, hour, day or week, or an exact range, and narrow to one application - esc steps back a question and then out again.
In QA it asks which Environment first, and can read any other environment's entitlement log.
Show Extra widens what the search can see. For those with special entitlements that means everyone's checks; for most users it only adds some less interesting ones. Not asked of another environment, whose view has no such parameter and hands back everything either way.
Then browse the checks under their histogram: ↑↓ + ⏎ for the full detail of one · / filters on the resource, action, entitlement or user · d cycles the wide column through the resource, the entitlement, what was authoritative and the request id · h hides the histogram. Its columns are split by result in the list's colours, denials at the base.
In a detail, c copies the request id and t keeps the check in the transcript.
One API call makes several checks, and they all carry its request id - so c on a denial and / on that id in /api-history is how you get from 'access denied' to the call that provoked it.
It runs as an ordinary query against Lusid.Logs.Metrics.Entitlement.Athena, so it reports the usual feedback, ^C cancels it server-side, and /set history-cap is its limit.
Closing always leaves the search and its table in the transcript.
See also /api-history · /history.
/diagnose [id]
all the platform recorded about one query run
Give it the execution id of a run - or last for the one this session just ran - and it gathers what the platform recorded about it into one report. d on a /history run does the same without asking anything at all, since that row already knows the id and when the run was; esc brings you back to it.
A request id works too - /diagnose 2025091514-f9626faa80ca48eba11197446fc7ad8b - which is the id an error page or an API response carries, and usually the only one the person asking you was ever given. It names the run only indirectly, so the first thing it does is look up what that request started; it needs no range, because the first ten characters of the id are the UTC hour the request arrived. Where one request started several queries - which is what /api/MultiQueryBackground does - it shows you the runs it found and asks which. d on an /api-history detail does all of this for the request under the cursor, where that request is one of the few that starts a query.
A run is rarely one execution. A query that reads a view runs as several, and the id you were handed is nearly always the parent - so the first thing it does is find the whole family, which it can do from any member of it. Each execution comes back with its own SQL, how long it took, how many rows it returned and its error if it had one; a view is listed under the query that ran it, and named.
Cause is the part worth reading first. A query that failed once routinely shows half a dozen unhappy providers, and only one of them is the reason: when a call throws, the coordinator abandons every call still running beside it. The report names the one that threw - down inside whichever view it happened in, rather than the view the top of the run can only point at - and lists the abandoned ones apart from it as what they are.
Then every provider call the run made, with its timings and row count, and an RTrace link for the LUSID ones. Then the run's feedback log, which the server can rebuild for 31 days. Finally what the pods themselves said, interleaved with QC / WebApi / Provider against each line - and where the run failed, everything those same pods said for the minute either side of it with no text filter at all, because the line explaining a failure very often does not carry the execution id.
It opens as a tree you walk: ↑↓ + ⏎ for everything about one execution - its SQL, its error, the calls it made and the feedback lines it put its name to · p every provider call · l the pod logs, where 1-9 show and hide one component at a time, / narrows to lines containing some text and o hides the pods and their links from above them - whichever you do, the moment on screen stays on screen · f the feedback log · c copies the highlights for a message · s saves the whole thing as a Markdown file to attach. Closing leaves the report in the transcript either way.
h finds the other runs of the execution under the cursor and browses them as /history does. A run matches when its SQL is within a set number of edits of this one's at both ends - the first and last 300 characters - its length within a fifth of it, and its query name the same where both have one. It asks for the range (30 days by default), the edits allowed (10) and whether to keep to the same client. Above the list, side by side: when the runs started, how long each took and how many rows it returned. p steps the last two through the providers the runs called, slowest first. r on a run recalls it into the editor history rather than running it.
Once the run is found, a check that fails - a telemetry system that is down, say - does not stop the diagnosis. Its section says it could not be read, with the error in a line, and so do the top of the report and the status line under the tree. e shows each error whole, and the saved file keeps them.
A saved diagnosis can be opened, and - where claude is on your PATH - handed to it, which is what the file is really for: the report says what happened, not what went wrong, and reading it against the dve and lusid-ibor repositories is the part an agent does well. The prompt it would be sent is shown while you are asked, since claude starts on it at once and never offers to; e lets you type straight over it - ⏎ and ^J exactly as in the SQL editor, /set enter and all - and brings you back to the question with what you wrote, so you can read it over before sending or change it again. A prompt you changed can be kept as the one every later diagnosis starts from. ⏎ and esc both answer no.
It opens in a tab of its own - a new iTerm2 tab, or a new Terminal window - so the diagnosis you are reading stays where it is, and the tab starts in the directory lumi was started in so claude can actually reach the repositories. The panel says which it will be before you answer. In a terminal that cannot be asked for a tab, claude takes this one until you quit it: there the diagnosis closes on its way there, and from /history it opens once you leave the browser.
/diagnose ce80d357-… 24h asks nothing at all. 1h, 2h, 24h and 7d are offered in the list and two hours is the default, but any offset the date fields take works as an argument - 3d, -6h, 2w. The window is not a filter - it picks the partitions the logs are read from - so a run it does not find is a window to widen rather than a run that is gone. Once the run is found, everything after that is read over the run's own span with five minutes either side. A request id brings its own window and a window cannot be given with one: the hour it names, and an hour either side of that.
In QA, where views over other environments' telemetry are registered, it asks which environment first - or name one anywhere on the command line, /diagnose ce80d357-… FBN_QA_AZ 7d, and it asks nothing. The query and provider logs read across; the feedback log does not, because that one is this domain's own WebApi's.
Outside a session, lumi diagnose ce80d357-… 7d asks nothing and writes the whole record to a Markdown file - seven days back and the signed-in environment unless told otherwise, and a word ending .md names the file.
It is all queries against Sys.Logs.*, named Internal:LumiCode:Diagnose:* so they stay out of /history - and entitled accordingly, which in practice means FINBOURNE.
See also /history · /feedback · /api-history.
/queries
browse Saved Queries: run, edit, move, delete
Pick a workspace, then a query - both filter as you type.
On one: ▶ run it · ✎ load it into the editor · ⇄ move or rename it (a workspace, a group and a name - change any or all three) · ✗ delete it after confirming.
The list reopens after a move or a delete, so a run of tidying is one command. Only Saved Queries are ever touched - a name already held by a dashboard is refused rather than written over.
See also /run · /save.
/drive
browse Drive: download, move, copy, delete
On a file: ⤓ download it (browse to the local folder, name it, overwrite confirmed) · ⤓ download and open it with whatever your desktop opens that extension with · ✎ move or rename it (the new folder, then the new name - either or both) · ⧉ copy it · ✗ delete it after confirming.
The picker reopens after each one, so a run of tidying is one command. A file still being virus-scanned is offered only the actions that do not read it, and ^R (or F5, where your OS lets it through) re-reads the folder from Drive.
See also /save · /queries.
/schedules [job]
scheduled query jobs and when they ran (read-only)
Defaults to the Luminesce Query Runner (default/QueryRunner) - the job every schedule /recent makes points at. /schedules all lists every schedule on the domain, and /schedules <scope>/<code> a named job's.
Pick a schedule to see its runs, newest first, a failure showing why on its row. Then a run for the whole record: ⊞ opens the Scheduler's log in your editor (/set editor) · ⤓ saves it to a file · ⧉ copies the run id.
Read-only - nothing here pauses, edits or deletes a schedule.
See also /recent · /set.
/cfg
browse and edit the Configuration Store
Pick a set - shared and personal are in one list, and typing filters it.
On the set: + add an item · ✎ change its description · ⇄ move or rename it (a new type, scope or code - written and then the old one deleted, since the API cannot change an address) · ✗ delete it and its items.
On an item: ◉ reveal a secret (v) · ⧉ copy the value to the clipboard (c) · ✎ change its value (^E opens your editor (/set editor), for a certificate or anything multiline) or its description · ⊘ block reveal from then on · ✗ delete it.
A revealed secret is drawn only in the panel and never in the output, so it is gone from the screen when the panel closes.
See also /set · /certificates.
/select
select the transcript by keyboard and copy it
↑↓ move the lit line · ⇧↑↓ or space grow the block · pgup/pgdn page · home/end the ends of the transcript⏎ copies what is lit · esc leaves without copying
Whole lines only - drag with the mouse for part of one (/help selection).
It is also the only way to scroll the transcript from the keyboard: every other key press means "back to the live tail", which is what makes typing at the prompt work.
See also /copy · selection · keys.
/clear [what]
clear the output area, or the record with it
Also /cls.
The screen and the scroll buffer behind it, not the record - /transcript still has everything that happened./clear transcript discards the record too, so what /transcript writes starts again from here. It is the one part that cannot be got back, which is why it takes a word of its own.
Neither touches the last result: /rows, /chart and /save still have the rows of the query you ran.
See also /transcript.
/transcript [file]
write the session as Markdown, or as an HTML page
The queries you ran and the tables they returned, in order - including the ones /clear took off the screen.
Not everything the screen showed: /help is drawn and not recorded, and what else is kept beside the queries is /set transcript's to say./help full is the one exception, and puts every help page in the record on purpose - a whole manual in Markdown, for documenting LumiCode elsewhere.
Naming a file writes there; without one, lumi picks a name and says where it went.
/transcript label Some Label puts a heading in the record instead of writing it, above everything you do from there on - so a session of one query after another comes out as sections saying what each of them was for. /transcript label on its own asks for the text.
A name already in the record is refused: two identical headings in one document are two places to look for one thing. /clear transcript starts the record, and its labels, again.
The label names this terminal's tab as well - ⬢ lumi - Some Label - so which of several sessions is which can be read without opening them. /set title off leaves the tab alone.
Once there is more than one part to the record, writing it asks which of them to write - the part just finished is marked, and the row above the list takes the lot. Whatever you mark comes out in the order the session recorded it. An unlabelled record is one part, so nothing is asked.
/transcript html writes a page instead, and it is the form to reach for when there are charts in the record: a heatmap is its colours, and Markdown has none - so there the colours are spelled as shades, and here they are the colours you saw. Tables come out as tables and a clickable cell stays clickable.
The colour is not only the charts': a feedback log says which lines are errors with it, a diagnosis which step was slow, and the queries are highlighted as the editor highlights them. All of that is in the page and none of it in the Markdown, which has nowhere to put it.
A chart in Markdown has one more thing against it: a picture drawn on a character grid holds together only while a row is exactly one glyph tall, and a fenced block takes whatever line spacing the viewer likes - above that, every bar comes apart into stripes. No glyph survives it and nothing in a .md file can set the spacing, so a chart written as Markdown is at the mercy of whatever opens it. The page sets it, and lumi says so when you write one with charts in it.
A file named .html is written as one without the word, and /transcript md <file> is how you insist on Markdown. One file either way, with its styling inside it - nothing to keep beside it.
Everything in a page is escaped on the way in, your data and an agent's answer alike: a record is read in a browser, and a cell of a result has no business being read as anything but text.
See also /clear · /save.
/usage [what]
how much LumiCode has been used, this session and in total
Commands, queries, charts and Candela, counted twice: since this session opened, and since the totals were last started. The busiest commands and chart kinds are named underneath.
/usage activity draws the days you have used LumiCode as a calendar - a column a week, a row a weekday, shaded by how much was done - with your sessions, active days and streaks beneath it.
/usage reset starts the totals again from today, after asking. The calendar and the streaks are not cleared with them: those are a record of when you were here, not a tally.
It is all kept on this machine, in usage.json beside the query history - counts and dates only, never a query, a provider or a domain. Nothing is sent anywhere.
The Candela token counts are what the agent itself reported for each turn, and it does not always report any - which is why the tokens are only shown once some have arrived.
See also /stats · /history · /ai.
/set [option]
change a setting; bare /set shows them all with values
Every setting persists across sessions, and a bare /set prints what each one is now.
table grid, rule, minimal or markdown - how result tables are drawncells multiline or flatten - what a cell with line breaks in it doesbanner full (4 rows), compact (1 row) or off - the pinned header, and the trail of where you arecatalog flat or tree - how /catalog lists providerschart-dots braille or blocks - what a /chart line or scatter draws its dots withmouse on or off - whether the transcript is lumi's to scroll or your terminal'senter run or newline - what ⏎ does, swapping it with ⇧⏎/^Jworkspace fit or fixed - whether the editor grows with the query or keeps 15 rowslineage on or off - whether queries ask the engine for lineageai-tools off, collapsed or full - what a /ai turn's tools leave behindtranscript what the record keeps besides queries: a bare /set transcript opens the picker (space toggles, a all, n none), and /set transcript feedback off switches one without ithistory-cap a number of rows - how many the three history searches will bring back (100 to 1,000,000, default 50,000)update-check on or off - whether lumi looks for a newer LumiCodetitle on or off - whether lumi names this terminal's tab after the sessioneditor a command, e.g. code - used by ^X, ^E and /schedules' logsqueryset what the next query set runs with - how many at once, how long each may take, how long the results are kept, its name. Carried from one set to the next, and all but the name kept for the next session
A /command always runs on ⏎, whichever way enter is set.workspace fit keeps the prompt on the bottom rows and grows it with the query, up to three fifths of the window, with completions opening above it. fixed gives it 15 rows with completions below. Fit needs /set mouse on; with it off the prompt is fixed.update-check asks once a day, in an interactive session only, and compares release notes rather than version numbers - the pipeline bumps the version on every build, so two versions far apart are usually the same LumiCode. It costs one small request; only a version genuinely newer than yours is downloaded to read its notes, and a newer one whose notes match yours is silent. off means nothing reaches out on your behalf, and /binaries still downloads whatever you ask it for.
title names the tab ⬢ lumi, and ⬢ lumi - <label> once /transcript label has said what this part of the session is for. The glyph says what the session is doing, which is worth having in a tab you are not looking at: ◐ ◑ turning a second at a time while anything runs - a query, a catalog load, a Drive listing, a /diagnose, a Candela turn - and then ✔ or ✗ for what a query came to.
That mark stands until the next thing you do and no longer: the command after it puts the tab back to ⬢. Work that has no outcome of its own to report never claims one - the tab simply stops turning.
The name in force when lumi started is put back on the way out, in terminals that keep a title stack (iTerm2, kitty, WezTerm, Ghostty); elsewhere the tab keeps the last name lumi gave it until the shell titles its own prompt again. Inside tmux it names the pane, and only reaches the real tab where tmux is set to pass titles through.
chart-dots is a font question, not a taste one. Braille packs eight dots into a character cell against the blocks' four, so a line drawn with it is a line rather than a staircase - but a font without braille draws every one of them as a blank or a box, and blocks have been in every terminal font for decades. A bare /set draws a sample of each, so which to use is a question you can answer by looking.
It is a question about your terminal alone: the record is drawn with blocks either way. The fonts that carry a chart's axis often have no braille at all, so a file read elsewhere falls back to a wider face for it - and a plot whose glyphs are wider than its own axis does not line up with it.
history-cap bounds memory, not the search: the browsers hold their rows so that filtering and the detail view are instant, so it is what decides whether a search costs tens of megabytes or thousands of them. A million rows of the API request log is gigabytes.
The editor falls back to $VISUAL, then $EDITOR, then VS Code if it can be found; a bare /set editor says which it will use and why, and none clears it. A GUI editor is given --wait where it must be waited for.
See also selection · keys.
/certificates
list and download client certificates
Also /certs.
The certificates that let a provider host outside FINBOURNE's cloud authenticate to this domain. Each is listed with its validity and whether it is valid, expired or revoked.
Downloading one browses to a folder and then names the file, the same way /recent's file save does - an existing file is confirmed before it is replaced. The private key is written 0600 where the platform has file modes, and the line that reports it says so.
mint (dry run) asks the server what creating a certificate would do, and changes nothing.
See also /binaries.
/whats-new [all]
what a newer LumiCode would bring, and take it if you like
Also /whatsnew · /news.
LumiCode compares release notes, not version numbers. The pipeline bumps the version on every build, so two versions far apart are usually the same LumiCode - what differs is the notes, and a newer build whose notes match yours brings you nothing.
So the banner only says 3 new when there are actually three things to read. This lists them, newest first, under whatever the notes group them by - and only the groups that hold something new to you. Then it offers to update.
/whats-new all prints the notes whole instead - every day of them, sections and all, and nothing offered. That is the one for a first run: what you have just taken is the newest there is, so there is nothing to compare it against and nothing the other form can say. /help tells you how it works; this tells you what is in it.
It is checked once a day in the background, in interactive sessions only - never in lumi run or a Scheduler job. Only a version genuinely newer than yours is downloaded, and only to read its notes. /set update-check off stops it entirely.
Typing this asks now when nothing has been established yet; otherwise it shows what was found and when.
Building LumiCode? A local build run with --debug rehearses the whole thing without a server: the notes you just compiled stand in for a newer LumiCode's, and the ones from the lumi installed on your machine stand in for your own - so editing release-notes.md and rebuilding is the test loop. It says so on the way in, the pretend version is 9.9.9-rehearsal, and where nothing installed can be found every note reads as new. LUMI_REHEARSAL_NOTES points the 'yours' side at any file instead.
See also /update · /binaries · /set.
/update
update LumiCode itself to the latest published version
Downloads the newest LumiCode and runs dotnet tool update from it - install refuses to overwrite a tool that is already there, which is exactly this situation.
Restart lumi afterwards: this session goes on running the version it started with.
On Windows the running lumi's own files are held open, so the update cannot happen from inside it. There the package is downloaded and kept, and the one command to run after leaving is printed.
/whats-new first if you want to know what you are taking.
See also /whats-new · /binaries.
/binaries
download a Luminesce binary, and optionally install it
Also /binary.
The CLI, provider hosts and drivers. Pick which, then the version (latest by default), then browse to the folder to put it in - the same picker /run uses, in folder mode: only folders are listed, and ✔ use this folder takes the one you are in. The server names the file. A .nupkg can then be installed with dotnet tool install from it.
Each binary needs its own licence and entitlements: being listed is not the same as being entitled.
LumiCode is in the list, and its versions are marked (yours) and (newer) against the one you are running - though /update is the shorter way to take a newer one.
See also /certificates · /whats-new · /update.
/help [topic]
this list, or one command or topic in full
Also /?.
/help lists everything, one line each. /help <name> is the page for one of them, and the name can be shortened as far as it stays unambiguous - /help hist finds /history.
/help full prints every page at once and puts the whole of it in the record as Markdown, so /transcript writes the lot to a file - which is how you start an article about LumiCode rather than a page of it.
⇥ on a buffer that starts with a slash offers the commands, each with its page in the pane beside the list - and after /help it offers these names.
/exit
leave LumiCode
Also /quit · /q.
^C at an empty prompt does the same. A query still running server-side is left running - /history finds it again in the next session.
See also /history.
keys
running, editing and recall keys
Running⏎ runs the buffer · ⇧⏎ or ^J inserts a newline
Most macOS terminals send ⇧⏎ identically to ⏎ - either use ^J, or map ⇧⏎ to send \n in your terminal's key settings. /set enter newline swaps the pair over.
A line containing only \ splits the buffer into queries run in parallel.
Editing⇥ or ^space opens completions - ⇥/⏎ accepts, esc dismisses. On macOS ^space may be taken by input-source switching.
Accepting a word leaves the space after it, so ⇥ ⇥ walks a line a word at a time. A half word like sum: keeps the caret against what it finishes.pgup/pgdn scroll a completion item's documentation when it overflows.
With no completions open they move a page through a tall query, or to its first or last row when it fits - on a Mac, fn ↑ and fn ↓.
On a buffer that starts with a slash the completions are the session's own commands rather than SQL.^P pretty-prints the buffer · ↑/↓ recall recent queries · ^X edits the buffer in your editor (/set editor)^R runs only what is selected, leaving the rest of the buffer on ↑ - for working through a script a piece at a time. With nothing selected it does nothing, since there is nothing to run. ⏎ always runs the whole buffer, selection or not.esc clears the line, or closes the completion popup if one is open.
Moving about⌥←/⌥→ move a word at a time, ^←/^→ likewise · add ⇧ to any of them to select as you go.home/end go to the ends of the line, pgup/pgdn a page through the buffer.click puts the caret where you clicked - as long as lumi is holding the wheel, since a terminal that is not reporting the mouse cannot say where you clicked. /set mouse off gives that up.
A press above the editor selects the transcript instead - drag, and letting go copies (/help selection)./select does the same without the mouse, and is the only way to scroll the transcript from the keyboard.
Selecting and copying⇧ with any movement key selects as you go · typing or delete replaces what is selected.^R runs what is selected and nothing else.^C copies the selection. With nothing selected it clears the line instead, and a second one leaves./copy copies the last query you ran.^V pastes, and so does your terminal's own paste - that one simply types the text in.
macOS: ⌘C never reaches lumi - the terminal keeps it for its own copy. That is why it works on the transcript above, where the selection belongs to the terminal (⌥-drag), and not in the editor, where it belongs to lumi. See /help selection.^X is the external editor here rather than cut, so cutting is select-then-^C-then-type.
See also running · selection · /set.
running
what the keys do while a query is running
esc detaches - the query keeps running server-side, and /history has its result when it finishes.^C cancels it outright.
The block fills the pinned band, showing as much of the feedback as the rows allow, newest at the bottom - and ▲ 12 more in its header when there is more than that. /feedback prints the whole log afterwards, however much scrolled past.f appears only when several queries are running, and switches how the band is divided: a share each, so a quiet query stays visible beside a noisy one, or pooled across all of them to read one log in depth.
See also /feedback · /history.
sets
named queries run together, each reading those above
A --- @Name line starts a query and names it, and a query reads the result of one above it as @Name. A buffer with any such line is run as one set:
--- @Ten (internal)
select [Int], Str from Testing10
--- @Evens
select * from @Ten where [Int] % 2 = 0
(internal) marks one that only feeds the others: it runs, but has no result of its own to show, save or browse. --- @Name = shared/Workspace/items/group/name uses a Saved Query instead, with nothing written under it.
Names are letters, digits and _, at most 31 characters (an Excel sheet's limit), and at most 25 queries.
⇥ offers the queries above as @Name wherever a table may go, and each query is checked by itself - so reading one above is not an error, and anything wrong with the set itself is underlined on its line.
The first run asks how many run at once (one at a time unless changed), how long each may take, how long the results are kept and the set's name; /set queryset changes them later, and they carry over to the next set. Scalar parameters are asked for once for them all, offering the values last used.
A query that fails stops those that read it, which are ⤼ skipped; the rest still run.
Each result is reported under its name, and /rows, /stats, /chart, /group and /lineage take that name first - /rows Evens, /chart Evens bar - or ask which when not given. ⇥ offers the names there, and after one the columns of that result. A set runs without lineage.
/save keeps the set itself, in LUSID Workspaces or a .lumiq.json file, and /run opens it again. It saves the results as one file too - see /help save./feedback starts with which query reads which, and /results lists a set's results once, to load again.
See also keys · running · /rows · /save · /run · /results · /feedback.
selection
selecting text with the mouse, and who is selecting it
Also mouse · selecting.
Click and drag across the transcript. Drag past the top or the bottom and it keeps scrolling; let go and what you selected is put on the clipboard. No modifier to hold, and it reaches as far back as the transcript goes rather than stopping at the rows you can see.
The highlight stays until your next key press, so you can see what went.
Your terminal's own selection is still available with a bypass modifier - ⌥ in iTerm2 and Terminal.app · ⇧ in kitty, WezTerm, Ghostty and xterm - for the areas lumi does not offer: the banner, the prompt, and a full-screen view like /rows. That one reaches only what is on screen.
All of that is /set mouse on, the default. With /set mouse off the transcript is ordinary output and your terminal's: it scrolls back, a drag selects and auto-scrolls, and your terminal's find works on it - but the banner and the prompt scroll away with everything else.
Bigger than a few lines? Ask for it instead: /copy result, /copy transcript, /copy. They come out tidier than a drag - no panel borders, no line wrapped where the window ended.
Three selections, three copy keystranscript - lumi's, by dragging · letting go copieseditor - lumi's, ⇧ with the arrows · ^C copiesterminal's - behind the bypass modifier · ⌘C on macOS, ^⇧C elsewhere
See also keys · /copy · /set.
glyphs
what the markers in a list or a heading mean
Also markers · symbols.
In the catalog⧉ a view · ⬚ its shape depends on how it is used⌥ it registered its own lineage, so x can explain it↗ a documentation link, clickable - one per link
On a resultƒ calculated · Σ aggregated · ∂ derived - all three mean /lineage <column> has something to say↗ on a value marks a clickable link
On an action▶ run · ✎ edit · ⇄ move or rename · ⧉ copy · ⤓ download✗ delete · + add · ◉ reveal · ⊘ block reveal · ⊞ open in your editor
See also /catalog · /rows.