Sign in, then find your way around
One page: get in, learn the loop, and read what each surface in the app is for — in the words of the help the app itself shows on it.
Getting started
There is nothing to install. Create an account, start your trial, and Compass opens on your company's workspace.
- Create an account — sign up, then add a card to start seven free days. Your workspace opens as soon as the trial does.
- Open the app — the button on your account takes you straight into your workspace. The site and the app are separate origins, so that button hands you across rather than being a plain link.
- Start where you are — add your first domain and service from the two icons at the start of the Explorer's header line.
A company has one workspace — its config, its code, its git repository and its running instance — and everybody you add to the team works in it with you, with the access you give them on your account.
The loop
Describe the shape, create the services, write the code, build it. Go round as often as you like.
- Design — add domains and services from the Explorer (a new service's project is made from the template you pick), or bring in folders you already have: in the Explorer's edit mode a folder's + adds it to a domain, as a subdomain or a service, by reference. The Topology draws how the code fits together.
- Create — adding a service makes its project from a template: a set of files your workspace keeps in Policy ▸ Templates, in any language, with the service's name filled in. Set one up first; with none, New service says so and takes you there.
- Implement — you write the code: in the built-in editor, in your own IDE, or by handing an issue to an agent, whose Work runs on the issue's own branch. It is yours from the first line.
- Build — check the shape is sound and compile:
compass validate, thencompass build. In the app, ▶ at the top of the Actions panel under a service's code builds it — the way its folder says, in any of the languages Policy ▸ Run & build lists — and runs a Rust service, and Problems shows compiler errors as you go. - Ship — build and run the services in your workspace, and keep them building as the design changes underneath them.
Drift is the loop's safety net: compass scan subjects reads the events out of the code as it stands now and tells you what the model does not know about yet.
The app, surface by surface
This is the app's own help, in one place: the same text Compass shows at the top of each surface and collects under Tools ▸ Help. Global Policy and Version Control have no card of their own in the app — they are read on that page.
Explorer
Browse your whole workspace as a tree — domains, the subdomains under them, and their services — and open any of them to work on it.
- Click a service's (underlined) NAME to open it in the Inspector. Its functions, models and events are on its Topology — the Explorer does not list them under it.
- New domain and New service are the first two icons on the Explorer's header line. New service asks for a name and a template, and makes the service's project in its domain's folder. Templates are your workspace's own, in any language (Policy ▸ Templates) — with none set up yet, New service says so and links there; the service is whatever its files are, so a
Cargo.tomlmakes it Rust and a.csprojC#. Renaming a service moves its folder. - Press / to jump to the search box, and : for COMMAND mode in the same field (from anywhere but a text box or the code editor, where those keys type).
- The row of whatever is open in the Inspector stays highlighted here until you open something else.
- The Explorer's tree icon at the left-hand end of the top bar and Ctrl/Cmd+B are one press: the Explorer goes, then the file tree beside an open file, then both come back. The icon beside the editor's tabs shows and hides that file tree alone. On its header line the right-hand icons are a warning sign while some folder holds code that is in no project — shown in the edit mode, beside the pencil: press it for every warning and what it says, and press one to show its folder — the pencil, which switches between domains and plain files, Refresh, which reads the folders and domains again, and the ⋯: Layout and the filters — the services' protocols to show, and the labels, type icons and tree lines the rows wear.
- At the right-hand end of the status bar, beside the bell, the team chat — two speech bubbles, with how many messages are unread — talks with the people in this workspace: press it, and the chat slides up over the page from it. The team chat comes with a Pro subscription — not its free trial.
- The bell at the right-hand end of the status bar keeps every message that pops up — the newest 25, with how many beside it (lit until you have seen them, red when one is an error). Press it to read them again, close one with its ×, or Clear all.
Command mode (:)
/ searches and only searches. The chip at the left of the field says what the box does with your words — Search unless you pick another, and Viewer Search while the Viewer is on screen.
Pressing the chip, or the : key, drops the commands down with the field empty: type to narrow them, the arrows move through them (the chip shows the highlighted one), Enter or a press chooses, and Escape puts everything back.
:searchfinds everything at once, each kind under a line of its own: services, workers, domains and the Explorer's folders; functions, as the Topology's Tree finds them — by their name, their owner's with it (Builder::call), or their file's path, in any case — in every project of the scope, each written as the Tree writes it and opening its card on the Topology; issues, by their title or their id, anywhere in the workspace — every word typed, any case, open or finished; or the eight characters their ID shows (their branch'sissue-…), the whole id or its first four or more, or a tracker's key (ENG-123); notes, by their name — every word typed — or the eight characters their ID shows, the whole id or its first four or more, anywhere in the workspace, each opening on its page; and the words in the files of the scope, the best files first, each opening at its line. The filter beside the field hides any kind of them:viewer_searchopens a service, domain or subdomain in the Viewer as its Map or its Sequence; it is chosen for you while the Viewer is on screen, and what was chosen before comes back when the Viewer goes
:f is short for search. Backspace in the empty field disarms a command.
The scope is the press at the field's right end: where search looks and where new work is filed — the service, domain or folder selected in the Explorer. Pressed, it opens the composer on it. With none selected it is not there, and the box says Select a scope in the Explorer to search.
Clicking a row
Rows carry no hover icons — the name is the link (it underlines when you point at it). A domain's, a subdomain's or an app's opens it in the Inspector on its Overview, the tab beside its files — the one open already, or a new one; a service's opens its editor. Opening one makes it the scope, and the Explorer is put away to give it the room; the Explorer button at the top bar's left end — or Ctrl+B — brings it back. Opening or closing a branch leaves it where it is, and so does a press with a key held.
The rest of a service's row does nothing — its functions, models and events are on its Topology, not in the tree. Everything the old icons did is on the item once it is open.
Ctrl/Cmd+B
Hides the Explorer. With a file open in the Editor, the next press hides the file tree beside it too, and the one after brings both back.
The Explorer button at the top bar's left end (the tree mark) does exactly the same, and its tip says what the next press does. The icon beside the editor's tabs shows and hides that editor's file tree alone.
On a narrow window
On a phone's or a small tablet's window the app is laid out as it is on a wide one — the same bar, the same tabs — but there is no room for the Explorer beside the page, so it slides in over the page instead: the Explorer button at the top left, or Ctrl+B, brings it in and puts it away, and so does picking something in it, opening anything from the Tools menu or the search, or pressing the page beside it. An editor's file tree does the same there: its own icon brings it in over the page, and it goes when you pick a file or press the page.
A wide window can have its Explorer slide in over the page too: tick Float over the page in the Explorer's ⋯, under Explorer left and right — your browser keeps it, and unticking it puts the Explorer back beside the page.
Tree lines
The lines in the tree — the vertical guides that connect nested rows to their parent, and the horizontal rule under every row — can be switched off entirely from the ⋯ on the Explorer's header line, under Show ▸ Tree lines (alongside the domain, subdomain and protocol labels and the type icons).
Indentation is untouched, and the choice is remembered per browser.
Explorer vs Inspector
Explorer is the tree you browse; Inspector is where the items you open show up as tabs. Opening an item from the tree switches you to the Inspector with that item focused.
Plain files
The pencil on the Explorer's header line is the Explorer's edit mode: the plain files of the folder Files root names (Settings ▸ Explorer), where a folder's right-click shows it in the Explorer or leaves it out, a root folder's row has a picker for the domain or subdomain it is in, and a folder in a domain has a + that makes it a subdomain of that domain, named after it — its row then says SUB where the picker was (press it for the same picker). The folders compass keeps its domains in, at the top of the workspace, are not listed. Press the pencil again when you are done.
The files there are faint, and pressing one does nothing — they are opened in the Inspector. Press a folder to open it in the list, and again to close it — one press — there alone: the Inspector stays as it is, so its own file tree is not opened alongside. To see a folder in the Inspector, right-click it and pick Open in the Inspector: a domain, subdomain or project opens as itself; any other folder opens as the project or folder that holds it, its file tree opened down to the folder, which is highlighted. The name of the Files root, at the top, opens the whole folder there.
Root folders
The Explorer shows the folders you add from your Files root (Settings ▸ Explorer) — each a root of its own, read down to its projects, a subdomain of the domain it is in — and nothing else under the Files root. Its Overview, and the Overview of every folder in it above its apps, is a subdomain's: its name and description, a band of figures across its top, and its README in a reading column — Edit at its top right opens the README in the editor, and the icon beside it drops down its outline, a heading pressed scrolls to it; read a way down, the round ↑ at the column's foot goes back to its top — with its charts at the right. Its properties drop down from its kind beside its name (“subdomain ▾”): its Location, its domain, its README by its path (press it to open the file) and its manifest. What is in it — Apps, Subdomains and Warnings — drops down from the band's Apps tile, each a list as a function card's In and Out are; press one to open it. A folder with no README has its properties in the reading column instead, with Create README.md at the column's top right: it makes the folder's README.md, its name the heading, and opens it to write — from then on the Overview reads it. On a phone the file tree is put away to give it the width (◱ brings it back).
- Add one from the plain files (the pencil on the header line): press a faint folder's + — its Add to compass card opens there and then, beside it. The Explorer's own Add a folder opens that view.
- Adding one asks for its domain — one you have, or a new one — before the Explorer reads it. Only those it can go in are offered: the top domains, and the subdomains that group folders — not one made of a folder, which is that folder's own. It is a reference: the domain names the folder, and the folder stays where it is on disk.
- A root folder in no domain is not shown, and the tree says nothing of it — it may be meant so. In the edit mode (the pencil on the header line), its + picks its domain.
- The free plan shows one root folder: adding another puts it in place of the first, and the card says so. Pro shows as many as you add.
- Once it is in a domain its row in the edit mode says so with a chip — SUB, or DOM in a top domain, the domain named in its tip. The chip is a label: taking it out is its +'s — Remove … from, which takes it out of the domain, asking first. A root folder taken out of its domain is out of compass, as it was before it was added — out of the root folders too, with an Undo that puts both back — and its + adds it again. One left in no domain another way (its domain deleted, say) has nothing on its row: its + picks its domain. Its right-click takes it out of the root folders and out of its domain, asking first; Undo puts both back.
- A folder's + in the edit mode — a root folder, or any folder in one — drops down Make … a subdomain, which makes it a subdomain of the domain it is in, named after the folder (one of that name there that holds nothing yet is used instead), by reference; the message has an Undo. From then on the subdomain's row in the Explorer is the folder's — what is in the folder is drawn in it, once — and the folder's row in the edit mode says SUB; its + has Remove the subdomain, which asks first, takes the subdomain made of it away and puts the folder back with the folder it sits in.
- The same + makes a folder a service where it is — at the foot of its dropdown, under a line, each item with the mark the Explorer gives what it makes (a subdomain's stack, a service's cube): Make … a service opens a card at the folder's row asking its name (the folder's, as an identifier) and its label — one of the list, or New label… to type one. Nothing is made on disk: the service's code is the folder, wherever it is, and it is in the domain the folder is in (it moves with the folder). A folder is a service or a subdomain, never both: a subdomain's folder is not offered Make … a service, and a service's folder is not made a subdomain — nor by Make each folder in it a subdomain. Its row has a chip as a domain's does — the service's cube and SVC, or its label once it has one; press it to pick another label, no label, or a new one. Stop … being the service, at the foot of that dropdown and of the +'s, takes it out of the topology and leaves the folder as it was.
- The same + drops down more: Make each folder in it a subdomain — each named after its folder, in the domain it is in — or every folder under it, all levels, nested as the folders are. Both ask first, with how many, pass over folders that are subdomains already, hidden or left out, and have an Undo. At its foot, Make each folder in it a service makes a service of each folder in it, where it is — each named after its folder as an identifier, with a number after it where a service has that name already — asking first with how many and their names, passing over folders that are services or subdomains already, hidden or left out, with an Undo. Remove the subdomains made of the folders under it takes them away again, asking first.
- A domain names its folders by their paths. Rename or move a folder in compass and every link to it — and to the folders in it — follows it, with the Explorer's own lists (root folders, folders shown or left out). Rename, move or delete one elsewhere (a terminal, another editor, git) and its links are said not there — a row where it was, and a warning in the edit mode — with where it seems to have gone: a folder beside it with what was in it, or one of its name elsewhere. Relink carries the links there; Forget it lets them go (the subdomains made of it are taken away). The folders compass keeps its domains in are not edited as folders — not renamed, moved, copied or deleted in the file tree, nor given a src/ — do that to the domain, on the Domains page.
- It is governed by its domain, as a service is: what the domain and every domain above it set — AIs, prompts, lanes, labels, views and projects — reaches it and every folder in it, and what a folder sets itself comes after. The domain's issues include its folders', its Topology their projects, and its file tree the folders themselves — at their real paths.
Showing or leaving out a folder
Switch the Explorer to plain files (the pencil on its header line). A folder the Explorer leaves out is faint — its tip says why: ignored by name, by you, inside an ignored folder, or no project under it.
- Right-click a faint folder and pick Show in the Explorer. It comes in under the folder it sits in — a subdomain of that domain — even from inside an ignored folder, or with no project in it.
- Right-click any other folder and pick Leave out of the Explorer. A folder you showed under it, or set as a domain of its own, goes with it — the message says so, with an Undo.
- Right-click a folder in a domain and pick Make it a domain of its own: it is a domain at the top, its folders its subdomains, wherever it sits; Put back where it sits takes it back under the folder it is in. One that is not there any more is a warning in the edit mode — pressed, it is forgotten, with an Undo.
The Explorer keeps these lists itself, with its root folders — Settings has only its Files root, where it starts. A folder inside a project, or a service's own folder, has neither. A folder's + is always on its row: pressed, it drops down what can be done — make it a subdomain, each folder in it, or every folder under it; take those made under it away; or, a folder not in compass yet, add it.
Team chat
The status bar's chat press, at its right beside the notifications bell, opens the team chat: talk with the people in this workspace — everyone who has signed in to it. It comes with the Pro plan — a Pro subscription, not its free trial: on another plan, and during the trial, the status bar has no chat press, and Tools ▸ Chat says so. It opens as a tall small window over the press, the conversation open filling it, its box at its foot — Type a message, with Format, the ☺, the paperclip and Send in it at its right: Enter sends, Shift+Enter starts a new line. The paperclip finds an issue, a note or a branch — three columns side by side, Issues, Notes and Branches (one under the other where the chat is narrow), the newest of each before you type, then by its words, an issue by its id too. ↑ ↓ move through them in turn and Enter puts the lit one in: its id (a branch, its reference — b: and its name) goes in the box, the others seeing its card once it is sent. Its head names the conversation, and its ▾ lists all of yours — New conversation first, then each with how many you have not read — the ▾ itself saying how many are unread in the others; its ⋯ is the conversation's.
Maximize, at the small window's top right, opens the chat as a tab of its own — Tools ▸ Chat opens the same tab — with the conversation you had open and what you typed: your conversations down its left — New conversation first, then each with whom it is, its newest message, when, and how many you have not read — and the one open beside them; on a wide screen, a conversation keeps to a column in the middle. Drag the list's edge to make it wider or narrower — or move it with ← → once it has the keyboard — and your browser keeps the width; a double press on the edge puts it back. While the tab is on screen, the status bar's press goes to it; once you have gone to another tab, the press opens the small window where you are, and the Chat tab, shown again, takes the chat back. Hold the small window by its head to move it where you like — it opens there again — and a double press on its head puts it back over its press.
New conversation starts one: pick a teammate for one of your own, or several for a group, with a name if you like. The people of a conversation you have already are that conversation — the chat says so before you press, and opens it rather than making a second. Each conversation in the tab's list has a ⋯ where its time is, with the pointer on it: Open in a tab, Mark as unread — it stays unread, even on screen, until you open it from the list — or Mark as read, and, for a group, Rename, Add people (they read what was said before, too) and Leave; a conversation is only ever read by the people in it. Drag a conversation up or down the tab's list to put it where you like — held anywhere on its row, or by the six dots at its left while the pointer is on it (on a touch screen, always there) — or Alt+↑/↓ on it, and the list keeps that order for you, on any device; its ⋯'s Newest first puts it back in order of the newest message.
Messages are drawn as the AI chat draws its turns: who said it — You, or their name — and when, over it; yours in a grey box, theirs on the page. That is the Compact layout; Comfortable puts yours at the right in a bubble of the accent colour and everyone else's at the left in grey ones — Display, in the conversation's ⋯, switches between them, and your browser keeps the choice. A run of one person's messages sits under one name. Each day is said between the messages, and what came since you last read is under New. The chat is drawn in the editor's typeface at one size — Chat text, in Settings ▸ Text size and wrapping, which is Editor text's until you step it.
Messages are markdown, as the AI chat's answers are: bold, italic, code, a fenced code block, bulleted and numbered lists, a quote and links. Format shows a row in the box, over the words, that writes them — Bold (Ctrl+B), Italic (Ctrl+I), struck (Ctrl+Shift+X), a link (Ctrl+K: what is picked becomes its words, the address picked to type over), a numbered list (Ctrl+Shift+7), a bulleted one (Ctrl+Shift+8), a quote (Ctrl+Shift+9), code (Ctrl+E) and a code block (Ctrl+Shift+E) — and puts it away again. A list started on an empty line comes with three items to fill (on a line with words, they are its first): Shift+Enter at an item's end goes on into the next empty one, or makes another, and on an empty item ends the list; any left empty go as the message is sent; the keys work either way, and the box's ☺ puts in an emoji. Shift+Enter on a list's line starts its next item; on an empty one, it ends the list. A picture written into a message is shown as a link to it.
An issue's or a note's id in a message — as its Copy ID gives it: an i or an n and its eighteen characters — is drawn under the words as its card, the one the boards draw: an issue's as the Workspace board has it — its state, its title, its labels, when it last moved, its swim lane, its due date and who has it — and a note's as the Notebooks page has it — its title, a line of its words, its labels, how many notes are under it, and when it changed — each with its id and its level on its first row. Each has its ⋯, the issue's own menu or the note's. A card does not show the id — the issue's is in its tip, and either's ⋯ copies it. Pressed, a card opens the issue's page, or the note's, in its own level; on an issue nobody has, Claim makes it yours. While the chat is open the cards keep up with their issues and notes — a change made here at once, one made by somebody else within about fifteen seconds. The id itself is taken out of the words, so it is not said twice — a message that was only an id is its card. A branch is a card too, written as its reference — b: and its name, b:feature/login, as Version Control's copy press (at its top, beside Refresh) and the paperclip give it: its name with the branch mark before it, and over it the project when it is a project's own branch; its newest commit — what it says, who made it and when; how many commits it is ahead of the main branch and behind it, and the files and lines it changed since it left it (lines added in green, taken out in red); whether it is checked out, and how it stands against where it is pushed. Pressed, Version Control shows its history. A branch this checkout does not have is looked for on origin — fetched from it if it has not been — and its card says on origin; a reference that names a branch neither has stays in the words with the warning mark. A name without its b: is only words, whatever it looks like. An id of that shape that names no issue or note you can open stays in the words, with a small warning mark after it saying so — and so does one a few characters off, an i or an n and 15 to 21 characters where an id has 18, its mark saying how many it has. An id written as code is left as it is, and a message cards three at most.
With the pointer on a message's words, a bar opens over it, toward their end, as in Teams: six emoji, a press each, then ☺+ for the rest of the emoji, and — on yours — Edit, and ⋯ with Copy text and Delete; picking an emoji puts it away, and the conversation makes room to show it. The emoji on a message sit at its foot — a little over the bottom edge of its box, in from its side, where its words are in one (yours always, everyone's in the comfortable layout) — yours lit, who put them there in its tip, how many where more than one; a press adds yours or takes it off. Their ☺+ adds another: it ends the row — after the emoji, at the far right of yours in the comfortable layout, where it is always shown (in the compact one, under the pointer) — its emoji opening from its right edge on yours there and from its left edge elsewhere. Edit puts its words in a box in their place — Enter to save, Escape to leave them; Delete asks first, then deletes it for everyone, leaving “This message was deleted.” in its place. The others see an edit, a deletion and an emoji as it happens.
A long conversation is read a page at a time — Earlier messages for more — and the chat holds only so much of it at once, asking only for what is new.
@ names someone: typed at the start of a word in the box, it lists the people of the conversation — you left out — whose name or handle starts with what you type after it, as in Teams; ↑ ↓ move, Enter or Tab puts the lit one in, Escape puts the list away. A person's handle is their sign-in address up to its @ — @ben for ben@example.com — and typed whole it names them too. In a message, each person named is drawn by their name, you in red, and a message naming you has a red bar down its left. Until you read it, a red dot pulses on the status bar's chat press and on the Chat tab, and its conversation has a red @ in the list. Only the people of the conversation can be named; an @ inside code, or an address, names nobody.
A new message pops up as a card for a few seconds — who said it, the group it is in, two lines of it, and how many more came with it in that conversation — with a red @ and a red bar down its left when it names you, and then it stays a little longer. Press it to open the chat on that message, lit as the chat comes to it; otherwise it goes by itself — never while the pointer or the keyboard is on one. Your own messages, and a conversation you are reading on screen, do not pop up, and nor do messages that came more than ten minutes before you came back to the app — the press's number counts them. Where they pop up is yours: the conversation's ⋯ ▸ Toast position shows the screen's nine places — the top, the middle or the bottom, at the left, in the middle or at the right — the bottom right at first; pick one and a card pops up there to show you, and your browser keeps the choice.
The press's number is how many messages you have not read, lit while there are some; a conversation you open is read. Someone who has not signed in to the workspace yet is not in the team until they have.
Signed out of the workspace — your password changed elsewhere, say — the chat says so under its head, keeps what you typed and stops asking for new messages; Sign in again takes you to the sign-in and back, your words in their box.
Text size
Settings ▸ Text size and wrapping has a size for each part of the app — Editor, Actions, Explorer and Settings (the Explorer tree and the Settings page, at one size), Work, Note and Chat — and, first, All text: the size of every one of them that has no size of its own, 12px until you change it, each kept inside its own range. Change a row and it keeps a size of its own, with a ↺ beside it that gives it back to All text (Work and Chat text's give them back to Editor text's, which they follow); Apply to all, beside All text, gives every row back at once, and Reset puts every size where it starts — All text at 12, no row with a size of its own. App zoom scales the whole app instead, and All text leaves it alone.
The Settings page grows and shrinks with Explorer and Settings text, so while the pointer stays on the row you are pressing it keeps its size — the next press lands on the same button — and it takes the new size when the pointer moves off.
Inspector
Work on what you open — services, domains, models, and the tools in the Tools menu — each in its own tab.
- Open several at once; the tab bar switches between them, and tabs can be dragged to reorder. Drag a tab onto the body to see two side by side.
- A service opens straight into its Editor; a domain, a subdomain or an app picked in the Explorer opens on its Overview, a tab beside its files. The icons on its file tree's toolbar open its other views as tabs beside the files: Overview, Policy, Topology, Notes — its notes and its levels' under it, in their notebooks — and Workspace — its issues, board and AI tasks. Before Topology, the Viewer's mark — Open in Viewer — opens its Map, the one its Topology tab draws, in a pane of the Viewer.
- A domain's or subdomain's Overview is laid out as a folder's: a band of figures across its top — its open issues, done, notes, files and apps, each with what changed this week and twelve weeks as a line; pressed, the Apps tile drops down its apps, and the subdomains and warnings on its line drop down theirs — then its description and the README of the one folder it names (naming none or several, the README in the folder compass keeps it in), the widest part of the page, and at its right its charts: its issues in each lane and filed and done a week at a time and the six newest, its notes in each notebook — those its Notebooks page offers, and those in none — written a week at a time and the six newest, and the languages its code is written in. A chart reads out what is under the pointer, and the icon at a card's corner opens its page — the Workspace, the Notebooks page — in a tab. A lane's name under its bar opens the Workspace on the issues in that lane, and a notebook's name the Notebooks page on that notebook. Its properties — its Location, the domain it is in, its README, its services and a top domain's colour — drop down from its kind beside its name (“domain ▾”), with Edit at their head: its name, and a top domain's colour, changed there. With no description and no README they are in its reading column instead, and Create README.md at the column's top right makes one — in its one folder, else in its own. Edit, at the top right of its reading column, opens its README — the one its properties name — in the editor, as a folder's page does; where it has none, Create README.md makes one.
- The ⋯ at the right-hand end of that toolbar holds the toolbar's icons when it is too narrow to show them all — the last of them move into it first — and a service's own actions: Edit service, Move service, and Browse source to launch your IDE. A domain has none of its own, so its ⋯ is there only while an icon is in it.
- The ▾ at the right of the tabs beside the files lists every tab open there, each with its mark — a page's, or its file's type — to go to it or close it (×), with Close others and Close all over them. A tab's × there, Close others and Close all ask first; Close immediately closes them without asking (a file with unsaved changes is always asked about), and Hide tab line puts the tabs away, the ▾ staying to switch between them and to bring them back. The Inspector's own tab bar has the same ▾.
- Under the editor, the Actions panel holds a Terminal, Output, Problems and the Outline. ▶ at its top builds the service, in whatever language its folder says, and runs a Rust service; the build it uses is set in Policy ▸ Run & build.
- AI, on the file's bar before Slots, opens the file's chat as a slide-over, as an issue's Work is — down the right of the window, under that bar — the other file of a split has its own. Each file has its own chat: open another file and AI opens that file's, and with the chat up it follows the file the editor shows. It is laid out as the Work is: its header says File chat — a ▾ on it once two or more files or functions have chats, listing them, each with where it is, to show another — then the file's name, a link that brings the file up in its tab; Maximize or Collapse, and its ⋯ (Refresh chat, its prompt — Open the prompt shows the one picked — where it opens, the AI it runs on, about the chat); then the conversation — one, with no tabs — and the box at its foot. Filter, the funnel before Maximize, finds your way in it by date, person or chat, ‹ › stepping from one to the next. Refresh chat starts again in the same conversation: a line goes across where it does, and what you ask after it goes without anything said above it. Until a chat's first message, Prompt over the box picks one of the level's File chat prompts, or None; beside it, on the same line, Primed: file says what goes with every question — the file's contents, as it is when the question goes. Where it opens, its ⋯ says, as the Work's does — Left, Right or Middle of the window, or Collapsed: a small window over the status bar's chat, the latest answer and the box, that stays up while you work elsewhere (Maximize opens the whole conversation from it). A file's chat and a function's are two slide-overs, each with its own place on the status bar after the issue — the file chat last up, a file's mark, and the function chat last up, a function's mark — and its name; pressed, it opens that chat again where its ⋯ says. Each keeps its own Position, and the two can be up at once, side by side. Every slide-over — this, a function's chat, the Work and the Research — is one width, and the chat stands beside a Work or a Research card that is up: drag the edge on the page's side to make them wider or narrower — half the window at the most — and double-click it for the width they start at. While the chat is put away, AI carries a dot — the accent while it answers, green once it has, red if it could not — and so does the file's tab, at its top right, while the file is not on screen; opening the chat clears it. AI again, ×, Escape or a press outside put it away — the small window only ×.
Search & focus
The search box finds services, workers, domains and folders, functions, issues and the words in the files of the scope — each kind under a line of its own. It searches only once there is a scope — the service, domain or folder selected in the Explorer — and the empty box names it (“Search payments…”). Until then it searches nothing and says where one is chosen: Select a scope in the Explorer to search.
The scope at the box's right end says where search looks and where new work is filed; a press opens the composer on it — an issue, or a note from its “Issue into …”. With no scope it is not there.
Its chip at the left (or the : key) picks what the box does: Search, or Viewer Search, which opens a service, domain or subdomain in the Viewer and is chosen for you while the Viewer is on screen.
See the Explorer's own help for the full list.
Topology
The Topology tab shows this level's code in two views — Tree and Map — built from the code and from the slots marked in it with compass:slot, and each function's card: its code, what calls it and what it calls, and a parameter traced through it. Use All or Slots only to choose what the views show.
For details, see the Topology help card on the tab, or in Tools ▸ Help.
Labels
One set of labels for every issue, task and note, defined on the Policy page's Workspace tab (Tools ▸ Global Policy for the whole workspace); renaming or deleting one reaches every task and note carrying it. There, a label made, renamed, recoloured or deleted waits for the page's Save like every change on it — lit unsaved until then, one deleted a struck line — and Cancel puts it back.
Put labels on an issue from its chips or its ⋯, and narrow the list by them with Filter.
A label can carry an issue template (Policy ▸ Workspace ▸ Issues and work): on a new issue it is written into an empty description, and on an issue that exists it is offered under what the issue says — and a note template (Policy ▸ Workspace ▸ Notes), the same for a note's words. It can pick a work prompt or a research prompt too: an issue or a note carrying it starts its chats from that prompt, until its Initial prompt picks another. Renaming the label renames it in the templates and the prompts too, and deleting it takes it off.
A goal can give labels to every issue made in it, and a notebook to every note written into it (their Configure cards). On the Policy page each label says the level it was created from, and under its name the goals and notebooks that give it and the templates and prompts it brings (one switched off says so) — a press on one opens it: the goal's project, the Notebooks page on the notebook, the template's or the prompt's card.
Policy per service
The Policy icon on the file tree's toolbar opens this level's policy as a tab: one page — AI, Run & build, Templates, Git and Workspace, one after another, each under its name — its tabs along the top going to each, the one you are reading lit as it scrolls, and Edit after them. On a wide screen the page keeps to one column, every section's buttons ending on one line, whether it is read or edited.
Every field resolves global → each domain and subdomain → service — for a folder of the Explorer, global → the domain it is in and every domain above it → its folders; each section says whether it is inherited or set here, and a change here overrides just this level.
Notes
The Notebooks page holds a level's notes — those written on it and on every level under it: the notebook on a file tree's toolbar, before Workspace, opens it as a tab for the item the Explorer is showing, as Workspace does. Its head has, from the left, List and Board — the view is kept — the notebook it reads, Filter, and at its right New note.
Notebooks gather notes. A notebook is a level's — a domain's, a subdomain's, the workspace's — made on its Notebooks page and offered there and on every level under it, and a note is put in a notebook of its own level or of one above it. A note is in one notebook or in none, and the notes under it are in its notebook with it. The notebook press drops down All notebooks, the level's own notebooks, then those of each level above it under its name — each with how many of the level's notes are in it — and No notebook: the one picked is the one the page reads. Those who make notebooks find New notebook… there too, and Rename, Configure and Delete for the one picked. Notebooks are made, renamed and deleted by those who write on the whole workspace.
Filter is the Workspace's panel of three columns: Group by — No grouping, Notebook, Labels (a note with two labels is under both), Subdomain or Service; Order by — last updated, created date, oldest first or title; and Filter by — Labels, flying its values out beside it: a note with any of those picked is shown, and the Filter press says how many it is narrowed by. List draws a group each — each note a row, its sub-notes under it, folded by its chevron; Board draws a column each, the notes in none first, each note a card with how many notes are under it; with no grouping, a list of rows and a grid of cards. Grouped by notebook, a card dragged to another column puts it, and every note under it, in that notebook, and a column's + writes a note into it; a notebook's ⋯ renames it, configures it — its name and its labels — moves it along its level's order or deletes it — its notes are kept, in no notebook. A notebook's labels go on every note written into it — a sub-note too — beside the note's own: a note from its + shows them on the card, where they can be taken off, and the note template one of them goes with is written into its empty words. A note moved into it later keeps the labels it has. Every note, a row or a card, has a ⋯ of its own — the menu its page's ⋯ opens, described below: Copy ID, Notebook, Labels, Link an issue…, New sub-note…, Move a note here…, Research — a switch — and Delete.
New note opens the composer as a Note, on the page's level and into the notebook it reads, and a notebook's + writes one into that notebook. The composer's “Note into …” or “Issue into …” at its top right says which it is and, pressed, turns one into the other; the scope at the search box's right end opens the composer too. A note is a title and words in markdown, with labels if you like — a label's note template is written into its empty words — kept on the level the composer is on: Enter starts a new line, and Ctrl+Enter adds it.
A note opens on a page of its own, in one Note tab. Drag it onto the Notebooks tab to read the list and the note side by side: a note pressed in its list or on its board opens in the Note half, the Notebooks page staying where it is; and with a note's page beside another page, Notebooks opens in that other page's half. The notebook at the far left goes back to the Notebooks page, the note lit there — its Level property opens the level it is written on — and ‹ › step back and forward through the notes you have opened. Its title runs the width of the page, and at its end are Research, Edit and ⋯ — Contents and Two columns are first in its ⋯. Under its title, in the room the formatting bar takes while you write, its properties run along a line — their values, not their names, going on to a second line when there are more: its level, the note it is under, its notebook — pressed, it puts the note and the notes under it in another of its level's or a level's above it, or in none; a sub-note's is its family's — its labels, who wrote it and when, and when it last changed. Its labels are the issues' own, from its level's set: + drops them down to tick, and a label pressed is taken off, asked first. A label that carries a note template offers it under the note's words, as on an issue. Two columns, in its ⋯ — a switch, on or off, not there while you write — reads the note in two columns as pages: the words fill one column, top to bottom, before they go on into the next (a short note keeps to the first), two to a page (one where the page is narrow), with ‹ ›, and the page it is on, under them; ← →, Page Up, Page Down and the wheel turn them too, and they are split again when the window changes size. While it is written with Two columns on, a dashed line across the box, Page 2 at its end, shows where each new page would start. Two columns keep the right, their pages set beside it, with no rule between the columns; a narrow page has no right. Its name, beside ‹ ›, drops its properties down with their names — while you write too. Contents, in its ⋯ when the note has two headings or more, drops down its outline, as an Overview's does: each heading a press that goes to it — its line while you write, its page in two columns. Down its right, as down an issue's: its Properties, folded until its heading is pressed — its ID, its level, its labels and who wrote it; its Linked issues — each opening on its page, its × unlinking it, asked first, and Link issue finding another; its Diagrams — the Topology maps linked to it, below; then its Sub-notes, as an issue's page has its Sub-issues: the heading folds them away (your browser keeps each heading's way), how many are straight under it — or None — and Add sub-note to write one under this one (its title, then Enter); then every note under it, a level a step in, each opening its page when pressed, and its ⋯ — the menu every note has, with Move it out on one straight under this one: a note of its own on its level. Drag the line between the words and the right to widen or narrow it, up to a third of the page — your browser keeps the width, an issue's page's right the same — and double-click it to put it back. The words keep their room first: the right narrows as the page does, then a narrow page has none, its linked issues and sub-notes in ⋯. Edit, Enter or a double-click writes in it where it stands — the title, its presses and the words stay where they were — with the issue's formatting bar in the room under the title; / at the start of a line puts in a heading, a list, a checklist, a quote, a code block, a divider, a figure, a link or today's date, and a link pasted over words makes them a link. Alt+↑ ↓ moves the line, or the lines picked, up or down. What you write is saved as you write it, and kept on this device until it is — offered back if the app closed first. A save after someone else changed the note is held, and the page asks whether to keep yours or use theirs. A checklist's boxes tick on the page. Its ⋯ is the menu every note has — on its page, a row's or a card's on the Notebooks page, and a card's in the team chat alike: Copy ID — the note's ID, an n and its first eight characters beside it, as an issue's is shown with an i; chosen, the whole id is copied, its n with it — then, a writer's, Notebook (the notebooks it may be in, flown out beside it; a sub-note's is its family's), Labels (its level's, to tick, in a panel that stays while you tick), Link an issue… and New sub-note…, each with how many it has, Move a note here… — a note already written put under this one — Research, a switch: off, the page has no Research press and no research is started on the note, the chats it had kept — and Delete, asked first, the notes under it with it — and, while you write, Undo everything since you started writing before it.
Diagrams: a note links Topology maps — live, never a picture. Add diagram, in its side panel's Diagrams, finds a scope that has a map — a domain, a service, or a folder or a project of the code map — as you type its name or its path (nothing is listed before you do), and links it on the branch checked out: from then on it is drawn from that branch, whatever is checked out, so it stays that branch's map as its code changes. Every linked diagram is drawn on the note, under its words, where it can be dragged and zoomed — All or Slots only, as the Topology draws a map: everything in the code, or only what its slots say. Which is picked in Add diagram, at its top right, before the scope — All unless you press Slots only — and kept with the diagram; its head says Slots only while it is. At its head's right end, ⤢ opens its map large, right there over the page, and ⋯ opens it in the Viewer or in the Topology (the scope's Topology tab, which shows the code checked out), switches Slots only on or off, draws it from another branch, or removes it. In the side panel each has its name — which takes you to it on the note — ⑂ its branch and how it stands, its ⋯ and ×, which takes it off the note, asked first. A diagram whose branch has been deleted — a dead link — or whose folder is not on its branch says so, in red or amber, with Pick a branch to draw it from another; the branch picked is checked before it is saved, and how many need fixing is said beside Diagrams. Maps are added to notes alone: they no longer go into an issue's work prompt.
Colour, in a note's formatting bar: Highlight and Underline each put the colour shown under them on what is picked — eight colours in each ▾, the one picked kept for the next press — and Ctrl+Shift+H and Ctrl+U do the same; pressed again on what is that colour, it comes off. Nothing picked, they take the word at the caret — or a heading's words, so a title or a subtitle is one press. The highlight's ▾ also puts a whole block in a box of a colour — the paragraph, or the lines picked — and /box starts an empty one. In the markdown they are [words]{.hl-green}, [words]{.ul-blue} and ::: hl-purple … :::; ==words== is a yellow highlight too.
Figures: a note's formatting bar has Image, and /image does the same — a card for a picture: one chosen from this computer, pasted, or dropped on it, or a link to one; a picture pasted or dropped into the note's box opens it too. A picture is kept with the note — a PNG, JPEG, GIF or WebP, made smaller first when it is large — and a link's is drawn from where it is. Its Figure description is set under it as Figure 1: and the words, the figures numbered in order. Add figure puts it where the cursor is, in its column, read in one column or two. With the cursor on a figure's line the card is that figure's, and Update figure writes it back. In the markdown it is  on a line of its own.
A picture pressed where the note is read opens bigger, over the app, in the viewer a plan's diagrams open in, named as it is under it: drag it to move about, scroll to zoom where the pointer is, or −, + and Fit at its bottom right — +, - and 0 do the same; Esc, × or a press outside it closes it.
A note's words are read and written at the size Note text sets in Settings ▸ Text size and wrapping — 13px until you step it, from 10 to 22px; its headings, code and tables grow with it.
Research, beside Edit — while it is switched on in the note's ⋯, as every note starts — opens a slide-over like an issue's Work, expanded, down the right of the window: chats with the level's AI about the note, each started from the Research prompt set in Policy ▸ Workspace ▸ Notes, filled in for the note, with what you type first. Its chats are one conversation, one after the other: its ⋯ starts with the note's id — chosen, it is copied — then Refresh chat, which starts another in it, a line across where it does, then that Initial prompt, then where it opens. It can be up beside an issue's Work; where both would stand in one place, they stand side by side. The note whose Research you opened last stands on the status bar, before the issue checked out — its mark and its id — and pressed, it opens its Research again. With research on more than one note, the card's Research ▾ drops them down — each its id and its name — and one pressed opens its research there.
An issue links to notes from its side panel's Linked notes, and a note to issues from its own Linked issues: Link note or Link issue finds one — Link note lists the ten newest notes, and words typed find any other — a name opens its page, and its × unlinks it, asking first. A note's ⋯ ▸ Link an issue… puts up the picker hung from it: the issues on its level, newest first, and any issue by its title or its id as you type — the ones it links to ticked; a tick links one, and taking it off unlinks it.
A note holds sub-notes. Its ⋯ ▸ New sub-note… drops down the notes written under it — each opening on its page, its × moving it out to stand on its own — with the box for a new one's title under them, ready: type it and press Enter, and it is written under this note and its page opens to write in. Move a note here…, in its ⋯ and at the foot of that dropdown, puts another note of the level under it: the picker hung from it lists the level's notes — not this one, nor those over it — and finds them by their words as you type; one ticked goes under this note, and its tick taken off moves it out again. A sub-note is on its parent's level, and in its parent's notebook; its header names the note it is under, a press back to it, and the Notebooks page's list draws it under its note. Deleting a note deletes the notes under it.
Editor
Browse and edit the files of whatever you have open in the Inspector.
- The tree follows the open item: a service shows its own files, a domain or subdomain everything underneath it.
- Files open READ-ONLY. Press Edit to start a session; Cancel discards it, Esc or jj leaves it keeping what you typed.
- Issues and their runs live on the Workspace tab — the Workspace icon on the file tree's toolbar, or space t.
- Browse source, in the ⋯ at the right-hand end of the file tree's toolbar, opens the service here.
- Modal keys: the read-only preview is NORMAL mode — j/k/h/l (or the arrows) and w/b move the caret, i starts editing, jj or Esc leaves it, u undoes and
:wsaves. - ff finds a file in this tree, fw finds text in the open file, and space + a letter opens (and closes) a tab of the Actions panel — all of which work before any file is open.
Keyboard: moving around
The preview is normal mode — the status bar shows NORMAL, INSERT or VISUAL.
j/kmove a line down / up,h/la characterw/b/emove a word forward / back / to its end0and$go to the start and end of the line,^to the first non-blankgggoes to the top of the file andGto the bottom
The arrow keys move the caret too, and a block cursor appears while you navigate by keyboard (it hides again the moment you use the mouse).
Keyboard: moving through code
{and}jump to the previous / next blank line, i.e. block by block%jumps to the bracket matching the one at the caretH/M/Lgo to the top / middle / bottom line of what is on screen, andzzre-centres the current lineCtrl+d/Ctrl+umove half a screengdjumps to the definition of the word under the caret,*searches for it, andn/Nstep through the matchesuundoes andCtrl+rredoes, from the preview — leaving insert withEsckeeps what you typed, so undo is how you take it back
: opens a command line: :w writes the file and a line number (:42) jumps to that line; Esc cancels it.
Keyboard: editing
i starts editing at the caret; a after it, I at the first non-blank, A at end of line, o / O on a new line below / above.
Esc or jj returns to the preview and keeps what you typed (the Edit button's Cancel is the one that discards). Save with Ctrl+S as usual.
Keyboard: changing text
From the preview:
xdeletes a character anddda lineyycopies a line, andp/Ppaste after / before the caretDdeletes to the end of the line, andCdoes the same and starts editingJjoins the next line on, andrreplaces one charactervandVselect by character or by whole lines
Copies and pastes go through the system clipboard, so Ctrl+V works here too.
Keyboard: searching
ff opens the file-name filter for this tree (the same box the magnifier on the tree's top row opens). The first match is pre-selected, so ff + a few characters + Enter opens it; ↓ / ↑ or Ctrl+n / Ctrl+p walk the matches, and Esc closes without opening anything.
fw opens find-in-file, the same bar as Ctrl+F: Enter steps to the next match, Shift+Enter the previous, and n / N do the same from the editor.
Search and replace, as in Neovim
/then a pattern andEntersearches forward from the caret,?backward, round the end of the file. Every match is lit as you type;Escgives up and puts back what was lit before.ngoes to the next match the way the search went,Nthe other way. An empty pattern searches for the last one again.:s/old/new/replaces the first match on the caret's line; addgfor every match on it.:%s/old/new/greplaces in the whole file,:5,20s/…in those lines, and:from a visual selection fills in:'<,'>for the lines it held.- After the last
/:gevery match on a line,iignore case,Ikeep case,ncount the matches without changing anything. - In the replacement,
&or\0is what matched and\1–\9its groups;\rstarts a new line;\uand\lchange the next letter's case,\Uand\La run, until\E. - Patterns are Vim's:
\<and\>are word edges,\(…\)a group,\|or,\+one or more,\{2,4}a count; start with\vto write a regular expression as JavaScript does. A pattern with no capitals ignores case;\Ckeeps it. :&repeats the last replacement on the caret's line (:&&with its flags),:nohclears what is lit, anduundoes a whole replacement at once.
A replacement edits the file as x or dd does: the tab shows it is changed, and :w saves it.
Keyboard: the space leader
space then a letter opens a tab of the Actions panel without reaching for the mouse:
t— Workspace (the issues and AI tasks)o— Outlinep— Problemsc— Topology (this level's marked slots, as a tree or a map)u— Output
Pressing the same pair again closes the panel, so one key both opens and dismisses the thing it names. (The Terminal has no leader key on purpose: it is the tab you want to keep typing into.)
Two keys act on the panel itself rather than picking a tab: space a hides or restores it, and space space moves it between the bottom and the side. A half-typed sequence is echoed at the bottom-right of the code area and times out on its own.
Language servers
Hover a name for its type and docs, with Go to definition and Find references under it; F12 jumps to the definition from the keyboard.
compass finds a language server for each file by itself. Settings ▸ Intellisense lists the ones running and, with Find servers, every one on this machine; Use chooses another for the files it serves.
Topology
See how this level's code fits together — which functions call each other, and which events pass between services. Topology builds its views from your code and from the slots you mark in it.
- Choose a view with Tree or Map at the right end of the header. Topology opens on Map and remembers the view you last used. A function's card counts what calls it and what it calls, and traces a parameter through its code.
- Choose All to show all of the code, or Slots only to show only what you marked with
compass:slot. - Click a function to open its card, pinned down the right side, which shows its code and lets you add a slot to any line. Over its code is its file — click it to open the file beside the map.
- A map is linked on a note — its side panel's Diagrams — and drawn there live, from its branch.
- To reverse a slot change, press
Ctrl+Z;Ctrl+Shift+Zputs it back. - When a scan stops at its file limit, a note under the header says so. Its × closes it, and the header then says partial — press that to bring the note back.
- To open Topology, click the Topology icon in a service's or domain's file-tree toolbar, or press
space cto open it in the Actions panel.
Tree view
The Tree view lists each file's functions with their line numbers and signatures. A dot next to a function marks each slot it contains; hover over a dot to see the slot's details.
- Expand or collapse: every row starts collapsed — a domain's, a service's, a folder's at any depth, a file's — and opens one level at a time: click anywhere on its row, or its ▸ or ▾. What you opened inside a row is open again when you open the row again. Long lists end with a Show N more button. Drawn again — a service's functions arriving, rows opening above — the tree stays on the row you were reading.
- Search: the magnifier in the header searches the function names and file paths — click it for a field, type, and
Escapeempties it and puts it away. The tree follows once you pause typing, and shows the first 150 functions a search finds in a service, their folders and files open, then Show N more for the rest; a row you fold while searching stays folded for that search alone. - Filter: beside the search, the funnel — Filter on a service's tab — opens the same panel the Workspace's Filter is, in three columns. Group by: Folder (folders, their files, each file's functions — the default), File (every file at the top, each with its functions), No grouping (one list) or Complexity table (below). Order by: Position in its file (the default) or Name A → Z — and with the table, its columns. Filter by: Slots (All functions or Slots only — the header's switch) and Show (below), each opening its values beside the panel. At its foot, ↺ clears the search and puts the folders back in each file's order, and Done closes it. A chip beside the funnel says what is applied — “N of M”, “By file · Name A → Z”; click its × to clear it.
- Several services: on a tab with more than one service, the header's search and funnel — All services — set the search, the grouping, the order and what it shows on every service together. The services' rows have no filter of their own, and show what that funnel says: an option ticked under Show shows on every service, one not ticked on none — whatever a service's own tab shows. While searching, each row says how many of its functions match; the services with a match open in turn until 150 matching functions are showing, and the rest fold, each saying how many match — click one to open it, or to fold one that is open. The services with no match fold, saying nothing matches; the header's chip counts the matches across them all.
- Show, under Filter by, has three options, each off until you tick it: Complexity (Cx %) — each function's Cx number at its row's right, coloured as it rates (the number on its card's meter), and each file's, rolled up from its functions': their numbers weighted by how long each is. A file's tip names its most complex function; File length (lines) — how many lines each file has; and Function length (lines) — how many lines each function runs to, from its header to its end.
- Complexity table, under Group by — in place of the service's folders, its Cx meter in the style of
htop(how much of its code is in functions that are hard to follow; point at it for how many of its functions rate high, moderate and low) and its functions as a table: CC (complexity), NEST, IN (how many of the service's functions call it), OUT (how many it calls) and FUNCTION — each written out as its file declares it, in the editor's colours — the hardest first. With Complexity (Cx %), Function length or File length ticked too, each is a column of its own: CX%, LINES, and FILE (its file and, after a bullet, how many lines it has — sorted by that). Click a column's head to sort by it — a count the most first, a name from A — and click it again for the other way round; its arrow says which. While it shows, Order by offers the same columns. Click a function for its card; the ? at the right end of the column heads says what each column counts. The table starts at the pane's left edge, its FUNCTION column on the editor's ground; as the pane narrows, FILE gives way first — narrowing, then gone, its head with it — then LINES, then the counts move closer together, and the function's column only after them. On a tab of several services, each service's row has its meter at its right end, and opened, its table, the meter not repeated over it. - Other findings: below the functions are slots that sit outside any function, and anything the scan reported. Click an item to open the file at that line.
The header shows how many problems (slots the diagram can't draw as written) and warnings (slots drawn differently from how they read) there are. Click ? in the header to learn how to mark a function.
Map view
The Map view draws the scope as a diagram. Each service that has slots is a frame labeled with its domain, its name after the Explorer's cube (a domain's frame wears its stack), and its marked functions are cards inside it — each function's name in the editor's colours, its file under it and its slots as chips. Solid lines are calls and dotted lines are events, their subject after a bolt; the client and services outside the scope appear at the edges.
With All selected, the map also shows unmarked functions that call or are called by others, with dashed borders. Each service shows up to 60 functions — use the Tree view to see the rest.
- Move and zoom: drag to move and scroll to zoom. Double-click empty space to see the whole map. You can also use the
+,-and0keys, and the arrow keys. Open a project or a folder on it and it stays where it is on the screen: the map is laid out again around it, and again as what it holds is read, without moving off what you were looking at — it is fitted again only when you ask (double-click,0). - Follow connections: hover over a box to highlight its lines. A project or a folder you click stays lit — edged in the accent, its lines lit — until what it opens has been read and drawn; meanwhile pointing at another box lights nothing, so you keep sight of the one you clicked.
- Find on the map: click the magnifier, beside the branch's name, and type: a list shows what the map says that matches — a function, a service, a domain, a file. Click one, or press
Enteron it, to move the map to it; it flashes where it is. - Back and forward: ‹ and ›, first at the right of the header, go back and forward through where the function card has been, as the card's own do — and back from where it started closes the card. They are greyed while no card is open.
- A map on a note: a map is linked to a note — its side panel's Diagrams, Add diagram — and drawn there live, from the branch it was linked on; it is no longer added to an issue's work prompt.
- In the Viewer: the Viewer's mark on the file tree's toolbar, before Topology — Open in Viewer — opens this map as it is drawn — its scope, All or Slots only — in a pane of the Viewer, under Tools. It is the Map itself, not a picture of it: drag and zoom it there. A function's card opens here, on the Topology tab, not in the Viewer. Pressed again for the same map, it shows the pane already open.
Function cards
Click a function in the Tree or Map view to open its card, pinned as a panel down the view's right side. The card shows:
- its header, one row: at its left, where the card can go — ‹ and ›, to move between the functions you've visited (the functions alone: code they opened beside the map is no step of its own) — the number between them says how many steps back you are; click it for the list of them, in the order you went there — the first at the top — and click one to go back there: a function the trace was followed into is joined to the one it came from, over it, by a line down the list's left, a dot on each in the colour of the name there, and a line under it says what went in and as what (
↳ fx as self); each row's ×, at its right end, takes that place off the list — not the one the card is on — then In and Out — how many functions call it, and how many it calls — and beside them the trace's icon; at its right, what you can do with the function — its Cx score (Cx 34%) and the AI's diamond — its chat — and at the very end Expand and × - the function's code with line numbers — the comments written over it folded, a chevron in the gutter of its first line rolling them out (click it again to fold them) — click a line number to open the file at that line, or click a function's name to move the card to it (‹ brings you back), or another name — a type — to open where it is declared beside the map. The types its header takes and gives back are underlined with dots where the workspace defines them — the service's own, or another crate's its file brings in, by name or through a glob of one of its crate's own modules (
use crate::prelude::*) — and listed in the Types dropdown at the right of the row over the code, beside Find, each parameter with the type it is written with. Click one, in either place, to open its model in the card. Its head is laid out like the card's own — ‹ and ›, then </>, and at the right copy, word wrap, open and × — and the row under it says what the type is and, at its right where there is room for them, the file and line it is defined at. ‹ at the first type you opened in it closes the model. Then a table of each field and its type, in the order the type writes them — then each variant and what it carries, its consts and their values, and, under a line, its methods in the service — each written as its header declares it, its file and line at the right, as In and Out list theirs, scrolling with the rest of the model; click a method to move the card to it, and ‹ brings you back with the model open as you left it. There is one model at a time: open another type — from the code, or by clicking one in the model — and the model goes on to it, ‹ back to where it was. The ƒ icon in its head, with how many methods its service has for the type, lists them as In and Out list theirs — ordered by Name or File from the list's head. A type a macro writes says which and what it is made over —made by rustc_index::newtype_index! over u32— a trait lists its functions, each with what it takes and gives back (click one to move the card to it, or, with no body of its own, to see its line beside the map), and its types and their bounds, each table under a word saying what it lists; a unit struct says it holds nothing. The copy icon in the model's head copies its lines as written. Each type in the model that the workspace defines is underlined with dots too: click it to open its model in the same place (an alias's, the type it stands for), and ‹ and › at the left of the model's head go back towards the one you started from and on again (Alt+←andAlt+→); the number between them says how many types back it has gone — click it for the list of them, and click one to go there. The { } icon, right after ‹ and ›, shows its lines as written, with their comments; a type opened from the code always starts as the table. Long lines and long types always fold under themselves. The open icon in its head opens the type's file in the editor next to the Topology tab, at its definition — click it again to close it. The model sits beside the code whenever the card has room for both — about 100 columns of code and 40 of the model — and under it otherwise, and while the file it opened is next to the Topology tab; drag the line between them to share the room — the model as wide as five sixths of the card, the code then scrolling sideways. Picked from the dropdown, a parameter is traced too, as clicking its name does, and it and its type are said at the left of the row over the code, after its length (a parameter traced from the header is said there too); click a lane of a trace and that is the way the name comes to be instead — from the parameter, name by name, each with its type where it is known — and clicking a step opens its type. Click the open type again, its ×, or pressEscapeto put it away. A function of more than 10,000 lines shows its first 10,000, and a last row says how many are left — click it to open the file where they start - over the code, its file — its name alone — and how many lines the function has — an ⓘ after the file when it opens with a comment saying what it is — and at the right the Types dropdown, Find in the function, Copy the function and Word wrap, held there as a long function scrolls. Scrolled down a long function, a round ↑ at the bottom right of its code takes you back to its top
- each of its parameters, a click that traces it
- an AI chat, sliding over the panel
Click the file's name to open the file in the editor next to the Topology tab, with the function's line numbers highlighted in the gutter — the × at the top of the highlight clears it; click the name again to close the file. Opening another function replaces that file. Drag another tab onto the editor and it splits with the Topology, the file keeping a pane of its own beside the map. Click the ⓘ for the comment the file opens with, popped up right under it — its lines as the file has them, each with its line number in a gutter, as the card's code has them. A long one scrolls; click elsewhere, press Escape or click the ⓘ again to put it away.
Click the AI's diamond in the header to open the AI chat — a slide-over of its own, beside a file's chat when one is up, down the right of the window under the card's header, its width the file chat's and its own place on the status bar, after the file chat's. Click the icon again, its ×, or press Escape to put it away.
Its chat is a file chat's kind — one conversation, with no tabs: its ⋯ holds Refresh chat, which starts again in it — a line across where it does, and what you ask after it goes without anything said above it — then its prompt — Open the prompt shows the one picked — and About this chat; the function's name at its head is a link that opens the function's file in a tab of its own, at the function, its lines lit. Over its box, beside Prompt on one line, Primed: function says what goes with every question: the function's contents and, while calls is ticked, its calls in and out — what calls it and what it calls, each with its code; untick it to send the function's contents alone (the tick is one for every function's chat).
While the function's chat is waiting for an answer and the chat is put away, the AI's diamond carries a small dot in the accent colour. Once the answer lands, a green tick takes the dot's place until you open the chat again.
The chat sends the function's code with each question, and the functions that call it and that it calls, each with its code; the box says how many each way.
The chat icon, at the chat's top right, opens the whole conversation, sliding over from the right as an issue's work conversation does: every turn, and under each of your messages what went with it — each function's code a line of its own, opened by its chevron — with a box at its foot to answer it, laid out as an issue's Work is. A file's chat has the same.
Hover a name in the code for what its language server says; a spinner at the foot of the code shows it is being looked up.
The card is always pinned down the side. Drag the panel's edge to resize it — as far as the whole pane, the map under it. Expand — the arrows beside × in its header — spreads the card over the whole of the view, the map or the tree under it; click it again to put the card back down the side at a third of the view's width (never narrower than reads), the panel's width from then on until you drag its edge. It stays expanded as you go from function to function; closing the card puts it back.
The AI's diamond opens the function's chat as a slide-over on top of the panel, from its right edge and from just under the card's header to its foot: the whole conversation, as the chat icon at the chat's top right opens it. The panel keeps all its width, and its header stays in reach.
Clicks in the panel leave the slide-over open, and ‹ or › takes it to the next function's chat with the panel. Click the slide-over's ×, press Escape, or click anywhere else to put it away; closing the card closes it too.
To close the card, click ×, press Escape, or click an empty part of the view. Escape puts away one thing at a time: a list or the breakdown popped up from the header, then a name held in the trace, then a parameter's trace, then the card. Typed in the chat, or with the chat sliding over the map, it puts the chat away first.
What calls it, and what it calls
At the left of the header, after ‹ and ›, In counts the service's functions that call this one, and Out the functions it calls — In 3, Out 36 — one step each way, each function once. Click either for a list of them: each written as its header declares it — pub fn, def, function or whatever its language says, then its owner, its name and what it takes — its file and line at the right.
The buttons at the top of the list order it: Name, by the function's name, and File, by its file's — A to Z, then Z to A when you click it again, the lit one's arrow saying which — and, on the list of what it calls, Order: the order it first calls them, the last first when clicked again. What calls it starts by name, and what it calls in its order; each list keeps the order you pick from function to function.
Click one, or step to it with the arrow keys and press Enter, to move the card to it; ‹ brings you back. The file and line at a row's right say where the call is, and clicking them shows it without moving the card: in Out, the line of this function that makes the call, lit in its code; in In, the caller's line, opened beside the map. While the card goes somewhere it has to read first — a function, a trace, a definition, a type — a small spinner rides beside the pointer until it has landed. A count of 0 is greyed. Click In or Out again, click anywhere else or press Escape to put the list away.
Tracing a parameter
Click the trace's icon — a route between two dots, beside Out in the header — and the function's parameters light up in its header, where it declares them, and every place one of them — or a name made from one — is handed to another of the service's functions has its out icon already: click one to trace that parameter and follow it into that function (where several go into one call, pick which). Click one to trace it (each parameter's name has a dotted underline, and a click on it traces it even with the icon off) — the code stays where it is, the lanes running down from the header. Every place the function uses the value is highlighted, as a marker pen marks a word: the parameter, and every name the value goes by after it — let simple = call_simple_intrinsic(self, name, args), a match arm, a field taken out — each name its own colour, the parameter's violet, so where the value changes hands, the colour changes (with more names side by side than there are colours, a colour comes round again only on a lane well apart from the other). The gutter widens to draw each name as a lane, the way a git graph draws its branches: a line in the name's colour between the line numbers and the code, from where the name is bound — a ring, on the parameter's own line where the header runs over several — down to the last line it is used on, with a dot on each line it is used on. Where a name is bound from another, the two lanes are joined across that line, so you can follow the value from the parameter down to where each of its names ends. A lane is taken by the next name once its own is done, and a trace of many names has narrower lanes. Point at a highlight, a lane, a dot or an out icon and that name alone — an out icon's names — is highlighted in the code — its uses deeper and edged in its colour, every other name's highlights put away — its lane lit and the others dimmed. Click a lane (or its dot, ring or join) to keep it so as you move on: the name stays lit until you click anywhere else — that lane again lets it go, another lane holds that one instead — or press Escape; the tip of a highlight says what it is there — read, handed to a call, put into another owner, given back.
Where the value is handed to another of the service's functions, an out icon sits right after the call — cx.declare_fn(sym, fn_abi)↳ — one to a call, however many of its names go into it (as arguments, or as what it is called on), all of them one colour; point at it to light the names it hands in, and its tip names the function and the parameter each lands in. Click it to move the card into that function, the value traced on there as that parameter, in its next colour — where several names go into the one call, click it for a list of them and pick the one to follow. ‹ brings you back to the trace as it was. Click the parameter again to let the trace go, its parameters still lit; click the trace's icon again or press Escape to put it all away.
A name bound again ends what it held: let x = other is not the parameter, and a closure's own parameter is not either. A condition that only decides between values is not where they come from — nor is what a match or an if decides by: a let of a match, an if or a block holds what its arms, its branches or its last line give — of a labeled block or a loop, what its breaks give — and an arm that returns, breaks or continues gives it nothing. What a method of another value gives back is that value's: map.get(&k) and locks.entry(p.to_owned()) find something by it — the entry, its state — not a part of it; the copy handed in goes into the map.
The trace is read from the code in every language compass reads — statements, calls and struct literals over several lines too — and follows calls as the call graph does.
The function's checks
In the header, its Cx score — Cx 34% — rates the function by three checks, a third each:
- Complexity — its cyclomatic complexity: how many paths run through it. One, and one more for each place it decides — each
if, loop,caseor match arm,catch,&&,||,??and ternary?. Green up to 10, amber up to 20, red past that - Nesting — how deep its control goes: one level for each
if, loop,switchortryinside another. Green up to 3, amber up to 5, red past that - Fan — how many of the service's functions call it, and how many it calls: the functions one call away, counted at the header's left
The number is how far along the three checks' scales the function is, out of 100, in one colour whatever it is — the breakdown says how each check rates.
Click it for the breakdown, popped up under it: a section for each check, each with its own htop meter — its bar as wide as the pop-up, its number at the bar's end, and how it rates beside it. The fan's number is its callers over its callees, in their two colours.
Under each meter is what made it: each kind of decision with its count and the lines it is on — click a line to see it in the file — where the nesting is deepest, and the functions that call it and that it calls, by class or file. Click one of those to move the card to it.
The breakdown's ? pops up what each check counts. Click the Cx score again, the breakdown's ×, anywhere else, or press Escape to put it away.
Marking code with slots
A slot is a comment in your code that marks a point for Topology to draw. It has the form compass:slot ID kind=KIND seq=N and goes at the end of a line or on its own line above it. The diagrams are drawn only from these marks.
There are six kinds of slot:
- entry, publish and subscribe mark where a service meets the network
- step, call and branch mark points inside a service
To add a slot, click + next to a line on a function's card, or turn on Slots in a file's toolbar and click + next to any line. To change or remove a slot, click its dot or ×; you're asked to confirm before it's removed.
If the file is open for editing, the change goes into the editor and is saved when you save the file. Otherwise, it's written to the file immediately.
Undoing slot changes
You can undo the slot changes you make in Topology: press Ctrl+Z while the tab has focus, and Ctrl+Shift+Z or Ctrl+Y to redo one — each says what it undid or redid.
The changes are remembered until you reload the page.
All vs. Slots only
Use All and Slots only in the header to choose what both views show:
- All shows all of the code: every function.
- Slots only shows only what you've marked: the Tree and Map views hide unmarked functions and services without slots.
A function's card is always all of its code — what calls it and what it calls counted from all of the service — with its slots on it.
Slots only is a view you choose, not the full architecture, so some connections may be missing. Topology remembers your choice.
Workspace
Write down what needs doing, and have an agent do some of it. The same issues, read two ways — a list or a board.
- Everything you write is an ISSUE. An agent works on an issue from the issue's own page: its Work, handed the issue's work prompt, hangs off the issue.
- Create opens the composer: a title, a description, and chips for labels, priority, assignee, due date, parent and project. Add files it.
- LIST | BOARD switches how the same cards are drawn: List (sub-issues under their parents) or Board (a column per group, or the swim lanes). Grouping is in Filter, and the list opens grouped by Project; List grouped by Project draws each project as its goals, issues and sub-issues. A level's saved views are in the same toggle, after Board: one of List, Board and the view is lit, and List or Board leaves a view for the plain list or board. List and Board share one strip, the same at every width.
- Every card's ⋯ offers the same verbs wherever you find it — its lane, labels, priority, assignee, due date, parent, project and goal, where it is filed, and whether it has work of its own.
- A scope's swim lanes are POLICY — Tools ▸ Global Policy ▸ Workspace, or the Policy icon on a domain or service.
The issue page
Issues open in one tab beside the Workspace, Issue — its tip names the issue in it. Opening another puts it in the same tab, and ‹ › on the issue's header step back to the ones it showed before and forward again, as a browser's do. The Workspace keeps its list, board or project page as you left it.
An issue has its page, its Work — a slide-over — and its work prompt's page. Nothing starts on an issue that is archived or complete until it is moved out of the archive or reopened.
The work prompt, then the work
- The work prompt is what the work's agent is handed: the Work prompt Policy names, filled in for the issue, with what was asked of the work and what was added from the Topology tab. Initial prompt, above the box of a chat not started yet or in the Work slide-over's ⋯, picks which of the level's work prompts it is, and its Open it shows the prompt as text in a card, to change for this issue alone — Save keeps it as the issue's; the level's prompt stays as it is.
- The Work box's first send starts the work, handed the work prompt as it stands — what you type is optional, and goes with it.
The header
The issue and its work prompt's page each have the same header: the Workspace's mark, ‹ ›, the issue's status circle and its name (cut short with … when it is long — the whole name is in its tip), then the page's name. The Workspace's mark at the far left takes you back to the Workspace; the issue's tab stays open. ‹ and › step through the open issues' tabs, in their order, and past either end go round to the other. Drag an issue's tab onto the Workspace's to read the list and the issue side by side, a press on a row or a board's card opening it there — the Workspace stays where it is. With an issue's page beside another page, the Workspace — its press on the file tree's toolbar, or the mark at the far left of the issue's header — opens in that other page's half. (Where an issue opens in place — in the Inspector's Actions panel — ← goes back to the list.)
Its page
The issue's page is drawn as a note's: its title and its words down the middle of the page, no wider than a note's. At the end of its title are Work (once its branch is checked out), Edit — Save and Cancel in its place while the title and the words are written — the issue's ⋯, which starts with Copy ID, the issue's id beside it, and after ⋯, until its work can start, Start Issue — Check out branch once its branch is made and the checkout is on another, and while its project or its goal has not started, the press that opens the project.
Start Issue
Start Issue asks first: the branch's name, and the branch it is cut from (its parent's line as it is now, or any other — the box's ▾ lists the branches Version Control has, local then remote, and typing narrows them), both yours to change; then Create branch makes the branch and pushes it to origin, nothing checked out, or Create branch and check out makes it and checks it out (unless there is uncommitted work or a run going) — the × at its top, or Escape, puts the question away with nothing made. A name that is taken, or a branch that is not there, is said in the question, to be put right. A branch cut from a line you chose stays on it. A project page's Start Issue asks the same.
The side panel
On the issue's work prompt's page, its top row carries what the end of the issue's title does on its own page — Start Issue or Check out branch, Work and the issue's ⋯ — and on either page, while the issue's branch is behind, the down-arrow Update branch icon. Under it, its Properties, folded until its heading is pressed — the rows its name's dropdown has; its Linked notes — each opening the note's page, its × unlinking it, asked first, and Link note finding another; then its Sub-issues — each with its swim lane, pressed to move that sub-issue. The side panel is a third of the page; drag the line between the page and it to narrow it — a note's page keeps the same width — and double-click it to put it back.
Its properties
The issue's name in the header, with its ▾, drops down its Properties, as a note's name and a domain's kind do: first its id (an i and the first eight characters its branch is named by; pressed, the whole id is copied, its i with it — a note's starts with an n, and the team chat draws either as a card) and the branch its work is on; then who it is assigned to, its priority, project, goal, due date and labels, the issue it is under, where it lives and its lane — each pressed to change it, the dropdown staying up while you do. Beside the project's name and the goal's, ↗ opens the project's page — the goal's with that goal brought into view; the goal's name, pressed, opens it too. A press outside it, Escape, or its name again puts it away.
Work
Work — at the end of the issue's title, beside Edit, once the issue's branch is checked out — opens the Work slide-over over the issue's page, expanded, down the right of the window, whatever its ⋯ says; pressed again, or Escape, or a press outside it, puts it away. It holds the work's chats, Git's stats and the box that talks to its agent; collapsed, it is a small window over the status bar's issue instead — the Work help card says more.
A branch's name, pressed — on an issue, or on a project's page — slides out its history: whether it is checked out, how far ahead of and behind what it was cut from, its commits, and Open in Version Control.
Work has a help card of its own.
Overview issues
“Work” in a card's ⋯ decides whether an issue has work of its own. Without them it is an overview, finished when its sub-issues are.
Every issue starts with its work on — a top-level issue as much as a sub-issue; switch it off to make it an overview. Once its work has started, the switch stays on.
The board, and its lanes
The board's columns follow Group by, and the board is always grouped: No grouping is held there, and Lane stands in for it. Grouped by lane, they are the swim lanes in the order your workspace set them up. Grouped by anything else there is a column per value — A to Z, months in date order, priorities most urgent first, every subdomain or service in scope — after Unassigned, which holds every card with none. Cards follow Order by.
On a grouped board, drag a card onto a column to give it that value: a project (in its first goal), a label (the one it left goes), a priority, or a place. A month asks which day; Unassigned takes the value off. Each column's + creates an issue already in it. Unassigned is headed by a dashed ring rather than its name: its ⋯ has Add issue and how its cards are drawn — Simple, titles in a narrow column, or Expanded, the swim lanes' own cards in a column as wide as theirs — and its search ends in a funnel that orders and filters that column alone (Order by, Filter by), leaving the Workspace's own filter as it is.
On the swim lanes, drag a card to place it; a card you have never dragged follows its work. Hold the middle mouse button anywhere on the board — over a card too — and pull to slide it sideways. Lanes are whatever your workspace calls its columns, in whatever order suits it.
Press a card to open the issue; its open icon, at its bottom right, shows its properties in a small window instead, to change them there. Up to three windows stand down the board's right edge — a fourth closes the oldest. One dragged by its title bar stays put. Press the space between columns and drag to pan.
Issues and sub-issues
Open an issue and use Add sub-issue in its side panel, or “Sub-issue of…” in any card's ⋯. An agent's runs hang off the issue as its Work. Its Sub-issues heading counts them, done of all (“1/3”, green once all are), and a sub-issue's card on the Board starts with the sub-issue icon.
The List view draws the whole shape, every issue with sub-issues starting folded; each row carries its project, due date and lane — everything else is on the issue. On a row the title opens the issue (it underlines under the pointer); pressing anywhere else on a row with sub-issues folds or opens it.
Grouped by project
The list draws each project as its goals, a step in under the project's name, in the page's order — “Unassigned issues” last. Each goal has a dot the size of an issue's:
- a finished goal a green dot, its number before its name, folded
- the ordered goal up next a blue dot, and the ordered ones to come numbered after it (“2.”, “3.”)
- an unordered goal an empty dot (a blue ring once it is in progress)
- a dashed dot for work that needs a goal
An opened goal shows its issues folded, a step further in, as sub-issues sit under an issue. A group's heading folds when pressed anywhere but a project's name, which opens the project.
Filtering
Filter is one menu of three columns:
- Group by: lane, project (the default), due date, labels, priority, subdomain or service.
- Order by: project order (as the project's page orders its issues, newest first for the rest), due date, title A → Z, created date or last updated.
- Filter by: lane, project, label, priority and level — this level, the levels under it, and the levels above it (an issue filed there in no project) — each opening its values beside the menu.
The menu stays up while you pick. Done, at its foot, closes it, and ↺ beside it starts over and closes it too: with one of the level's saved views on, that view as it was saved, nothing else narrowing; with none on, every filter cleared.
Grouped by due date, each month that has something due is a heading with its days under it — soonest first, every past day marked Overdue in red, Today and Tomorrow said on it — and No due date last. Grouped by labels, an issue with two labels is under both.
A scope can keep saved views (Policy ▸ Workspace ▸ Views), each set with this same Filter panel: List or Board, its grouping, its order and its filters. Views made on a level reach every level under it — marked inherited there, and managed where they were made — and a level's own come after them. Its Workspace opens on the first. They are at the left of Filter's foot: its arrows step through the rest, each drawn in the columns above as it comes on, and the view's name between them — lit while the view is on, in italics once it is changed — puts it back after a change, as ↺ does. List or Board pressed while a view is on leaves it: the plain list or board, with no grouping, Project order and none of the view's filters; the view's name, unlit, puts it back.
Beside Filter, the strip says what is in effect — Grouping by, Ordering by and Filtering by, each only when it is in use — with a dot between each; press it to change them. Those words are never cut short: on a narrow pane they go onto another line, and the strip scrolls sideways only when even that is not enough.
Grouping is not a filter: nothing visible is left out. Completed work is always listed, and a run is part of its issue's row.
Where an issue is filed
On the scope you are on — the composer says which at its top right, the level's icon by its name (“Issue into main”); the ? in its corner says the directory it runs in and the lane it lands in.
An issue cannot be filed on the workspace as a whole: open a service, domain or subdomain first, which is what makes “do this here” mean something.
“Issue into main”, pressed — its mark or its words — turns the composer into a Note (“Note into main”, a note's mark), kept on that level rather than filed; pressed again, an issue. There is no × on the composer: Escape, or a press outside it, puts it away.
Loose, or tight in a project
An issue in no project is loose: as well as on the level it is filed on — and the levels above it, as every issue is — it is listed on every level under it: a subdomain lists its domain's, a service the domains it is in. Put in a project, it is tight: it is filed on the level the project was made on — moved there, its sub-issues and work with it — and listed there and on the levels above it only; one written into a project is filed there from the start. A project of the workspace moves nothing. Taken out of its project, it stays where it is, loose again. Filter ▸ Level narrows the list to this level's, the levels under it, or the levels above it.
Its Location — on its page, or Move location… in its ⋯ — moves it to any domain, subdomain, folder or service, its breakdown and work with it; its page stays open on it where it is now.
Work
Where an agent does the issue's work on its branch, handed the issue's work prompt — a slide-over on the issue's page, opened by its Work press once its branch is checked out, or from the status bar; at the page's right, left or middle, or collapsed to a small window over the status bar's issue.
- The Work press, at the end of the issue's title once its branch is checked out, opens the Work slide-over, expanded, down the right of the window: Git's stats — pressed, its version control beside the card — Maximize or Collapse, and a ⋯ — Refresh chat, Open in Version Control, its initial prompt, where it opens, deleting the last chat, and about the chats — and under them one conversation with the work's agent, every chat of it one after the other, and the box that talks to its agent.
- The work prompt is what the work's agent is handed: the Work prompt Policy names, filled in for the issue. Initial prompt, above the box until a chat's first message is sent and in the ⋯, picks it, and its Open it shows it as text to change for this issue alone.
- A chat's first send starts it; what you type is optional. After that the box replies to its agent. The ⋯'s Refresh chat starts another in the same conversation — a line across where it does — and the agent is not handed anything said above it.
- Git is the lines the checkout has added and taken away and not committed (a new file's lines among them), kept up to date while the agent works. Pressed, it drops down the branch's numbers — where it merges, its commits, what it has committed and what it has not — with Version Control at the top.
- Its ⋯ starts with the issue's id — chosen, it is copied — then Initial prompt, then where it opens — the Left, Right or Middle of the window, or Collapsed: a small window over the status bar's issue, the latest answer and the box, that stays up while you work elsewhere. Collapse, beside the ⋯, makes it the small window from then on; the small window's Maximize opens the whole conversation until Escape brings the small window back. × always closes it.
- The work runs on the issue's branch, so the checkout has to be there. Anything holding it is said in place of the box, beside the press that clears it.
The work prompt
What the work's agent is handed, kept as a document of the issue's: one of the Work prompts of Policy ▸ Workspace ▸ Issues and work, filled in for this issue — its title and words, and what was asked of the work — with the functions added from the Topology tab under its own Code heading (a map is linked on a note now).
- Initial prompt, above the box of a chat not started yet, is a dropdown: the level's work prompts that are switched on, the one it starts from ticked and named after it — “Initial prompt: Bug fix”. Picking another keeps it as the issue's, for its page and every chat — and what was written for the issue goes: an edit is for that one use, and the prompt picked, filled in again, takes its place. Nothing is asked.
- Open it, in that dropdown — and Initial prompt in the ⋯ of the Work slide-over's first row — shows the prompt as text in a card, to change if need be — its variables in a dropdown over the box, filled in when it is handed: Save keeps it as the issue's own, and the work is handed it as it was saved, with whatever you type in the Work box after it. The level's prompt in Policy stays as it is. Once a chat has started, it shows what that chat was handed instead. The work stays where it is.
- The issue's work prompt also has a page of its own (the activity's Work prompt on the issue's page), whose pencil writes it too.
Its file is a working file, not the repository's: it is never in Version Control's changes, and no commit or landing takes it.
Preview
The work prompt rendered. A flowchart in it — a map it holds from the Topology tab, or one written by hand — is drawn as a diagram, with Expand under it, and one brought from the Topology has Open too, which opens the map of its scope back on a Topology tab of its own. Each is whole, and no taller than a few inches, however big the diagram is; pressed (or Expand), it opens large to drag around and zoom (scroll, or − + and Fit at its bottom right), and Escape puts it away.
Each code snippet sits under a header that folds it away. A function from the Topology map has its service over its name and its file, as the map's function card does, with its language at the right.
Edit, and its formatting bar
The work prompt's markdown, in the editor an issue's description uses: line numbers in a gutter, highlighting, and the file editor's keys and undo, about 100 columns wide. Point at the gutter and a faint # appears at its top: press it to hide or show the line numbers.
Each diagram's Mermaid is folded to one line saying how many lines are hidden. The chevron beside it in the gutter — or a press on that line — opens it, and closes it again. Save always writes the whole work prompt; if it changed while you were editing, Save merges your edit into it — where you both changed the same lines, you are shown both to choose from.
The strip on top
It formats the selection or the line:
- H1, H2 and H3 — the same level again takes the heading off, another level changes it
- Bold, Italic, Strikethrough, Inline code and Link
- Bulleted, Numbered and Checklist
- Quote, Code block and Divider
Save and Cancel are at its right-hand end.
Keys (Ctrl or ⌘)
Bbold,Iitalic,Einline code,KlinkAlt+1,2,3a headingShift+Xstrikethrough,Shift+.a quoteShift+7,8,9a numbered, bulleted or checklist line
Enter at the end of a list item starts the next one, and Enter on an empty one ends the list. Ctrl+S or Ctrl/⌘+Enter saves and goes back to Preview; Escape is Cancel.
Starting the work
The Work box (“Anything the work should know? (optional)”) starts it: its first send hands the issue's work prompt — the issue's own, what you typed after it, or else the level's work prompt its Initial prompt picks, filled in with what you typed — to the AI set in Policy ▸ AI. Until then Initial prompt, above the box, picks which of the level's work prompts it starts from, and its Open it shows the prompt as text in a card, to change for this issue alone — Save keeps it; it goes once the chat has started. The slide-over stays where it is and shows the chat as soon as it is made; Initial prompt, in its ⋯, then shows what it was handed — the work brief, in a card hung from the ⋯.
What can hold it is said in place of the box:
- the issue is complete
- its goal is finished, or waits its turn
- the project or the goal has not been started
- the issue has no branch yet, or the checkout is on another branch
- the issue is an overview — its sub-issues have the work
Talking to the agent
Enter sends and Shift+Enter starts a new line. While the agent runs the box says so and waits; when it has finished, what you send replies to it.
The slide-over holds the chat's whole conversation, every turn after the brief it was handed, newest at the foot.
A run that stopped before it finished says why in its last turn, and replying tries again. When the AI is not signed in, the send becomes Log in.
Its text is the editor's: the editor's typeface, at the size Editor text sets in Settings ▸ Text size and wrapping. The conversation itself — what is said, and the box — can have a size of its own there: Work text.
Chats
The slide-over holds one conversation with the work's agent — no tabs: every chat of the work, one after the other, oldest at the top.
- Each chat is its own context with the agent on the issue's branch — its own run of the work, handed the issue's work prompt with what you write first.
- The ⋯'s Refresh chat starts another: a line goes across the conversation — “Refresh chat — the conversation above isn't part of your conversation with your AI” — and the next message starts a new run, the Initial prompt over the box until it is sent; Cancel refresh goes back to the one before. It starts even while another chat's agent is still working — chats run side by side, on the issue's branch in its one checkout, so each agent sees what the others change.
- The ⋯'s Delete this chat deletes the last chat, asked first — its part of the conversation goes, and what it changed stays in the checkout. Its About these chats says the AI they run on, and what they are.
- Each message carries its date and time after its label — an answer's after its numbers, when it finished.
- Filter — the funnel beside Git's stats — opens a small popup under the head, over the conversation, to find your way in it: by Date, Commit, Person or Chat, which one (a day, a commit, a person, a chat), where it is of how many, and ‹ › to the one before and the one after — a person's messages one after another. What is not it is dimmed, and the one it is at is lit and brought into sight; ×, the funnel again or
Escapeputs it away. - A chat somebody else started is theirs: their words carry their name, and a line under their part says where it ends — it isn't part of your conversation with your AI. What you write under it starts a chat of your own, as Refresh chat does: the work prompt and your words, never their conversation.
The last chat is the issue's work: the issue is done when its run finishes and no other chat's agent is still working.
Where it opens
The ⋯ at the right of the first row starts with the issue's id — chosen, it is copied — then Initial prompt, then where the work opens, which this browser remembers:
- Left, Right or Middle — the slide-over, 35% of the window wide, down that side of the window or in its middle, between the tabs and the status bar, whatever page is under it. A press outside it or
Escapeputs it away. - Collapsed — a small window just over the status bar's issue, where the status bar opens it, one size whatever it holds: its first two rows, the chat's latest answer and its box. It stays up while you work elsewhere — a press outside it and
Escapeleave it be — and its × puts it away. Its Maximize opens the whole conversation where Left, Right or Middle last put it — collapsing keeps that;Escapeor a press outside there come back to the small window, and × closes it.
Work, on an issue's page, and a note's Research open it expanded, down the right of the window, whatever the ⋯ says — the ⋯ is where the status bar opens it, and a place picked in it moves it there while it is up.
Collapse, beside the ⋯ wherever it opens, puts it in the small window — and it opens Collapsed from then on, until the ⋯ says Left, Right or Middle again.
The issue's name is on it when the status bar opened it, and collapsed — the way to the issue's page.
Beside a note's Research
A note's page has Research — the same slide-over, for a note: chats with the level's AI about it, each started from one of the Research prompts in Policy ▸ Workspace ▸ Notes — its Initial prompt picks which. It has no Git stats and is held to no branch.
It can be up at the same time as the Work. Each keeps its own chats and its own place — its ⋯ says where — and where both would stand in one place they stand side by side, the one opened first at the edge (one over the other in a narrow window). A press in one leaves the other up, and Escape puts away the one you are in.
The note being researched — the one whose Research you opened last — stands on the status bar before the issue, each its mark and its id; a press on it opens its Research. Collapsed, the Research's small window stands over it, and two small windows stand side by side in the bar's order: the note's, then the issue's. A small window the other's whole card would cover stands beside the card instead, and the card keeps its whole height.
What it changed
Git, in the slide-over's first row, is what the checkout has changed and not committed — the lines added and taken away, a new file's lines counted as added (+12 −3) — while the issue's branch is checked out. It moves as the agent works.
Pressed, it opens the work's version control beside the card, in most of the room beside it — its branch at its top; under it the commit shown — its title, then AI when an answer made it — else the initials of whoever committed it, in their colour — its id and how long ago, said short (now, 5m, 3h, 2d) — and pressed, its commits open in a popup under it, over the change: what is not committed (a dashed ring) and the branch's commits, newest first. A commit picked closes it, and when an answer made it, the Work's conversation shows that answer, lit, wherever it is in it. A press outside the popup, or Escape, closes it. Under that, what the commit changed in all — its lines and files, who made it at the right — and the change, file by file, as Version Control draws it, its files held at the top while the change scrolls under them — in one column, or side by side with the switch at its top (Version Control's own choice too; under a narrow width it stays one column). Its text is the size of the Work's conversation beside it — Work text, or Editor text's until that has its own — and pressing a commit's id copies it. It only shows them: committing anything more and merging the branch are done in Version Control itself — the ⋯'s Open in Version Control, or the ↗ at the fly-out's top. Drag its outer edge to make it wider or narrower (double-click it for the width it opens at); Git pressed again, × or Escape puts it away.
Each answer, a commit. When the agent finishes an answer that changed files, what it changed is committed on the issue's branch — locally, never pushed, one commit an answer (Policy ▸ Git ▸ Work turns it off). An answer's commits are only its own: the one made for it and those its agent made itself. A commit somebody makes while it runs, a merge brought in then, or another chat's answer running beside it is never counted as its, and if the checkout was moved to another branch meanwhile, nothing is committed. The answer's label carries its numbers — AI ⑂ +12 −3, one press: pressed, the fly-out opens on that change, lit among the commits — the small window opens out first.
AI, by its commits. Every commit an answer made is marked AI in the fly-out's list; any other commit carries the initials of whoever made it. The server keeps each answer with its commits — the words sent, who sent them and the answer — for as long as the issue lives, even when its chat is deleted or the answer asked again, so the marks are the same for everyone who opens the issue.
When it is done
The issue's work is done when its run finishes — its newest chat's, when it has more than one — and no other chat's agent is still working. A run that stopped before it finished leaves it not done, until a reply runs it again.
An overview is done when its sub-issues are. Where Policy ▸ Swim lanes names a lane for finished work, the issue moves there by itself.
The issue's branch
The Issue section's Branch row names the issue's branch and whether it is checked out; once merged it is struck through. Pressed, the name slides out its history — where it stands, its commits, and Open in Version Control.
The work needs the checkout on that branch, because Git counts the checkout's own changes. While it is checked out, the status bar shows the issue — its mark and its id, what the checkout has not committed yet and how many commits its branch has that its target has not — and a press opens its Work slide-over, with the issue's name at its top to go to the issue's page (the branch's own name stays at the bar's left, after the compass mark). Check out branch, at the end of the issue's title row after its ⋯ (on its other pages, the side panel's top row), puts it there — the Work press then stands at the end of the issue's title — and is refused while uncommitted work or a running agent is in the way.
When another issue's work is still uncommitted in the workspace, the page offers to open it.
Diagrams in a work prompt
A map no longer goes into a work prompt from the Topology tab: it is linked on a note — the note's side panel, Diagrams — and drawn there live, from the branch it was linked on. The diagrams a work prompt already holds stay in it, under its Diagrams heading, and Preview draws them as the Topology tab draws a map: frames for services, cards for functions, lines at right angles.
A flowchart can be written by hand too, in Edit, as a ```mermaid block; a sequence written that way is shown as its code.
Viewer
Open topology and sequence diagrams side by side in a resizable grid.
- Open it from Tools ▸ Viewer, or send a service's or a domain's Map to it with Open in Viewer — the Viewer's mark on its file tree's toolbar, before Topology: the same Map its Topology tab draws, All or Slots only as that is set.
- Each pane's ⋯ holds its filter, fit, maximize and rotate. Drag a pane by its header to rearrange the grid: drop it on another pane's middle to swap them, near its left or right edge for a new column beside it, or near its top or bottom edge for a new row above or below. A strip between rows, or under the last, makes a new row there.
- Architecture, domain-overview, and per-service sequence views all render here.
- While the Viewer is on screen, the search box at the top is on Viewer Search: type a service, domain or subdomain and pick it to open it here. The line over the results says what it opens as — Map or Sequence, All or Slots only — and a press switches it. Panes already open come first; picking one brings it forward.
Pane types
Each in its own pane:
- Architecture — the whole system
- Domain overviews — publishers and subscribers, with orphans surfaced inline
- Per-service call chains
- Topology maps — a scope's Map, from Open in Viewer on its file tree's toolbar, to drag and zoom; a function's card opens on the Topology tab, not here
One diagram at a time
The Viewer row's › menu under Tools has a toggle that changes what opening a diagram does:
- On — a diagram opened from the Explorer or from Viewer Search clears the grid and fills the Viewer on its own. Switching it on while several are open collapses them to the one you were looking at.
- Off — it joins the panes already there.
The choice is remembered per browser. The same menu has View all Domains.
Global Policy
Govern each scope: which AIs run its work, how its services build and run, how a new service's project is made, what Commit does, and the shared sets on its Workspace tab — labels, projects and goals, the board's swim lanes, the templates an issue is written from, what an issue's work needs before it starts, and what a note's research and its words start from.
- Tools ▸ Global Policy edits the workspace default. For a domain, subdomain or service, open it and press the Policy (shield) icon on its file tree's toolbar.
- One page in five parts — AI, Run & build, Templates, Git and Workspace, each under its name: a tab along its top goes to each, and the tab of the part you are reading is lit as the page scrolls. Edit, at the right-hand end of the tabs, edits the whole page.
- Values inherit down the tree. A lower level overrides a single field, or a whole list by taking its own copy, and the ↺ beside “overridden” goes back to inheriting.
- The page is read-only until you press Edit, or double-click the page — edited, it takes the edit colour, as a file being edited does; changes then wait for Save, and Cancel throws them away.
AI
The AIs this level runs its work on — an agent from the library (Claude Code, Codex, Gemini CLI, Cursor Agent, Aider, OpenCode, Goose, Amp, GitHub Copilot CLI, Qwen Code, Crush) or an API endpoint, with its model, mode and effort. With two or more that run issues, Runs on chooses whether one Primary runs everything or they take turns (Round robin). If one is unavailable the next in the list is used; drag a row to change the order. Any AI can be removed, the last one too.
When an AI answers that it is not signed in — on an issue's Work, in a file's chat or in a Topology card's chat — Log in opens Tools ▸ Terminal and runs that AI's own sign-in there (claude auth login, codex login…). Each AI's ⋯ in the list has Log in too. An API signs in with what its card names instead.
Endpoints that sign in
An API endpoint signs in with a key, an OAuth 2.0 token (client credentials: a token URL, a client ID and the variable holding its secret) or a username and password (HTTP Basic) — its card's Signs in with. No secret is stored in the policy: each is read from a variable of the server's environment that you name, starting COMPASS_AI_ (or a provider's own key variable), and no address may carry a username or a password. A token URL is https://, and so is the endpoint of an AI that signs in with OAuth or a password — plain http:// only on the machine running compass serve (localhost, 127.0.0.1); such an AI names its endpoint, or its sign-in would go to the provider's own address. The card checks all of it before Done takes it, as the Save, a run and Check do.
What an AI is for
Each AI has a Purpose: All (the default — it runs your issues and answers the file and function chats), Issues alone, or one non-contextual chat alone — a chat always runs read-only and is sent nothing but what it is about:
- Non-contextual — files — a file's chat (its AI, before Slots); what you type, and the file when its prompt sends it.
- Non-contextual — functions — a Topology function card's chat; the function's code.
An AI set up for a chat alone answers that chat first; with none, an AI for all answers it. An AI for issues alone answers no chat. A chat on a folder of the code map, or on a function in one, uses the AIs set up for that folder, the domain it is in, or the workspace.
The prompts each chat starts from are not an AI's: they are a list of that chat's own, on Run & build (File chat prompts, Function chat prompts).
The tokens it took
The sparkles and a count at the right of the status bar are the tokens the workspace's AI runs took — each run's latest turn, which a reply or a rerun replaces, so it is what the latest turns took rather than every turn's; a dash where no run has reported its usage. Pressed, it puts up what the count is made of: the total, in and out, how many runs reported their usage and how many ran where the provider reports none (a CLI that prints no usage, a hand-off), then a row a level the work was filed on, the most first — pressed, its Workspace — and the notes' research. A level whose largest run went over its token budget is marked ⚠.
Run & build, and Git
Run & build sets how a service filed here is built — automatically, the way its own folder says (Cargo, Go, Gradle or Maven, npm, Python and more; the field's ? lists them), or by a Build command of the level's own, used for every service under it — the prompts a file's chat (File chat prompts) and a Topology function card's chat (Function chat prompts) offer to start from — and the Terminal: the shell a new terminal starts (the system default the host detects, one of the shells it found, or a path of your own) and the folder it starts in. The Terminal is the workspace's, one for every level as Git is, and like the rest of the page it changes with Edit and is kept with Save. A prompt's text can name what its chat is about, each filled in as the question goes: a file's {path}, {filename}, {language} and {contents}, a function's {function}, {path}, {filename}, {language} and {contents} (its code alone), and the {service} either is in. Every one of these prompts uses {contents} — the whole file, or the function's code — so its chat has what it is about: a prompt's card lights {contents} in yellow until the text names it, and Done waits for it. Each card is named for its list — a file chat prompt, a function chat prompt — as a creation template's is, and opens large.
Git sets what Commit does — push after committing, and optionally open a pull request — the branch work is cut from (its ▾ lists the repository's own branches, none the app made for a piece of work), how a finished goal's branch is merged (Merging: a merge commit, squashed into one commit, or either — chosen when finishing it), and whether each of the Work's answers is committed on its issue's branch (Work, on until switched off). There is one repository, so Git is the same at every level.
Who a commit is by is not set here: it is whoever is signed in, or else the git user of the machine running compass serve. It pushes to the repository's own origin.
Templates
Templates is one list: the workspace's creation templates, each with a switch.
Offered here
A template's switch says whether Add service offers it at this level — switched off, it stays in the library and is not offered here. Levels below inherit what is switched on until one changes it, written when you Save. The first switched on is Add service's default, tagged default; Make default beside another one switched on puts it first. Where no level has chosen, every template is offered, new ones too.
Creation templates
The workspace's library: a name and a set of files each, in any language (there are no built-in ones). A service made from one is whatever its files are — a Cargo.toml makes it Rust, a .csproj C#.
- New template opens it in its own editor: the files as a tree, and File, Variables and Preview tabs. Deleting a file, a folder or a variable asks first.
- Each variable is a row; its pencil opens it as a form, every field with its own ?.
- A variable can be required (an empty answer is refused) and can carry a validation — a regular expression the whole answer must match — with the error message Add service shows when an answer breaks it.
Variables
Variables are {{name}}, or a case of it such as {{name|snake}} or {{name|pascal}}. compass fills name, domain, date and year itself; variables of your own are asked for by Add service — one at a time, with arrows to move between them — and it will not make the service until every answer passes.
The variable bar inserts one at the cursor in the case you pick.
Swim lanes
The board's columns, left to right. New lane adds one, by name.
Press a lane's name to edit it, drag to reorder, and × to remove it; a removed lane's cards go back to the lane their work gives them. A new issue starts in the first lane. Every board also ends in Archive, which clears its cards after a set number of days.
A lane's card has Automatic moves: issues land in it by themselves when their branch is created (Start Issue's Create branch), when their branch gets a commit, or when their work completes. They only move forward, and they keep that order along the board — a later move's lane is never left of an earlier one's: a box the order forbids is held, saying why, and dragging a lane past that asks first and turns the later move off.
Labels
The names issues are filed under. Every level inherits the set above it and may add its own, in one list, each label saying where it was created from — the workspace, a domain or a subdomain. Renaming or deleting a workspace label reaches every task and note carrying it, and the issue and note templates and the work and research prompts that name it: a rename renames it there, a delete takes it off.
Projects and goals
Projects, and the goals inside them, group issues. They are managed on Workspace ▸ Projects, which also says who may create them. A project's ⋯ there has Configure… — one card with its name, due date and branching strategy — and Delete this project.
A project keeps its work on branches — its own, each goal's and each issue's, each started on a press — unless its Branching strategy is left off, as it is made or later in its Configure… card. Then its issues' work runs where the checkout is: nothing is started, switched to or waited for, and its page offers no Start presses and no branches. Changing it there asks first, when you save. Turning it off lists the branches the project already has: they are left as they are — none is merged or deleted, and the work on them stays on them — and Turn it off waits for a tick saying you understand that. Turned back on, the project picks them up where they are.
Start project, and a goal's Start goal, ask first, as Start Issue does: the branch's name and the branch it is cut from (the box's ▾ lists the branches Version Control has), both yours to change — and Create branch makes it. A project's branch is a folder of its own and /project — its goals' and issues' branches are made in that folder — and a goal's is in its project's folder, a folder of its own and /goal, its issues' made in it; a folder that already holds branches, or is another project's, is refused in the question. The folders named stay through a rename of the project or the goal. A project cut from a branch of yours other than the one you work from is fed from that branch and lands on it; a goal cut from another branch is fed from its project's after that, and lands on it as every goal does.
A project made on a level is offered there, on every level under it and on every level above it — never on another branch of the tree. A lower level's Workspace ▸ Projects lists the ones made above it first, marked inherited; they are managed where they were made. The list says no counts — a project's goals are under it, its issues on its page. Opened from that level's Workspace, such a project's page is marked inherited too and shows only that level's issues — Delete and Complete project still count all of it. Grouped by project, every project's name opens its page, one with none of a level's issues too.
Every issue is in a goal
Every issue in a project is in one of its goals, ordered or unordered: there is no project-level “Not in a goal”.
- The Project chip and a card's ⋯ ▸ Project list the projects, one row each; the word at its right says where the issue will land. A project with one open goal files it into that goal in one press; one with none files it in no goal (Unassigned); one with more opens its goals to pick from (‹ goes back).
- A goal's “+”, beside its ⋯, files straight into that goal. The “+” is there whether the goal is open or folded.
- Creating a project from the picker gives it a first goal, “Unassigned issues”, and puts the issue there — rename it or move its issues on the project's page. It is drawn under the other goals, at the bottom of the plan, until it is renamed or made an ordered goal.
- An issue moves between goals with ⋯ ▸ Goal,
Alt+Shift+↑/↓or a drag; to take it out, change its project. - Removing a goal moves its issues to the next open goal; the only open goal still holding issues cannot be removed until there is another.
- Work in no goal — filed before this rule, or as Unassigned — is listed under “Needs a goal” — it folds, as a goal does — until each is put in one.
The project's page
- Every finished goal keeps its step number (in green) and drops its branch, gate and date — its name and count say it — and the ordered goals to come are numbered after them.
- New goal is in its header, right of the project's ⋯. A goal's ⋯ has Rename and Configure…: one card with its name, whether it is ordered and its position — every step listed, the finished goals' shown but greyed, nothing going before them — its due date and “Use this date”, its gate, and its labels. The same card is on Workspace ▸ Projects, and New goal asks the same.
- A goal's labels go on every issue made in it — and on every sub-issue under one — beside the issue's own: the composer shows them as the goal is picked, where they can be taken off before it is added, and the issue template one of them goes with is written into an empty description. An issue moved into the goal later keeps the labels it has. A label renamed or deleted is followed into the goals that give it.
- An issue's title opens it (it underlines under the pointer); pressing anywhere else on a row with sub-issues folds or opens them.
- A row's Start Issue asks as the issue's page does, and Create branch and check out there opens the issue with its Work slide-over out.
- With Branches hidden the goals close up; with them shown each goal keeps the room its git lines need. With the Branches slid out over the rows, the branch under the pointer lights its row.
Where things stand
- The dot beside a project's name — on its page, in the Projects list, wherever a list is grouped by project — is where it stands: white not started, blue in progress, green complete.
- A goal's date is its issues' date: an issue put in the goal (the composer shows it), and every sub-issue under one, takes it unless someone gave it a date of its own, and follows it when it changes. Untick “Use this date” in the goal's Configure card to stop that.
- The project's own date is under Complete project, after how many issues are left.
Updating branches
The down-arrow icon in the header (Update branch) opens a slide-over of what the project's branches are missing:
- the commits the project's branch is behind the branch it was cut from: “This branch is out-of-date”, the branch they come from and the one they go into, then each commit — press one, or the open icon over them, to read it in Version Control
- the policy files its branches lack
Update, beside the slide-over's title, merges them in, the commits first, then the files. With policy files to update too, the commits and each branch carry a tick and Update takes what is ticked; with nothing ticked it is off. A goal whose branch is behind the project's has the same icon on its line — and so does an issue whose branch is behind where it lands (its goal's, its parent issue's or the project's): on its side panel's top row, its row here, and its List row and Board card. Pressed, each opens the same slide-over, with that branch's commits and no tick — Update merges them in, and a conflict opens Version Control on it. A branch counts as behind only where bringing it up to date would change its files: one that already has what those commits bring — as every branch does once Update has put the policy files on it — shows no icon.
Issues and work
The prompts an issue's work starts from — kept in this workspace's database, the same on every branch, in no file — and the templates an issue is written from:
- Work prompts — a list, as many as you need: each a name, the labels it goes with (shown on its row only where it has some) and its text — what an issue's work prompt starts as, filled in for the issue:
{issue_title}and{issue_body}are its title and description,{work_request}what was asked of the work in its box (a prompt that does not name it still gets it, at its end),{issue_id}its id,{today}the day and{linked_notes}the notes it links to — each its name and id over its words, as they are when the work starts. An issue's description or its own work prompt can name{linked_notes}too: Linked notes on its formatting bar puts it in. (The short names these had —{title},{issue},{prompt},{id},{date},{notes}— still work in what was written with them.) The functions added from the Topology tab go under the prompt's own Code heading, made for them when it has none — a map is a note's diagram now, not a work prompt's.
Which one an issue starts from: the Initial prompt over its Work slide-over's box picks it; until it does, the first that goes with one of the issue's labels, else the first switched on — tagged default. With none on, the built-in. A label goes with one prompt. Each row has a switch: off, the prompt stays in the list and is offered nowhere.
A prompt's card has the variables it can use in a dropdown — choose one to put it in at the cursor; the list icon beside it says what each is filled with.
↺ puts the built-in text in the box: a few plain lines naming every variable, a line whose variable is empty left out with the label over it.
Issue templates
The structure an issue is written in — headings, a checklist, the questions to answer — each going with labels. A label goes with one template, and the list is inherited down the tree like the other lists. Renaming a label renames it in the templates that name it, and deleting one takes it off them.
- On a new issue, putting on one of its labels writes the template into an empty description. Words already written are never replaced: the template is offered under them. Taking the label off again takes an untouched template back out.
- On an issue that exists, putting the label on asks first, with the template shown, and Add template puts it under what the issue says.
Each template has a switch too: switched off, it stays in the list and is used for nothing — no label brings it.
The first that is on is what a new issue in the composer is written from — tagged default; in Edit, drag a row to change the order. With two or more on, the composer's Template, on its row of properties, picks another, or none: one it wrote gives way to another pick, and one of your own words is never written over — a pick goes under them.
A template can name the variables {issue_title}, {issue_id} and {today} — its card has them in a dropdown, as a work prompt's does. They are filled in when the template goes into an issue; a new one shows them as written until it is added, since it has no id before that.
Notes
The prompts a note's Research starts from — the Research prompts, a list kept in this workspace's database like the work's, each a name, the labels it goes with and its text: what the AI looking into a note is handed, filled in for the note. {note_title} and {note_body} are its title and words, {note_location} where it is kept, {linked_issues} the issues it links to, a line each, {research_request} what was typed to start the chat (a prompt that does not name it still gets it, at its end), {note_id} its id and {today} the day. (The short names these had — {title}, {note}, {level}, {issues}, {prompt}, {id}, {date} — still work in what was written with them.)
Which one a chat starts from: the Initial prompt over the Research slide-over's box picks it, kept as the note's, and its Open it shows it as text to change for that note alone, its variables in a dropdown over the box (the level's prompt stays as it is; a pick puts the level's back); until it does, the first that goes with one of the note's labels, else the first switched on. With none on, the built-in. A switch on each row: off, the prompt stays in the list and is offered nowhere.
A prompt's card has the variables in a dropdown, as a work prompt's does, and ↺ puts the built-in in the box: a few plain lines naming every variable, which ask the AI to read and to change no file.
Note templates
The structure a note is written in — headings, a checklist, the questions to answer — each going with labels: the notes' own list, apart from the issue templates, with their rules. A label goes with one note template, the list is inherited down the tree, and renaming a label renames it in the templates that name it, deleting one takes it off them.
- On a new note, putting on one of its labels in the composer writes the template into its empty words. Words already written are never replaced: the template is offered under them.
- On a note that exists, putting the label on asks first, with the template shown, and Add template puts it under what the note says.
A template switched off stays in the list and is used for nothing. The first that is on is what a new note is written from in the composer — its Template picks another; drag a row to change the order. A template can name {note_title}, {note_id} and {today}, filled in when it goes into a note — a new one's when it is written.
Inheritance model
Every field resolves global → every domain and subdomain hop → service (Postman-style): set it once high up and override only where a service differs. Each field names the level its effective value came from.
Saving
Nothing is written until you press Save. Edit covers the whole page; leaving the level with unsaved changes discards them and says so. Whatever you change is lit and says unsaved until Save keeps it or Cancel puts it back — a list's row (a view, a lane, an AI, a prompt, a template, a label), a field, where new work lands — and what you take out of a list stays as a struck line, “removed · unsaved”; changed back, it is as it was.
Going back to inheriting
There is no whole-level Clear. Each section's ↺ beside “overridden” returns that section to inheriting, and picking “Inherit” in a single field hands back just that field — never touching a parent or a child.
Terminal
A persistent terminal for your workspace — run commands without leaving the app.
- Sessions keep running: navigate away, come back, and each one is still there with its scrollback. + starts another, and the picker beside it switches between them.
- A new session starts at the workspace root — or wherever the Policy page's Run & build ▸ Terminal points it.
- For a terminal that starts inside ONE service's (or domain's) directory, open it and use the Terminal tab of the Actions panel under its editor.
- Split, beside ↻, puts another terminal in the session's tab — up to four, two to a row, each its own shell. The pane you are typing in is outlined; drag the line between two to resize them, and × in a pane's corner closes it.
- ↻ restarts the session you are in: it ends, and a new shell takes its place.
- Ctrl+V (or Ctrl+Shift+V) pastes, as right-click ▸ Paste does — a sign-in code copied from the browser goes in whole.
Persistent sessions
Terminals run server-side and survive navigating away or closing the item — the session is still there when you open it again.
↻ is what deliberately ends one (and × on a session in the picker, when there are several); a session left idle is reaped after 30 minutes.
Which shell it runs
Your machine's shell, launched on the host running compass serve — not a sandbox.
Which one it launches is set on the Policy page, under Run & build ▸ Terminal — the system default, or a path of your own — and so is the folder a new terminal starts in; a service terminal starts in that service's directory.
Text and colours
It is set in the editor's typeface, at the size Settings ▸ Text size gives Actions text, with a steady block cursor.
Programs' colours are a terminal's sixteen — red is red, green is green — tuned for the theme's ground, light or dark, and 24-bit colour is drawn as asked (the shell is told so: COLORTERM=truecolor).
Version Control
Review what has changed in the working tree, then commit it with a message.
- The working tree, split the way git reports it: Merge Changes, Staged Changes and Changes, each a folding list of files.
- Pick a file to read its diff in the pane beside the list, and drag the divider to give either side more room. On a narrow panel the list takes the whole width, the branch's history becomes a section under it, and a file opens in a window over the list.
- Hover a row to stage it (+), unstage it (−) or discard the change (↺). The group header does the same to everything under it. A row under Merge Changes has a ⋯ with Resolve… instead.
- Add a message and Commit. It records the whole working tree, staged or not, as one commit.
- Saving is manual. The branch checked out is named at the left of the status bar, after the compass mark, with what has changed; click it to open this panel. The copy press at the top of this panel, beside Refresh, copies the branch checked out as its reference —
b:and its name — which the team chat draws as the branch's card. While an issue's branch is checked out the branch is its name alone, and the issue has a segment of its own further along — its mark and its id, what the checkout has not committed yet and how many commits its branch has that its target has not — and a click on that opens the issue's Work slide-over, with the issue's name at its top, a link to its page.
Discarding
Discard throws the working-tree change away, and git keeps no record of an uncommitted edit — so it asks first, and the confirm says which case you are in:
- A tracked file is restored from the index, which leaves anything you had staged staged.
- An untracked file has nothing to restore to, so discarding it deletes it from disk.
What "save" writes
Config is written as JSON under .compass/; operational and secret state lives in the workspace's PostgreSQL database, not in the committed files.
Committing and pushing
Global Policy ▸ Git decides how far Commit goes: “Push after committing” makes the button Commit & push, and “…and open a pull request” adds a pull request, whose target branch is picked beside the button — until one is, the branch the workspace works from when Branch to work from names one, else the repository's main line, never the branch committed on. It is opened with the GitHub CLI on the machine running compass serve, signed in (gh auth login, or GH_TOKEN in its environment), on the GitHub repository origin is; the row says so with a ⚠ while it cannot be. A commit to a branch whose pull request is already open lands on it, and the panel says that one rather than opening another.
When the push lands and the pull request does not, the notice at the top of the panel says so and Open the pull request opens it again; when the push did not land, Push again.
The ⋯ menu
- Fetch, Pull and Push
- Edit history — undo the last commit, amend it, squash, or read the reflog
- Branch history
Incoming
Incoming lists the other branches (and pull requests) with work this one does not have yet, each with a button that merges it in.
Project branches
A project's branch, its goals' and its issues' belong to the project: the branch list shows them with a lock, and Version Control neither merges nor deletes them — nor merges anything onto one. The project's own page does both (Finish goal, the project's finish). Once the project is deleted, its branches are ordinary branches again.
When the policy files change
The policy files are the agent files in its levels' folders (the workspace's, its domain's — CLAUDE.md, AGENTS.md, .claude/…); the prompts are kept in the workspace's database, not in its branches.
- When they have changed since some of the project's branches were cut, the down-arrow icon in the project's header says so in its tip; pressed, it lists those branches, the project's own first and sub-issues last, each with the files it lacks. The branches are read again each time it opens, so one cut a moment ago is in the list, and Incoming changes shows each file's change line by line.
- Update merges them into the ticked ones, one commit each, without moving your checkout (the branch you have checked out gets them in its working tree, to commit from Version Control).
On the project's page
- The issue whose branch is checked out has a green row.
- A branch whose issue or goal has been deleted is no longer the project's, and is left out.
- Complete project opens a slide-over of the project's branch — what comes into the branch it lands on, commit by commit — with Finalize project at its foot, asked first (with a merge message).
- A project's plan — its goals, their order, what is finished — and each plan's state are the workspace's, the same whichever branch is checked out.
- A project in progress — started, not yet completed — has its page on the editing ground, for everyone who opens it.
Merge conflicts
A merge that stops on conflicts lists the files under Merge Changes. Resolve… shows each conflict and takes the current side, the incoming side or both; Commit is refused while any remain.
Every card above is dismissible in the app, and Tools ▸ Help brings them all back.
Your account
The workspace is one thing; the account that pays for it and decides who sits in it is another. A company has one workspace and everybody in the company works in it. Who is in, and what each of them may do there, is decided on your account page and nowhere else — the app has no access settings of its own.
Three tabs — Account, Team, Billing — and the tab is in the address, so a reload keeps your place and “it is under Billing” is a link you can send. Details are read-only until you press the pencil on the card, because a page of live inputs invites edits nobody came to make.
Team and seats
Who is in your company, and what each of them may do about the company itself.
- Invite people by email. They get a link and join when they accept it — into the company's workspace, the same one you work in. Accepting needs that address: signed in with it, or with an account created on it from the link (no company needed — they are joining yours). Nobody is added without saying yes.
- Invitations wait under the members, each with Resend (a new link; the old one stops working) and Revoke. A link works for 7 days, once; the person can also decline it from the same page.
- Three roles. Owner pays and can do everything. Admin runs the team but cannot buy or cancel. Member has a seat.
- Only an owner can make another owner, or demote or remove one. An admin cannot promote themselves, which is the whole reason that rule exists.
- Every member takes a seat, and seats come from the plan — and so does every invitation still waiting on an answer, including one sent again after it ran out. Inviting somebody into a full company asks you to add seats, or revoke an invitation, first rather than quietly overselling. An owner adds them from Add seats, which opens Billing's Change plan or seats.
- In more than one company — your own, and a team that invited you? The Team tab shows one at a time; pick it at the top.
The last owner cannot leave
A company with people in it and nobody in charge of it cannot be administered, invited to, or cancelled — so removing the only owner, demoting them, or closing their account is refused until somebody else owns it too.
Workspace access
What each person may do inside the company's workspace. Owners and admins see it on the Team tab.
- Owners and admins of the company can do everything in the workspace — they manage this page, so a lesser grant would be one they could lift.
- Everybody else gets a group: pick it in the Workspace access column on Members. Until somebody is placed, they get the default group. A new company has three: Admins (everything), Engineers (read and write, every tool, and the General and Editor settings) and Viewers, the default (read, Help and the Global Policy — it can look at everything and change nothing).
- A group's Access is one of No access, Read, Read and write or Administer — everything, including rewriting history, agent settings files and template checks. A group that can write can be held to domains: it may then change those domains and everything nested beneath them, and nothing beside them.
- Under What it opens it is held to the parts of the app it needs, grouped as the app is: Overview; Policy — seeing it at every level, from the Global Policy down, and changing it with the AI and the agents; Inspect — the Explorer, the item tabs, the Viewer and the Editor; the Workspace and Topology; and the Tools — Version Control, the Terminal, Help, and the General and Editor settings. The Terminal and the settings, marked with a lock, are refused by the workspace itself as well; the rest are left out of what a group sees. A group that administers opens all of it.
- The default group cannot be removed: make another one the default first. Removing any other group puts the people in it back on the default.
- What a group may do reaches somebody already working in the workspace on their next action, not at their next sign-in; what it opens, the next time the app is loaded. Taking somebody off the company closes the workspace to them on their next action.
Write includes running code
Write access brings ▶ Run, and with the Terminal a shell; both run code inside the workspace. A domain scope keeps a group's edits through the app inside its domains; it is a guard against mistakes, not a wall against somebody determined who can write. Give write only to people you would let edit the code — and a terminal somebody already has open stays open after they are taken off the company, until it is closed.
Plan and billing
The plan, the trial clock, your invoices, and how to stop paying.
- The trial takes a card. Seven days, nothing charged, and cancelling before day seven costs nothing. The workspace opens when the trial starts, which is when the card goes on.
- Change plan or seats changes the subscription in place — Pro or Enterprise, monthly or annual, and how many seats — with the total shown before you save. Stripe bills, or credits, the difference for the rest of the period straight away. Seats cannot go below the people in the company and its open invitations.
- Update card and Billing details & receipts open Stripe's own billing page, where the card on file, the billing address and every receipt are kept. Card details never reach us.
- A payment that did not go through is said on the plan, with Update card beside it. Stripe tries again on its own schedule, and the workspace stays open while it does.
- Invoices are grouped by year with a paid total for each, and every one links to the receipt Stripe holds.
- Stopping ends the subscription at the end of the period you have already paid for — not the moment you press it. You keep everything until that date, and the page says which date.
- Changed your mind before then? Keep my subscription puts it back, and nothing will have happened.
Only an owner can buy or stop
An admin runs the workspace; an owner is the one on the hook for the bill. The buttons are not offered to anybody else, because the server would refuse them.
Getting back in
Two ways, and the second one is the one to set up before you need it.
- Forgotten password — ask for a link. It works once and expires in an hour. The page says the same thing whether or not the address has an account, because anything else would be a way to find out who our customers are.
- Recovery codes — ten single-use codes, generated from the Account tab and shown once. We keep only a hash, so that screen is the only time they can be read.
- A code gets you in when the mailbox is gone. Make them before that happens: with no email and no codes, there is nothing on our side that can help.
Changing your password asks for the old one
Being signed in says somebody is at that keyboard; it does not say it is you. The same goes for making recovery codes, and neither field is pre-filled by your browser — proving you know the password is the point of asking.
Destroying your account
Behind the ⋯ at the end of the tab strip, in two deliberate steps.
- Type your email address and your password. The password proves who is at the keyboard; the address proves you know which account you are closing.
- A second dialog confirms. Nothing is deleted until you press Confirm and delete, and going back at that point changes nothing.
- Any company where you are the only member is deleted with you, and its billing stops at the end of the current period.
- Companies with other people in them carry on. If you are the last owner of one, you are asked to hand it over first.
- A company deleted with you takes its workspace with it — its config, its code and its git history. Push anything you want to keep to a remote of your own first. A company that carries on keeps its workspace.
There is no undo
Destroying an account deletes it at once: you cannot sign in to it again, and no recovery code reaches it. That is why it takes two steps and a password to reach.
Next steps
The fastest way to understand Compass is to use it.