Dosirak is a desktop database. A project is one folder on your computer, named by you and put where you want it, and it stays there: no account, no sync, nothing to export. On macOS, press Cmd wherever this guide writes Ctrl.
Get a database going
- New Project (Ctrl+Shift+N). The system save dialog asks for a name and a folder. Dosirak writes a folder with a
.dosirakextension there. If a folder of that name is already there, the create fails. Pick another name or another folder. - Create a table. A project with no tables opens on the Create a table form. Type the table name and press Create table. Later tables come from + New table at the foot of the sidebar in Build.
- Add the fields. Build (Ctrl+B) lists the table's fields. Press + in the page head for each new field, then set its Name and Type in the panel on the right.
- Open the Form layout. Switch to Design (Ctrl+D) and open the compartment in the sidebar. A new table arrives with three layouts: a list named All and the table name in lower case, Form, and Split.
- Put the fields on the form. A new field waits off the form until you place it. Click the region on the canvas, then switch each field on under AVAILABLE in the Region settings panel.
- New record (Ctrl+N) in Run (Ctrl+R). The new record shows on the form. Type into a field. The value saves when you leave the field.
The window
A project opens in one window. Its name sits at the top left, and beside it the mode switch holds Build, Design and Run. The switch changes what you edit. The open project, the selected compartment and the layout on screen all stay where they were.
| Mode | Key | What it changes |
|---|---|---|
| Build | Ctrl+B | The table. Its fields and their types, and under Table settings its name, icon, color and relationships. |
| Design | Ctrl+D | The layouts the table owns. List, Grid, Form, Split, Print form and Print list. |
| Run | Ctrl+R | Records. Read them, type into them, search, sort, print and export. |
The three modes also sit in the View menu, with the same keys.
The compartments sidebar
The sidebar on the left is headed COMPARTMENTS. A compartment is a table. What the list holds depends on the mode.
- Build lists the compartments alone, with a grip to drag them into order and + New table at the foot.
- Design turns each compartment into a folder. Click a row to open it and the table's layouts appear inside, draggable into order, with + New view below them and a menu of the six kinds.
- Run shows the same folders and layouts, with nothing to add or reorder.
Under the compartments, the AGENT group holds Approvals and Server in every mode. Approvals carries a count when calls are waiting for you.
- The eyebrow folds the sidebar. Click the COMPARTMENTS header and the sidebar collapses to a narrow strip. Click the strip to bring it back. The content takes the freed column rather than being covered.
- The tree remembers its shape. Design and Run draw the same folders from the same open list, so moving between them does not reopen or shut anything.
- F2 renames the selected row. It renames a compartment in Build and a layout in Design. Run has no rename.
The inspector
Build and Design put a settings panel on the right of the canvas. In Build the panel follows whichever field is selected in the list, and the selected field's name is its heading. In Design it is a rail that opens on whatever you click on the canvas, and its title names the kind it edits: Layout settings, Region settings, Field settings, Band settings, or Page settings on a print layout. Close settings shuts the rail, and so does Esc.
The record bar
Run carries a record bar across the foot of the window. Left to right: a pie showing the found set's share of the table with the found count beside it, an arrow to the previous record, a slider running the whole found set end to end, an arrow to the next record, and the record number.
- Drag the slider to go a long way. A bubble names the record under the thumb as it passes. The record loads when you let go.
- The number is a field. Type a record number and press Enter to jump there.
- The pie is Show All Records. While a search is on, the pie becomes a button that gives every record back. Ctrl+J does the same.
- The slider takes the keyboard. Arrow keys step one record, Page Up and Page Down move a hundredth of the set, and Home and End go to the ends.
Projects
A project is one folder with a .dosirak extension, in the place you chose for it. Everything the database holds is inside that folder.
| Item | What it holds |
|---|---|
project.toml | The project name and the bundle format number. |
schema/ | One file per table: its fields, its regions and its relationships. |
views/ | One folder per table, holding one file per layout. |
workflows/ | Made with the bundle and still empty. |
files/ | Made with the bundle and still empty. |
data.sqlite | The records. |
Dosirak also makes an assets folder the first time an image goes into the project, from a print layout or an image field, and copies the picture into it.
Back it up
Copy the folder. There is no account and no server copy, so the folder is the backup. Close the project before you copy it, so nothing writes to the database part way through.
Open and close
Every item is in the File menu.
| Item | Key | What it does |
|---|---|---|
| New Project… | Ctrl+Shift+N | Asks for a name and a folder in the system save dialog, then creates the bundle. |
| Open Project… | Ctrl+O | The system folder dialog. Select the .dosirak folder itself. |
| Open Recent | A submenu of the projects you opened before, with Clear Recent Projects at the bottom. Disabled while the list is empty. | |
| Close Project | Ctrl+W | Puts the window back to its recent projects list. The window stays open. |
| Reveal Project in File Manager | Ctrl+Shift+R | Shows the open project's folder in the system file manager. |
Close Project and Reveal Project in File Manager are off until a project is open.
- Dosirak reopens a project where you left it. The mode, the compartment, the layout and the record you were on come back. That place is kept on this machine, not in the project. A copy opened on another machine has no place to return to.
- The window with no project open is the recent list. It carries Open project and New project, a row per recent project with its full path, a remove button on each row, and Clear list.
- Open the folder, not the app. Open a
.dosirakfolder from the file manager, or drop it on the window, and Dosirak loads it. A second launch hands the path to the window already running. - The name is the folder name. The name at the top left and the name in the window title both come from the folder, minus the extension. Rename the folder and the project is renamed.
Tables
Tables are made in Build (Ctrl+B). The sidebar lists them under COMPARTMENTS. A table is created and reordered from that list.
- Press + New table at the foot of the sidebar. The Create a table form opens.
- Type the name. This is the name people see in the sidebar.
- Press Create table. The table opens in Build with its field list on the left.
A new table arrives with two fields, Created on and Updated on, both of type Timestamp and both off the form. It also arrives with three views: a list named All plus the table name in lower case, Form, and Split. The form starts with one region, named after the singular of the table name.
Rename, reorder, delete
Open Table settings from the gear in the page head. The Name row renames the table. The new name is kept when you leave the field or press Enter. A rename does not change the table's id or the schema file that holds it, so nothing that points at the table breaks.
To reorder the list, drag a table by the grip that appears on its row. The grip is there in Build only. Esc during a drag puts the old order back.
Delete table sits at the foot of Table settings. The confirmation is a system dialog: it names the table, says that this removes the table, its fields and its relationships, and that the action cannot be undone. Under that it lists every place elsewhere in the project that named the table, as the table name and then the field, view or calculation, so you can see what the delete breaks before you agree to it.
What a delete takes with it
The records go with it. The table's rows are dropped from data.sqlite in the same commit that removes its schema file, so there is no half-deleted table left to clean up afterwards, and the records are gone for good.
Every relationship that named the table as the parent goes too, and with it the relation field that relationship had put on the child table. The child's own records stay. Its views, lookups, portal columns and sort rules that read through the deleted table are pruned by the delete.
Table settings
| Setting | What it does |
|---|---|
| Name | The name in the sidebar and in the page head. |
| Comment | A note on the table. Two lines, free text. |
| Icon | A glyph beside the name. The picker has a search box. Picking the glyph the table already has clears it back to Table. |
| Color | Eight swatches, plus No color. The choice tints the glyph. |
| RELATIONSHIPS | Every relationship this table takes part in, and + Add relationship. |
| MCP | Read, Create, Edit and Delete for agents, each set to Allow, Ask or Deny. |
- Every setting in this panel saves as you make it, so the drawer has no Save button.
- Created on and Updated on cannot be renamed, retyped or deleted. The kernel writes them.
- Right-click a table row in Build for Settings and Delete. Delete runs the same confirmation as the button in Table settings.
Fields
Build lists a table's fields on the left and opens Field settings on the right. The + in the page head adds a field. It arrives at the foot of the list named Field and its number, typed Text, with the name selected so you can type over it. Every change in the panel saves as you make it.
The types
Text. One line. Names, codes, a reference number that is not arithmetic, a short label.
Long text. Several lines. Notes, a description, an address, anything that wants a box rather than a line.
Number. Anything you count, price, measure or total. A number field is the only one that can be a serial.
Date. A calendar day, with no time of day on it.
Date & time. A moment. The value carries a zone when it is written and is kept as UTC, so the same moment reads correctly on a machine set to another zone.
Choice. A fixed list of options, written once on the field instead of typed again on every record. One option per record, or several when Allow multiple is on.
Image. One picture per record, chosen from disk. The file is copied into the project's assets folder, so the picture travels with the bundle. PNG, JPEG, GIF, WebP, SVG and BMP are accepted.
Switch. Yes or no. Whether an invoice is paid, whether a record is archived.
Aggregate. A number read from the other side of a relationship: how many related records there are, or the sum or average of one of their number fields. See Calculations.
Formula. A value worked out from the record's own fields rather than typed. See Calculations.
Two more types appear in the field list and are not yours to choose. Timestamp is Created on and Updated on, which the kernel writes and will not let you rename, retype or delete. Relation and Portal belong to a relationship, which owns both ends and removes them when it goes.
Settings that cross types
Default. Under RULES. The value is written into a new record when nothing else fills that field. It is a starting point, and nothing stops the field being emptied again. Default sits on Text, Long text, Number, Date and Image. Choice takes its default from its own options. Switch has Default on instead. Date & time, Aggregate and Formula have none.
Number format. Under FORMAT, on a Number field, on an Aggregate, and on a Formula whose result is a number.
| Setting | Options |
|---|---|
| Style | Number, Currency, Percent |
| Thousands | On or off. Off by default. |
| Decimal places | 0 to 6. Left empty it reads Automatic. |
| Currency | Three letters, such as USD. Shown only when Style is Currency. |
Date format. Under FORMAT, on a Date field, on a Date & time field, and on a Formula whose result is a date.
| Format | 22 September 2026 reads |
|---|---|
| ISO | 2026-09-22 |
| Short | 9/22/26 |
| Medium | Sep 22, 2026 |
| Long | September 22, 2026 |
| Full | Tuesday, September 22, 2026 |
A Date & time field adds a Time row under the date one: 2:30 PM, 2:30:45 PM, 14:30 or 14:30:45.
Choice options. Under OPTIONS. + Add option adds a row, each row takes a label, the grip reorders them and the cross removes one. An option with no label blocks the save, and the panel says so. Under RULES, Allow multiple lets a record hold more than one option, and Default picks one of them. A choice field with Allow multiple on cannot be read by a calculation.
Serial. Under RULES, on a Number field only. Switch it on and two rows appear: Next value, the number the next record takes, and Step, how far the counter moves each time. The kernel fills the number when the record is created, and the field cannot be typed into. Turning Serial on numbers the records that have no number yet, in the order they were created, starting after the highest number already there. The counter only moves forward, so a deleted record's number is never handed out again. Turning Serial off keeps the numbers already written and drops the counter. A serial has no default, and turning it on clears any default the field had.
Changing a type, deleting a field
Picking a different type from the Type menu does not change the field at once. It opens the Change field type dialog, which reads the old type and the new one across the top, lists every reference the change would break, and then runs a check over the stored values. The check reports how many values convert to the new type and how many empty values stay empty. When a value cannot convert, it says the change cannot proceed and gives the count and the reason for each problem. Apply is disabled until the problems are gone.
Two targets want something from you first. A move to Date says dates must use YYYY-MM-DD. A move to Choice opens a box for the option list, one per line as value | label, and existing text has to match a value exactly.
Delete field sits at the foot of the panel. The confirmation lists the views, lookups, portal columns, sort rules and calculations that named the field, so what breaks is on screen before you agree. A calculation that loses a field keeps its text and reads as empty.
- A field has a Comment row of its own. It is a note for whoever opens the panel next, not text the record shows.
- Drag a field by its grip in the Build list to reorder it. That order is the form's too: it counts within each region column.
- A new field waits off the form until Design places it. Adding a field changes no layout on its own.
- A choice option's stored value is made from its label and remade when the field saves. Rename an option and the records holding the old value no longer match it, so settle the labels before the records arrive.
- Relation and Portal fields take their names from the relationship. The Name row on them is read only.
Calculations
Two field types hold a value nobody types. Both are worked out when the record is read, so neither can be typed into and neither takes a default.
A Formula field works along one record. It reads that record's own fields, and fields further up the parent chain through belongs-to relations. Its result is a number, text or a date, and the kernel decides which from the expression itself.
An Aggregate field works the other way, down a has-many relationship, over the records on the far side. Its result is always a number. The AGGREGATE block in Field settings takes three rows.
| Row | What it takes |
|---|---|
| Relationship | One of this table's has-many relationships. A belongs-to relationship is not offered. |
| Calculation | Sum, Count or Average. |
| Number field | A number field on the related table, or a formula or aggregate there that gives a number. Count does not use this row and hides it. |
The calculation editor
A formula field shows its saved expression in the FORMULA block, with each field name drawn as a pill. The block is a button. It opens the Calculation drawer.
FIELDS on the left is a tree over this table's fields and the fields up each relation, with a search box. OPERATORS sits under it. The EXPRESSION box takes the middle. FUNCTIONS runs along the foot, grouped Math, Text, Date and Logic, with the signature and a one-line description of whichever one you touch. Clicking a field, an operator or a function inserts it at the caret.
The kernel checks the expression as you type, a moment after you stop. The status line under the box says what you have:
- A tick and the result type, Number, Text or Date.
- With a record open in Run, Open record: and the value this formula gives for it, formatted as Run would show it, or empty on this record.
- On a failure, the message, with the offending span underlined in the box. A name that matches no field keeps its text and turns red.
Apply stays disabled until the check passes on the text now in the box. Ctrl+Enter applies. Esc closes the drawer without saving, except when the suggestion list is open, where the first Esc closes that list.
The language
A field goes in braces: {Price}. The editor writes field names, and the project stores field ids. Renaming a field does not break a calculation that uses it.
Text goes in double quotes: "Serves " & {Servings}. Inside a quoted string, write \" for a quote and \\ for a backslash. Numbers are plain, such as 0.5.
A field up the parent chain is a path of belongs-to relations. The editor joins the names with a middle dot, {Estimate · Company · Discount}. The stored form joins the ids with full stops, {estimate_id.company_id.discount}.
The operators are + - * / and &, which joins text. The comparisons = <> < > <= >= work inside IF. A date plus or minus a number moves by that many days, and a date minus a date gives days.
| Function | What it gives |
|---|---|
ROUND(number, places) | Rounds to that many decimal places. |
ABS(number) | The number without its sign. |
MIN(number, number, …) | The smallest of the numbers. |
MAX(number, number, …) | The largest of the numbers. |
UPPER(text) | The text in capitals. |
LOWER(text) | The text in lower case. |
LEFT(text, count) | The first characters of the text. |
LEN(text) | How many characters the text has. |
TRIM(text) | The text without spaces at either end. |
TODAY() | Today's date. |
YEAR(date) | The year of the date. |
MONTH(date) | The month of the date, 1 to 12. |
IF(test, then, else) | Then when the test holds, else otherwise. Both give the same kind of value. |
ISEMPTY(value) | Holds when the value is empty. |
An empty input gives an empty result through every operator and every function, and division by zero is empty as well. Nothing turns into a zero behind your back. Where an empty input needs an answer of its own, test for it with ISEMPTY inside IF.
Two examples
A line total, rounded to cents:
ROUND({Price} * {Qty}, 2)
The status line reads Number. A line with no price reads empty rather than 0.00.
A name to show, with a fallback:
IF(ISEMPTY({Nickname}), {Full name}, {Nickname})
The status line reads Text. Both branches give text, so the result type is settled.
- The OPERATORS chips read
−,×and÷and insert-,*and/. The expression is plain ASCII. - Type a brace to get a field list at the caret, or a few letters to get functions and fields together. Enter or Tab accepts, the arrows move through the list.
- Select a run of text, then click a function chip to wrap the selection in that function.
- A single-choice field reads as the label people see, not the value stored under it. A choice field with Allow multiple on cannot be read at all, and neither can an image, a relation or a portal.
- A switch reads as a number, 1 or 0. An aggregate reads as a number.
- One formula can read another. A cycle is refused and the message names the formula that points back, so a calculation that uses its own field never saves.
- An agent has the same check. The
check_formulatool returns the result type or the error and its position, and writes nothing.
Relationships
A relationship joins two tables and has two roles. The role is read from the table whose settings you have open: that table either has many records of the other one, or it belongs to one of them. An invoice has many line items, and a line item belongs to one invoice. Same relationship, named from each end.
- Open Table settings from the gear in the page head, in Build.
- Press + Add relationship. A draft row appears, reading from this table, through a role, to a table you have yet to pick.
- Pick the role and the other table. The role menu holds has many and belongs to one. The table menu lists the project's other tables.
- Press Create. The row joins the list above, and both tables change at once.
What creating one adds
The child table gains a relation field named after the parent in the singular. An Invoices parent gives its child a field named Invoice, stored as invoice_id. That field holds one record and nothing else.
The parent table gains a portal named after the child table. A Line Items child gives Invoices a portal named Line Items, which shows that invoice's line items.
Each lands at the foot of the main region of its own table's form, so both ends are on a form from the start. Design moves them, or takes them off. Neither can be renamed, retyped or deleted on its own: the relationship owns both ends and takes them with it when it goes.
A new relationship starts with the delete rule Restrict and with Create related switched on.
Each row in the RELATIONSHIPS list draws this table, the role as a wire between the two, and the other table. The line under it reads the delete rule and whether related creation is allowed. The menu at the end of the row holds Change relationship, Delete rule and Delete relationship.
Portals
A portal shows the children of the record you are on. Select it in Design and Field settings gives you its target, which form a row opens, and how the rows look.
| Setting | What it does |
|---|---|
| Target | The related table. Read only; it comes from the relationship. |
| Open detail | The form that opens when a row is clicked. None means the rows do not open. |
| Style | List for rows, Card for cards. A card portal then picks a card style and fills its slots. |
| Rows shown | How many rows the portal reserves height for. A list takes up to 20. |
| Show title | The portal's name above the rows. |
| Search bar | A search box over the portal's own rows. |
| COLUMNS | Which of the related table's fields the rows carry, and in what order. A portal keeps at least one column. |
With a form chosen under Open detail, clicking a portal row in Run opens that related record on that form, and the record bar grows a back arrow reading Back to the view you came from. With Open detail on None, the rows sit there and do not open.
Lookups
A relation field names a record. It does not show that record's values. Those come onto the form as lookups: in Design, select the region on the canvas, then switch the related field on under AVAILABLE in Region settings. The relation appears there as a branch with the related table's fields under it.
A lookup on a form carries a Shows row of its own, set to Read or Entry. Read displays the related value. Entry lets it be typed into, and the panel says what that means: the value is written to the related record, so it changes on every row that points at that record. An image lookup is Read and cannot be anything else.
On a form a lookup reaches one step across one relation. A path through more than one relation, such as a line item reading its invoice's customer's city, is available to a list column, a portal column, a sort rule and a calculation. Those paths are read only everywhere, and so are the paths an agent asks for with list_lookup_paths for a list, print or sort column and list_portal_paths for a portal column.
Rules
Delete rule in the row menu opens the shared rules. Both ends of a relationship read the same ones.
| Rule | When a record in the parent table is deleted |
|---|---|
| Restrict | Related records block deletion. This is the default. |
| Clear reference | Related records stay. Their reference is cleared. |
| Cascade | Related records are deleted. Their own delete rules then apply in turn. |
Under the rule, the dialog counts the records linked across this relationship today. Under that sits Create related. With it off, nothing can create a related record across this relationship: not the portal, not the relation picker, not an agent. Deleting a child never deletes its parent, and changing a rule does not touch a single record.
What a delete cascades to
Deleting a record plans the work before it does any of it. The dialog lists one line per relationship it reached, with the table, the effect, and how many records that effect lands on, and names the relation field each step came through.
Cascade follows the chain. A child deleted by cascade applies its own rules to its children, so the count in the dialog title and on the delete button is the whole set, not the one record you started from.
One Restrict anywhere in that chain stops everything. The dialog then says the record cannot be deleted, tells you to remove the blocking references first, and offers nothing but Close.
Deleting the relationship itself is a different act. The confirmation names the field it drops from the child table and how many stored values go with it. Aggregate fields that depended on the relationship are deleted too, which the dialog says before you agree.
- Change relationship in the row menu switches the role or the other table. It runs the same migration check as a field type change, so a change that would leave an invalid link is refused rather than half applied.
- The relationship list is on both tables. Adding one from either end makes the same pair, and either end can delete it.
- A number column in a portal can carry a Count, Sum or Avg under the rows.
- Two tables can hold only one relationship between them, so a table already related is not offered in the menu. A table cannot relate to itself either.
- A record can be created and linked in one step from the portal or the relation picker, which is what Create related governs.
Forms
A form shows one record. Design arranges it in three nested parts, and every setting in this section belongs to one of them.
A chamber is one slot of the form's shape, and the shape decides how many slots the page has and whether they stand side by side or one under the other.
A region is a box that stands in a chamber and holds fields, with its own name, frame and column count.
A column is one vertical track inside a region, and every placed field stands in one column, on one line.
The shape is set in Layout settings, the gear beside the view name, under Chambers: One, Two, T, Inverted T, Four, Sandwich, Sidebar left and Sidebar right. A full chamber holds three columns of fields, a half chamber holds two. Each chamber is ruled off on the canvas, so an empty one still shows where a region can go. One is the whole page and takes no rule.
The canvas, and what Run leaves out
Design draws the form as a preview. It draws the layout, never record values, so a field is its name over a bar and a portal is a head over faded rows. Run draws the same regions with the data in them.
What Design adds is the handles. Every region has a head with its name in it, and the grip, the column count and the settings gear appear when you hover, select or focus the region. The seams between the fields carry the line marks. In Run a region shows its title when Show title is on, and that is all that is left of the head.
The canvas is one tab stop and the parts inside it take the focus in turn.
| Key | In the canvas |
|---|---|
| Tab | From the sidebar into the canvas, then into the open settings panel. Shift+Tab walks back. |
| ↑ ↓ | Between the lines of the field's own column. Up from the first line selects the region. |
| ← → | Along the line, then into the column beside it. |
| Home End | The first or last part of the region. |
| Enter | Open the settings of the selected field or region. |
| Space | Start a keyboard drag of the field or the region. |
| L | Join the field to the line above it, or break it onto its own line. |
| Delete | Take the field off the form, or ask to delete the region. |
| Esc | Drop the selection. |
Place a field in a region
Build makes fields, and a new field waits off the form until a design places it. A field you just made is not on any form. A relationship is the exception: its relation and its portal land at the foot of column 1 of the first region.
- Press Ctrl+D and open the form view in the sidebar.
- Click the region head to open its settings.
- Find the field under AVAILABLE and turn its switch on. It lands in that region, at the foot of the column.
- Drag it on the canvas to the column and the line you want. The accent bar in the seam shows where it will land.
Move a field between columns
Three ways, all of them the same change. Drag the field across the canvas into another column. Or open the region's settings and drag its row into another COLUMN group in the FIELDS list. Or select the field and use its own Placement control, which draws the region's columns: drag the block by its grip into another column, and drag the block's trailing edge across the columns to its right to widen it. A click on a column to the right spans the block through it, and ← and → nudge the width a column at a time.
Set a field's line
A field arrives on a line of its own. The mark in the seam above a line pulls that line up beside the one above it, so two fields share the width. The mark on a joined field breaks it back onto its own line. A line is a row inside one column, and nothing in one column can move anything in another: the columns are separate stacks, with no shared row heights.
Take a field off the form
Select the field and press Remove from form at the foot of its settings, or pressDelete on it in the canvas. The field goes back off the form and its settings read Off the form. Nothing else about it changes. It keeps its type, its settings and its stored values, and it is just no longer drawn. Design places fields. Build owns what the table holds.
Region settings
Click the head of a region, or its gear, to open them.
| Setting | What it does |
|---|---|
| Name | The region's name, drawn in its head and, when Show title is on, over its fields in Run. |
| Show title | Off hides the name in Run. Design still shows it in the head, marked Hidden. |
| Column walls | Draws a rule between the columns, on the columns' own tracks. |
| Frame | Box, Divider or None. Box is a ruled card, Divider is a rule above the region, None is bare. |
| Layout | Single holds one set of fields. Tabs holds panes. |
| Columns | One, two or three. A tile the chamber cannot hold is off, with the limit in its tooltip. |
One column reads best. Use two only when the region holds enough fields to fill both, and never leave a column empty. A portal reads best in a region of one column.
A new region is added by the + at the foot of a chamber and is named Region 2, Region 3 and so on. The first region of a form cannot be deleted. Deleting any other region moves its fields into the first one, and the confirmation says how many fields move and where. Records are not changed.
Tab regions
Set Layout to Tabs, or pick Tabs instead of Region in the chamber's add menu. The region becomes a tab control and its fields move into Pane 1. The pane strip sits in the region head and + at its end adds a pane. The region's settings list the panes, and a pane's row drags to reorder. Run draws the same strip, and ← and→ move between tabs there.
- Each pane carries its own columns. A pane's settings hold its name, its column walls and its column count, and the open pane's count is what the canvas draws.
- Turning Tabs off keeps the fields. The panes' fields move back into the region, and the panes go.
- A tab region keeps one pane. Delete pane is off on the last one. Deleting the whole region takes its panes with it, and their fields move to the first region.
Field style on the form
Select a placed field and its settings hold PLACEMENT and TEXT. The text style is the field's value on this form only: Size, Normal or Title; Bold and Italic; Align, left, center or right; and Colour, from the theme tokens Ink, Secondary, Muted, Accent, Accent 2, Success, Warning and Danger, or Custom with a hex value. Every change saves at once, and the canvas behind the panel draws the result in the field's bar. A switch and a picture have no text style. A picture read through a relation gets Crop instead, Fit or Fill.
Portals on a form
A portal is the parent side of a relationship, and it draws the related records inside the form. Select it on the canvas. Open detail stands with its name and its table, and the ROWS group holds the rest.
| Setting | What it does |
|---|---|
| Open detail | The form of the related table that a row or a card opens, or None. |
| Style | List draws rows and columns. Card draws the card template. |
| Rows shown | The height, in rows or in rows of cards. Past the count the portal scrolls. Up to 20 as a list, up to 10 as cards. |
| Show title | Draws the related table's name, with the row actions beside it. |
| Search bar | A search over the portal's own rows. |
The height is the row count, not the data, so the fields under a portal stay where the design put them however many related records a record has.
A list portal's columns work as a list view's columns do: the shown ones carry a grip and a switch, the rest wait in the tree under AVAILABLE, and a column can be a field of the related table or a lookup through it. A portal needs at least one column, so the last switch is locked. Pick a column to open its own settings: Header, the text style, Shows with Read or Entry, and, on a number column, Total, set to None, Sum, Avg or Count, which draws a summary bar under that column. A lookup is read only. A picture column takes Crop, Fit or Fill.
Portal style: cards
Set Style to Card and the portal draws the same card template a grid view draws, with Cards per row from one to six. The style picks the slots, each slot takes only the field types that fit it, and a slot can also read a lookup through the related table. The styles and their slots are listed under the grid below. A portal and a grid use the same ones.
- A card is read only. It has no entry cells and no edit mark, so entry stays on a list portal and on the form. A delete mark still appears when the relationship allows deletes.
- A card opens its record only when Open detail names a form. Without one the card takes no click.
- Switching to cards trims the height. A list portal set past 10 rows comes down to 10 when it becomes cards.
Lists, grids, and split views
A table holds as many views as you want, and a view is one way of drawing that table's records. Design mode lists them in the sidebar under the table.
| Kind | What it draws |
|---|---|
| List | Records as rows, with a column per field you turn on. |
| Form | One record, arranged in chambers and regions. |
| Grid | A card per record, from one of four card templates. |
| Split | A list or grid and a form together, stacked or side by side. |
| Print list | A printed table of columns, with page bands. |
| Print form | One record on paper, with its own chambers and regions. |
Add, rename, and delete a view
- Press Ctrl+D and open the table in the sidebar.
- Press + New view under its views and pick a kind. The view goes to the end of the list, is selected, and is named New list, New grid, New form, New split, New print form or New print list.
- Type the name in Layout settings, the gear beside the view name. F2 on a view in the sidebar opens the same field.
- Drag a view by its grip to reorder the sidebar. The one at the top is the one the table opens.
Delete view sits at the foot of Layout settings. It asks first, and the confirmation says what it means: this removes the view, records are not changed. A table keeps its last view, so the button is gone when only one is left. A list, grid or split that pointed at the deleted view loses that link, and you pick another.
List columns
Open a list view and Layout settings holds its columns. The ones that are on carry a grip and a switch; the rest wait in the tree under AVAILABLE. The pool is the table's own fields plus the lookups through its relations, so a column can read a value from a related record. A portal is never a column.
Order comes from either side. Drag a shown row by its grip in the panel, or drag the column chips on the canvas. A chip carries the column's name, its sort mark with the rule's number when the view sorts by more than one field, and its field type.
Press a shown row, or a chip, to open that column's own settings beside the list's:
- Header. The text drawn over the column, in place of the field's name. Clear it, or type the field's name, to go back to the name.
- Text. Size, Normal or Title; Bold; Italic; Align; and Colour, from Ink, Secondary, Muted, Accent, Accent 2, Success, Warning and Danger, or Custom with a hex value. The size, the marks and the colour reach the cells only. Align moves the header with them.
- Picture. A picture column takes Crop instead of a text style: Fill crops the picture to the cell, Fit shows the whole picture. Fill is the default.
A list's own settings are shorter. Row opens names the form a selected row opens, or None. Print opens names the print layout its Print action opens, or None. Show title and Column walls are switches, and Frame is Box, Divider or None.
The search bar
Search bar draws a search over the list. One list also holds Primary search layout, which makes it the table's Find list, and exactly one list holds that. The Find list always shows its search, so its Search bar switch is locked on, and Primary search cannot be turned off while the table has only one list. A grid has its own Search bar switch and draws it over the cards.
The default sort
A list, a grid and a print layout each hold a sort of their own: SORT BY, then a rule per line with a field and Ascending or Descending, and + Add rule for the next one. A field takes one rule, so Add rule stops when every field is used. With no rule, records keep their created order. A sort can use any of the view's possible columns except a picture, which has no order.
The sort is a default, and Run can set the order aside. Sort records, Ctrl+Shift+S, sorts the found records another way, and Use layout sort in that dialog hands the order back to the view.
The grid
A grid draws a card per record from one of four templates. The template names its slots, you fill each slot from the table, and a slot takes only the field types that fit it, so a picture cannot land in a text line. A required slot starts at the first field that fits; an optional slot starts empty.
| Card style | Slots | Layout settings |
|---|---|---|
| Text | Title, Line 1, Line 2, Line 3 | none |
| Photo | Picture, Title, Caption | Picture, Short or Tall; Crop, Fill or Fit |
| Thumbnail | Picture, Title, Subtitle, Badge | Shape, Square or Round |
| Figure | Title, Value, Footnote | Align, Left or Center |
Title is required in every style, and so are Picture in Photo and Thumbnail and Value in Figure. Picture takes an image field. Value takes a number or a date. Every other slot takes text, a number or a date. A formula counts as the type of its result and an aggregate counts as a number, so either can fill a slot.
Cards per row runs from one to six. Card opens names the form a selected card opens. Set to None, a click only selects the record. The grid canvas draws the same template Run draws, with bars in place of the values.
Split views
A split arranges nothing of its own. It names two views of the same table and shows them together: List, which takes a list or a grid, and Form. Panes sets the arrangement, Stacked for the form below the list or Side by side for the form beside it. Either pane can be left at None, and the canvas says so until you pick one.
Each pane is still edited where it lives, in its own view. The split's canvas previews both and does not take clicks.
Records
Records are Run mode. The Record menu only appears while a project is open and Run is the mode on screen, and every shortcut below is scoped to Run except Undo and Redo.
New record and delete record
- Switch to Run with Ctrl+R.
- Press Ctrl+N, or use New record in the header. The record is created empty and becomes the current record.
- Press Ctrl+Delete (Cmd+⌫ on macOS) to delete the current record. A dialog opens before anything is written.
The delete dialog reads the relationships first. It names each related table it reaches, what the delete does there, and how many records that is. The effect is one of Blocks deletion, Clear reference or Delete. A record that another record blocks cannot be deleted at all, and the dialog says so instead of offering a button.
Right-click anywhere in Run for New record and Delete record. On a list, the right-click makes that row current first, so the menu acts on the row under the pointer.
The record bar
The record bar sits at the foot of Run. From left to right: the found count with a pie of the table it came from, Previous record, the pager, Next record, and the record number.
- The number is a field. Type a record number and press Enter to go there.Esc puts the box back.
- The pager is the whole found set, end to end. Drag it and a bubble names the record under the thumb before you let go. The arrows turn one record.
- The pager takes keys. Arrows move one record, Page Up andPage Down move a hundredth of the set, and Home and End go to the ends.
- The pie is a button while a search is on. It is Show All Records, and the wedge is how much of the table the found set holds.
Lists, grids, splits and forms all carry the bar. A print layout carries it while a record is current, so you can page through what the page will print.
Editing a field in place
On a form you type straight into the fields. The value is written when you leave the field. A switch writes on the click, on a form and in a list cell. A date or a number field shows its formatted value until you focus it, then the text you are typing, and Enter leaves the field.
List cells are read only, apart from a switch. A row opens the form named in the list's Row opens setting. The status bar reads Saving, Saved or Not saved beside the record count.
Undo and redo
| Key | Action |
|---|---|
| Ctrl+N | New record (Run) |
| Ctrl+Delete, Cmd+⌫ on macOS | Delete record (Run) |
| Ctrl+Z | Undo |
| Ctrl+Shift+Z | Redo |
Undo and Redo cover more than records. They take a field value, a new record, a deleted record, layout changes (a move on the canvas, a field's line and width, a region or a pane, adding and renaming a layout), field settings (a rename, the choice options, the rest of the settings), table settings, and a new table. Inside a text field the two keys stay the field's own text undo.
- The history holds fifty steps and it clears when you change the project or select another table. A step writes back into the table it was made in, so it does not outlive it.
- Typing then leaving one field is one step. Edits to the same field of the same record within a second merge.
- A delete is undoable only when it took nothing else with it. If the plan cleared a reference or deleted a related record, Undo would not put those back, so it does not offer to.
- Undo on a new record removes it only while nothing points at it. Otherwise it reports that other records now point at this record and drops the step.
- A step that no longer fits is dropped. You get "Cannot undo" with the step's name and the reason, and the stack moves on.
Find and sort
The search bar
A list carries a search bar at the top of the records. It is on by default, and the layout's Search bar setting turns it off. A grid can carry one too, from the same setting on its own panel. Forms have none.
- Type into the search bar. The list does not filter per letter, which keeps a long table quick.
- Press Enter. The list narrows and goes to the first record that matched.
- Clear the box to search again at once, with no Enter needed.
The search reads the columns of the layout you typed it in, and it matches the text those columns show. The status bar reads the result as a count of the table.
The found set
The found set is the records that matched. It belongs to the table, not to one layout. Change layouts and the found set holds, the search box fills with the same text again, and the current record does not move. Open another table and the search starts over.
- The record bar counts the found set and the pie beside it is the share of the table that set holds. While a search is on, the pie is a Show All Records button.
- A new record clears the search. A blank record matches nothing, so the found set gets out of its way.
- One list can be the primary search layout. The setting marks it as the one the table's find opens, and a list that holds the mark keeps its search bar on.
Show All Records, Ctrl+J in Run, gives the found set every record back. The current record stays where it is and the list scrolls to it.
Sort Records
Ctrl+Shift+S in Run opens Sort records on a list, a grid or a split. The dialog holds a stack of rules under SORT BY, most significant first.
- Press Add rule and pick the field to sort by. A field can appear in the stack once.
- Choose Ascending or Descending for that rule.
- Add the next rule to settle the records that the one above it left equal.
- Press OK. The found set reorders. Cancel leaves it as it was.
This sort lives in Run and is never saved. It goes when you change layouts or tables. While one is in effect the dialog offers Use layout sort, which drops it and hands the records back to the layout. OK with no rules does the same, and the empty stack says so: Records use the layout sort.
- A column head is a one-rule sort. Click it to sort by that column ascending, click it again to turn it around. Either way it replaces a stacked sort.
- The status bar names the sort. It shows the first rule with its direction, and a plus count for the rules under it. The tooltip reads the whole stack.
The sort a layout starts with
A list, a grid and a print list each keep their own sort. Open the layout in Design and the layout panel holds the same stacked rules as the Run dialog. These are saved with the layout, and Run uses them until a Run sort takes over. A layout with no rules says what that means: Records keep their created order.
A print layout is a view of the table, built the same way as a list or a form, and it draws paper instead of a screen. There are two kinds: Print form and Print list. Both carry the printer mark in the layout list.
A print form has an arrangement of its own, kept in the layout and separate from the table's screen form, so changing one leaves the other alone. A print list has columns, set on the layout panel the way a list's are.
Bands
A print layout is a stack of bands. Each band has a role. The role is fixed and the panel only reads it back to you. The name is yours.
| Role | Where it draws |
|---|---|
| Title header | The first page only |
| Page header | The top of every page |
| Column head | Above the rows, on a print list |
| Body | The row, on a print list |
| Page footer | The foot of every page |
A new print form starts with a title header and a page footer. A new print list starts with a page header, a column head, a row and a page footer, with the table's first six fields already in the row.
Each band sets a name, Show title, a frame, its columns from 1 to 4, and the space above and below it in inches. Fewer columns fold the last one into the one before it. A page footer sits on the bottom edge, so only its space below means anything. A print list's row and column head draw the layout's columns, so they take no column count of their own.
Inside a band, each column is a slot, and a slot holds blocks. Press + Add in a slot to add one: Text, Field, Image, Page number, Date printed or Rule. Drag a block by its grip to move it within a slot or across to another. Click a block to open its settings beside the pane. Each block's row shows what it sets as small tokens, so you can read a band without opening every block in it.
Band presets
Presets in the blocks pane fill a band in one go. A preset replaces the band's blocks and sets its column count to fit. The title text it writes is the table's name.
| Preset | Fits |
|---|---|
| Title only | Title header, page header |
| Title and page number | Title header, page header |
| Logo, title, date | Title header, page header |
| Date and page number | Page footer |
| Page number only | Page footer |
Page settings
The layout panel of a print layout holds the sheet. Paper is Letter, A4 or Legal. Orientation is Portrait or Landscape. Under OUTPUT, Records is Current or Found set, and Page break is Per record or Continuous: a sheet each, or the records running on down one. Page break is off while Records is Current, because one record is one sheet either way. Margins are the four sides in inches, a tenth at a time, and never past two.
Printing
A list or a form prints through the print layout its Print opens setting names. A layout that names none has no Print action. A split prints with the list it borrows, or else with its form.
- Open the list or form in Run and find the records you want.
- Press Ctrl+P, or choose Print in the Record menu.
- Choose Current or Found set. The dialog counts the found set for you. The layout's own Records setting is where the choice starts.
- Press Print. The print layout opens, drawn at its real size, and the sheets go to the system print dialog. Save as PDF lives there.
- The choice at print time is not saved. It ends when the print layout closes, and the layout's Records setting is untouched.
- The header counts the paper. A print layout reads the number of records and the number of pages they make, because only the drawn page knows what fits.
- A record that does not fit says so. The preview asks for larger paper, smaller margins or a shorter form rather than cutting the record in half.
An image in a band
- Add an Image block to the slot you want it in. It opens for editing with no file yet.
- Press Choose. A file dialog opens, for
png,jpg,jpeg,gif,webp,svgandbmp. - Set Height in inches. It starts at 0.5 and runs from 0.1 to 8.
The file is copied into the project's assets folder, so the project carries its own logo. A file already there with the same bytes is reused, and one with the same name and other bytes gets a numbered name. The Logo, title, date preset puts an empty image block in the left column; pick its file the same way.
Export
Export Records, Ctrl+Shift+E in Run, writes records to a CSV file. It works from a list, a grid, a split or a form. A split exports its list pane. A print layout is output already, so it has no Export.
The export drawer
- Pick the Source. Layout takes the layout's fields in reading order. Table takes the table's fields, portals aside.
- Pick the Records. Found or All, each with its count. Both choices are live only when something narrowed the set: a search on a list, or a form, which holds one record.
- Check the Order. It reads the sort in effect, rule by rule, or Created order when there is none. The file follows what is on screen.
- Turn Header row off if you want values alone.
- Arrange the fields. Drag a grip to move a field in the file. The switch turns one off and it keeps its place. AVAILABLE below adds a field reached through a relationship that already exists.
- Press the Export button. A save dialog asks where the file goes. The default name is the table and the layout, or the table and all fields.
- A portal's columns wait under its name, off. One record is one row, so a portal column writes all of its related values into one cell, one value per line.
- A field through a relationship reads as its path. The header joins the steps with a middle dot, so
company.namearrives as the company label and then Name.
What the file holds
The file opens as UTF-8 in a spreadsheet: it starts with a byte order mark, ends its lines with CRLF, and quotes to RFC 4180. A cell with a comma, a quote or a line break is quoted, and a quote inside a cell is doubled. The header row, when it is on, is the field labels.
Values are written for a spreadsheet to read, not as the screen formats them.
| Field | In the file |
|---|---|
| Number | A plain number |
| Date | YYYY-MM-DD |
| Date & time | RFC 3339 |
| Switch | TRUE or FALSE |
| Choice | The option's label |
| Relation | The related record's display value |
| Image | The file name |
| Empty | An empty cell |
The agent's import reads the same formats back. It also takes a choice's stored value in place of its label, and a record's uid in place of a relation's display value.
When an agent exports
A connected agent has the same export. It writes to the Dosirak folder in Downloads, returns the path, the record count, the header and the first rows, and never replaces a file that is already there. The rows themselves are not returned, so the number of records does not matter. A list layout is a saved export: name it and the agent takes its columns and its sort.
Connect an agent
Model Context Protocol (MCP) is an open standard for connecting an AI agent to outside tools and data. Dosirak runs an MCP server inside the app and gives the agent typed tools, so it reads and writes the same tables and records you see in the forms and lists.
- Open the project you want the agent to reach.
- Select Agent > MCP Setup… The Server entry under AGENT in the sidebar opens the same page.
- Turn on the switch for the project under PROJECT ACCESS on the Access tab. The rules beside it stay locked until you do.
- Select Clients and pick yours: Codex, Claude Code, Gemini CLI, Grok, Hermes, or JSON for Claude Desktop and other
mcpServersclients. - Copy the command or configuration with the Copy button beside the client's name.
- Do the Then and Verify steps the page lists for that client. They differ: Claude Code needs no restart, Codex does.
Keep Dosirak open while the client connects, and while the agent works. The server lives in the app. A call made with the app closed comes back as Dosirak is not connected. Open the desktop app, then retry.
You do not install anything by hand. The bridge ships inside Dosirak, and the command or configuration on the Clients tab is built for your system and points at the bridge Dosirak supplies.
The rules
A project is closed until you turn access on. Before that, the agent sees nothing: list_projects returns only the projects whose switch is on.
Once access is on, the project is open. Every table allows read, create, edit, and delete, and the Allow Build and Allow Design switches are both on. You tighten it from there.
| Control | What it covers |
|---|---|
| Project switch | Whether the agent reaches the project at all. |
| Allow Build | Tables, fields, relationships. |
| Allow Design | Views, regions, chambers, field placement, print layouts. |
| Table rules | Read, Create, Edit, Delete, one rule each, per table. |
| Field overrides | Read, Create, Edit on one field. |
Each table rule is set to Allow, Ask, or Deny from the DATA grid on the Access tab. Deny Delete on the invoices table and the agent can no longer remove an invoice. Set it to Ask and each delete waits for you.
A field can override the table rule for read, create, and edit. Those three sit in the field's own settings under Design, not on the MCP page, and each one is Inherit, Allow, Ask, or Deny. Inherit takes whatever the table says. Deny read on the field holding a home address and the agent gets the record with that value removed.
The two switches do not grant each other. Turning Design on leaves every Build tool denied, and the other way round.
- The rules sit on the project, not on the client. Connect a second agent and it sees exactly the access the first one has.
- A Deny beats an Ask. If one call touches a denied field and an ask field, it fails rather than queueing.
- Move a project folder and its access breaks. Locate project… on the Access tab points the saved rules at the new path, and it refuses a folder whose tables do not match.
What Dosirak does not govern
Dosirak governs its own database. It does not govern the rest of an agent's tools. If the same agent can send mail or write files, that is between you and those tools.
A cloud agent sends what it reads to its provider. The database file stays on your disk, but the records the agent is allowed to read travel with it. Deny read on the tables and fields you want to hold back.
Approvals and activity
Set a rule to Ask and the agent's call never reaches the database. It stops and waits as a request, and nothing is written until you review it. The agent gets an approval_required error telling it to look in Dosirak.
Open the queue from Agent > Approvals, or from Approvals under AGENT in the sidebar. That sidebar entry carries a count of the requests waiting for you. The page has two tabs: Active and History.
What a request shows
Select a request in the queue and the panel shows:
- The client that made the call, or MCP client when it gave no name, and the tool it called.
- The action and the table, in the heading.
- Progress: Requested, Review, Apply, with how long ago each finished step happened.
- The fields the call touches, by their labels, under Field, Now, and Proposed. A create shows Proposed alone, since there is no current value.
- A delete plan, when the call is a delete: each table and field that refers to the record, how many records that is, and whether the rule reads clear reference, delete, or blocks deletion.
- A migration plan, when the call changes a field type or a relationship: the field, the change, how many stored values convert, and how many stay empty.
A relation value appears as the related record's display value, not its identifier.
Approve or deny
- Read the request. The Now column is what the record holds today.
- Type a note if you want one kept with the request. The field is optional, and the note shows with the request under History.
- Select Approve & apply to write the change, or Deny to refuse it. Dismiss drops the request without answering it, and Clear all drops every request waiting.
An approved request applies at once. You do not have to tell the agent to try again.
- Approving lifts the Ask rules for that one call. It does not lift a Deny, and it does not change the rules on the project.
- If the record changed between the request and your approval, the write does not run. The request goes Stale and the agent has to ask again against the current values.
- Turn project access off while a request is waiting and the request is cancelled.
- Two identical calls do not make two requests. The second attaches to the one already waiting.
Bulk changes need Allow
The bulk tools, plan_record_changes, plan_import_records, and apply_record_changes, do not queue. They need Allow on every table and every field they touch. One Ask in the set and the whole call fails with bulk_requires_allow, which tells the agent to either get the rule set to Allow or work one record at a time with create_record, update_record, and delete_record.
The activity strip
The strip along the bottom of the window shows the server state, OFF, READY, or CONNECTED, how many clients are connected, and the calls made against the open project, oldest at the left.
Every call is recorded, whichever rule applied, including the ones that were denied or that failed. A check mark means the call finished, a question mark means it is waiting on you, and a cross means it was denied or it failed. Hover an entry for the time, the tool name, the project path, and the message. A denial's message reads Denied, then the field or table, then the action it wanted.
The strip holds recent calls for the project you have open. Answered requests stay under History on the Approvals page.
Themes and appearance
The View menu holds both controls. Theme lists every theme and applies the one you pick. Appearance… opens the screen where themes are made. The choice is app-wide and survives a restart. It is not stored in the project, so a theme does not travel with a .dosirak bundle.
Six themes ship with the app. None of them can be edited.
| Theme | Mode |
|---|---|
| Hanji | Light. The default. |
| Celadon | Light |
| Aluminum | Light |
| Lacquer | Dark |
| Obsidian | Dark |
| Slate | Dark |
The gallery
Appearance opens on a grid of cards, CUSTOM first, then BUILT-IN. Each card draws the chrome, sidebar, fields and accent button in its own colours, and carries the theme name and a Light or Dark badge. Click a card to apply it. The active card gets a ring and an Active check.
Each card has a menu. Every theme offers Duplicate and Export. A custom theme adds Edit, Rename, Reset and Delete. The header holds New theme, which duplicates the active theme and opens the editor on the copy, and Import, which reads a theme file from disk.
The theme editor
- Start from a theme. Press New theme, or pick Duplicate on any card. A built-in theme cannot be edited, so a copy is the only route.
- Name it. The name sits in the editor header. A copy arrives as
Hanji copyor whatever the source was called. - Set the tokens. The panel groups them. A colour takes a hex value typed in the field or picked from the swatch.
- Watch the preview. The pane beside the panel redraws a small app on every change. Nothing outside the editor changes until you save.
- Save and close. The button is disabled while a token is invalid, and a count of blocking issues sits next to it.
What a theme sets
| Group | Tokens |
|---|---|
| SURFACES | Mode, App, Chrome, Sidebar, Inspector, Compartment, Input, Input focus, Tray |
| INK | Primary, Secondary, Muted, Inverse |
| ACCENT | Primary, Hover, Subtle, Secondary |
| STATUS | Success, Warning, Danger, Info |
| BORDER | Color, Strong, Focus, Width |
| SPACING | Wall, Thin wall |
| RADIUS | Control, Compartment, Badge |
| TYPE | Heading, Body, Mono |
| DENSITY | Spacing, Text size |
Mode is Light or Dark. Width, Wall, Thin wall and the three radii are fixed steps on a segmented control. Spacing is Compact, Normal or Loose. Text size is S, M or L. Heading, Body and Mono each choose from the fonts the app carries: Newsreader, IBM Plex Sans, IBM Plex Mono, JetBrains Mono, System Sans, System Serif, System Mono.
- Duplicate and Export in the editor go dead while you have unsaved changes. The tooltip says Save first.
- Reset puts back the values of the built-in theme the custom one was copied from. The name and the id stay.
- Double-click a custom card in the gallery to open the editor on it.
- Export writes TOML, named after the theme id with the suffix
.dosirak-theme.toml. Import reads a.tomlfile back. - Custom themes live in the app data directory, beside the stored theme choice. They are never written inside a project.
Colours on a field or a column
A field on a form and a column in a list carry their own text colour. Eight of the choices are theme tokens, so they follow the active theme and its mode. The ninth is a fixed #rrggbb value, which stays the same in light and dark.
| Value | Draws with |
|---|---|
ink | Ink Primary |
secondary | Ink Secondary |
muted | Ink Muted |
accent | Accent Primary |
accent2 | Accent Secondary |
success | Status Success |
warning | Status Warning |
danger | Status Danger |
#rrggbb | That colour, in both modes |
In the app the same set appears as Ink, Secondary, Muted, Accent, Accent 2, Success, Warning, Danger and Custom. ink is the default.
Every shortcut
The app's keymap, by group. Help > Keyboard Shortcuts in the app shows the same list for the computer it runs on. A key in a list group works while that list has the focus.
Project
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| Ctrl+Shift+N | Cmd+Shift+N | New Project | Any mode |
| Ctrl+O | Cmd+O | Open Project | Any mode |
| Ctrl+W | Cmd+W | Close Project | Any mode |
| Ctrl+Shift+R | Cmd+Shift+R | Reveal Project in File Manager | Any mode |
| Ctrl+Q | Cmd+Q | Quit Dosirak | Any mode |
Edit
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| Ctrl+Z | Cmd+Z | Undo | Any mode |
| Ctrl+Shift+Z Ctrl+Y | Cmd+Shift+Z Cmd+Y | Redo | Any mode |
Modes
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| Ctrl+B | Cmd+B | Build | Any mode |
| Ctrl+D | Cmd+D | Design | Any mode |
| Ctrl+R | Cmd+R | Run | Any mode |
Navigation
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| Ctrl+1 | Cmd+1 | Focus the sidebar | Any mode |
| Ctrl+2 | Cmd+2 | Focus the main area | Any mode |
| Ctrl+3 | Cmd+3 | Focus the settings rail | Any mode |
| Ctrl+Shift+↑ | Cmd+Shift+↑ | Previous Table | Any mode |
| Ctrl+Shift+↓ | Cmd+Shift+↓ | Next Table | Any mode |
| Ctrl+Shift+← | Cmd+Shift+← | Previous View | Any mode |
| Ctrl+Shift+→ | Cmd+Shift+→ | Next View | Any mode |
| Ctrl+K | Cmd+K | Go to | Any mode |
| Ctrl+\ | Cmd+\ | Show or Hide Sidebar | Any mode |
| Ctrl+F | Cmd+F | Find | Any mode |
| Esc | Esc | Close or deselect | Any mode |
Settings
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| Ctrl+I | Cmd+I | Settings for the selected field | Build |
| Ctrl+I | Cmd+I | Settings for the selected part | Design |
| Ctrl+Shift+I | Cmd+Shift+I | Table settings | Any mode |
| Ctrl+, | Cmd+, | Appearance | Any mode |
Fields
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| Ctrl+N | Cmd+N | New field | Build |
Records
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| Ctrl+N | Cmd+N | New record | Run |
| Ctrl+P | Cmd+P | Run | |
| Ctrl+Delete | Cmd+⌫ | Delete record | Run |
| Ctrl+J | Cmd+J | Show All Records | Run |
| Ctrl+Shift+S | Cmd+Shift+S | Sort Records | Run |
| Ctrl+Shift+E | Cmd+Shift+E | Export Records | Run |
| Ctrl+[ | Cmd+[ | Previous record | Run |
| Ctrl+] | Cmd+] | Next record | Run |
Help
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| Ctrl+/ | Cmd+/ | Keyboard Shortcuts | Any mode |
Mode switch
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| ← → | ← → | Previous or next | Any mode |
| Home End | Home End | First or last | Any mode |
Sidebar
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| ↑ ↓ | ↑ ↓ | Move | Any mode |
| Home End | Home End | First or last | Any mode |
| ← → | ← → | Fold or unfold | Any mode |
| F2 | F2 | Rename | Any mode |
| Space | Space | Start a keyboard drag | Any mode |
| A–Z | A–Z | Jump by name | Any mode |
Field list
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| ↑ ↓ | ↑ ↓ | Move | Build |
| Home End | Home End | First or last | Build |
| Enter | Return | Open | Build |
| F2 | F2 | Rename | Build |
| Space | Space | Start a keyboard drag | Build |
| A–Z | A–Z | Jump by name | Build |
Calculation editor
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| ↑ ↓ | ↑ ↓ | Move through suggestions | Build |
| Enter Tab | Return Tab | Accept the suggestion | Build |
| Ctrl+Enter | Cmd+Return | Apply | Build |
Record bar
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| ← ↓ | ← ↓ | Previous record | Run |
| → ↑ | → ↑ | Next record | Run |
| Home End | Home End | First or last record | Run |
| Page Up Page Down | Page Up Page Down | Move by a page | Run |
Record list
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| ↑ ↓ | ↑ ↓ | Move | Run |
| Enter | Return | Open | Run |
| A–Z | A–Z | Jump by name | Run |
Tabs
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| ← → | ← → | Previous or next | Run |
Design sheet
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| Tab Shift+Tab | Tab Shift+Tab | Next or previous zone | Design |
| ↑ ↓ ← → | ↑ ↓ ← → | Move | Design |
| Home End | Home End | First or last | Design |
| Enter | Return | Open settings | Design |
| Space | Space | Start a keyboard drag | Design |
| L | L | Join or split the line | Design |
| Delete Backspace | ⌦ ⌫ | Remove | Design |
Print bands
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| ↑ ↓ | ↑ ↓ | Move | Design |
| Home End | Home End | First or last | Design |
| Enter Space | Return Space | Open | Design |
| A | A | Add a block | Design |
| Delete Backspace | ⌦ ⌫ | Remove | Design |
Field tree
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| ↑ ↓ | ↑ ↓ | Move | Any mode |
| Home End | Home End | First or last | Any mode |
| ← → | ← → | Fold or unfold | Any mode |
| Enter Space | Return Space | Pick | Any mode |
Approvals
| Windows and Linux | macOS | Action | Mode |
|---|---|---|---|
| ↑ ↓ | ↑ ↓ | Move | Any mode |
| N | N | Write a note | Any mode |
| A | A | Approve & apply | Any mode |
| D | D | Deny | Any mode |