Solipsist · features

Every part of the interface, once.

What each user-facing part is called, where it lives on the screen, what it is for and what touching it does. Arranged the way a writer meets them: the frame around the page, writing, asking the agent, reading its answer, watching it work, talking to it, and the review of changes from outside.

None of the pictures are drawn here. Each one is the app's own component rendered with sample data, or the real editor with its own extensions put in that state, styled by the app's own CSS. Regenerate it with bun run features; when a component changes, so does its picture. The words come from scripts/features/catalog.tsx, and test/features.test.ts fails when a component exists that this page doesn't list.

Top bar · ← title · save state Banners Status bar · mode · suggestions · agent · auto-merge · debug · caret · words
01

The frame

What is always on the screen around a page: where you are, whether it is saved, and what is wrong with the connection.

Pages React component

WhereThe home screen, at /

The list of pages (the .md files in the docs folder), newest first.

Use it for

  • Find a page to open, or start a new one.

When touched

  • The gear: opens the settings dialog.
  • New page: creates an empty page and opens it.
  • A page's file name: opens it at /d/<id>. Its first line is beside it.
  • The time is when the file last changed.
src/app/pages/Pages.tsx
With pages

Pages

Empty

Pages

No pages yet.

    TopBar React component

    WhereTop of a page, full width

    Where you are and whether your words are safe: a way back, the page's title, and the save state.

    Use it for

    • Go back to all pages.
    • Know at a glance whether the page is saved: nothing else in the app says it.

    When touched

    • ← : back to the list of pages.
    • Copy page, beside the gear: copies the page for GitHub and Google Docs (see Copy page).
    • The gear at the right end: opens the settings dialog.
    • Save state changes by itself as you type: Unsaved changes → Saving… → Saved, or "Can't save, retrying…" in red when the server isn't answering.
    src/app/pages/Frame.tsx
    Saved
    ←Plan for Q3Saved
    Unsaved changes
    ←Plan for Q3Unsaved changes
    Saving…
    ←Plan for Q3Saving…
    Can't save
    ←Plan for Q3Can't save, retrying…

    A page from a newer Solipsist React component

    WhereIn place of the page, when its file was saved by a newer build

    A page whose format is newer than this build knows is shown read-only: nothing here can change it until Solipsist is updated.

    Use it for

    • Read a page a newer Solipsist saved, without risking it: no saving, no agents, no Sync.

    When touched

    • The banner names the page's format and the newest this build knows, and says to update. The top bar reads Read-only. The server refuses any write to the page (423) in case one is tried.
    src/app/pages/NewerPage.tsxsrc/shared/docfile/file.tssrc/server/files.ts
    Saved by format 2, opened by a format-1 build
    ←notes/plan.mdRead-only

    Banners React component

    WhereUnder the top bar, one strip per problem

    Strips that say what is wrong with the page's connection or file, with the one thing to do about it.

    Use it for

    • Another tab has the page open (only one may).
    • The connection to the server is lost.
    • The file changed elsewhere while you were typing.

    When touched

    • try again: reloads the page.
    • Reload: takes the other version. Keep mine: keeps yours and writes it over theirs.
    src/app/pages/Frame.tsx
    Open in another tab
    Connection lost
    Changed elsewhere

    SupportNudge React component

    WhereUnder the top bar, when a page opens

    A quiet strip asking you to buy a licence, once you have written on support.after_days days (14 by default). Nothing is locked and nothing is sent anywhere: the count stays in support.json on this machine.

    Use it for

    • Buy a licence if Solipsist is useful to you.
    • Say you already have one, or put it off.

    When touched

    • Buy a licence: opens the shop in a new tab.
    • I've bought one: never asks again.
    • Later: asks again after 7 more days of writing.
    • It is checked only when a page opens, so it never appears while you write.
    src/app/pages/Frame.tsxsrc/server/support.ts
    After 14 days

    Settings gear React component

    WhereRight end of the top bar, and in the header of the pages list

    A gear that opens the settings dialog, from a page or from the list of pages.

    Use it for

    • Reach the prompts and the loaded settings without leaving the page you are writing.

    When touched

    • Click: opens the settings dialog over the page. Escape or the ✕ closes it.
    src/app/pages/SettingsDialog.tsxsrc/app/pages/Frame.tsxsrc/app/pages/PagesView.tsx
    In the top bar
    ←Plan for Q3Saved

    Copy page React component

    WhereJust above the page, on its right

    Copies the page as you see your own text (unsaved edits included), in two formats at once: markdown for GitHub and rich text for Google Docs. Markers, suggestions, margin comments and hand-written HTML comments are left out; a range's text stays.

    Use it for

    • Paste the page into a GitHub issue, PR or comment: the markdown keeps image paths as written (relative to the page's folder), which render when that folder is in the repo.
    • Paste it into Google Docs: headings, lists, tables, code and links come across, and the images are embedded (SVG and other formats drawn as PNG), up to 8 MB of images in all; past that the rest are links to this server.

    When touched

    • Click: copies. Its label is always "Copy page as markdown".
    • Copied (green check) for two seconds; its title says if any image was linked rather than embedded, and why.
    • Couldn't copy (red) when the browser refused the clipboard; its title has the reason.
    • No key: ⌥⌘C is the card's chat, and ⇧⌘C is the browser's inspector.
    src/app/pages/CopyButton.tsxsrc/app/doc/copyPage.tssrc/app/pages/Sheet.tsxsrc/app/chrome.css
    Ready
    Copied
    Couldn't copy

    Prompts (settings dialog) React component

    WhereThe settings dialog, first tab

    Every instruction the agents are given, to read and change: the protocol, the prompt each run is sent, one prompt per kind of placeholder, and the chat prompts.

    Use it for

    • Change how the agents behave without editing the app: shorter answers, another voice, a house style for one kind of placeholder.
    • See what the agents are actually told, with the slots the server fills in.

    When touched

    • A prompt in the list: opens it in the editor. "edited" marks a prompt whose file of yours is in use; "unsaved", one with a change not yet saved.
    • Save: keeps the text as a file in your prompts folder (~/.config/solipsist/prompts). It is refused, with the reason, if it is empty or leaves out a required {slot}.
    • Revert: drops the unsaved changes.
    • Reset to default: deletes your file and brings the built-in text back.
    • A change applies to the next run and the next agent started; one already running or waiting keeps what it began with.
    • Closing with unsaved changes asks once.
    src/app/pages/PromptsPane.tsxsrc/app/pages/SettingsDialog.tsxsrc/server/prompts.tssrc/app/settings.css
    An edited prompt open

    Loaded settings (settings dialog) React component

    WhereThe settings dialog, second tab

    The settings the server is running with, by section, each with its value and where the value came from.

    Use it for

    • Check what is in effect: a value from the default, from solipsist.yaml, or from an environment variable (named).
    • Find out why a setting isn't what you expected. A secret shows only as "set".

    When touched

    • Filter: narrows the list by key, environment name or description.
    • Hover a key: what it does and its environment name.
    • Read only: change settings in solipsist.yaml or the environment and restart.
    src/app/pages/SettingsPane.tsxsrc/server/config.tssrc/app/settings.css
    Defaults, a file and an environment variable

    Choose your files React component

    WhereOver the home screen, on the first launch and from Add files

    The markdown files md_search_paths found, to pick which ones Solipsist copies and syncs.

    Use it for

    • Say which of a project's files to work on. Nothing is created until you confirm.

    When touched

    • All: ticks or clears every file.
    • Add N files: copies the ones ticked into .solipsist/.
    • Cancel (Add files only): closes it.
    src/app/pages/SetupDialog.tsx
    First launch

    Sync and its dialog React component

    WhereSync to file and Reload from file in the top bar; the dialog over the page

    Sends the page to its original file, and asks first if the original changed since it was loaded.

    Use it for

    • Write your edits to the repo, or take in a newer original.

    When touched

    • Sync to file: writes the page over its original.
    • Reload from file: merges the newer original with your edits.
    • Overwrite the file: replaces the original.
    • Discard my edits and load the file: when both changed the same text.
    • Create it: when the original was deleted.
    • Cancel: nothing is written.
    src/app/pages/SyncDialog.tsx
    The original changed

    Connect a model React component

    WhereOver the page, from the status bar or the ask key when no model can run

    How to connect a model, instead of a request that can only fail.

    Use it for

    • Find out what the agent needs before it can answer.

    When touched

    • Close: closes it.
    src/app/pages/ConnectModel.tsx
    No model yet
    02

    Writing

    The page itself, and the small things that happen inside it while you type.

    Sheet (the editor) Tiptap extension

    WhereCentre of the screen: the page, in a serif at reading size

    A Tiptap editor on one markdown file. What you type is saved to the .md file; nothing else is stored.

    Use it for

    • Write: headings, lists, tables, code, images, links; markdown shortcuts work as you type.
    • Everything else in this file is something that happens in or beside this sheet.

    When touched

    • Typing saves after a short pause (see TopBar).
    • Cmd/Ctrl-Z undoes your edits and your decisions on suggestions.
    • The page is focused when it opens.
    src/app/pages/Sheet.tsxsrc/app/editor/behaviour.ts
    A page

    Plan for Q3

    The deadline is end of Q3, and the review is on the calendar.

    • Ship the editor

    • Write the docs

    Team

    Date

    Web

    3 Sep


    Vim mode Tiptap extension

    WhereIn the sheet; switched from the status bar's left button

    Optional Vim keys for the sheet: normal, insert, visual and visual-line modes, with a block cursor.

    Use it for

    • Move and edit without the mouse. Off by default (the status bar says Standard).

    When touched

    • Click the mode button in the status bar: Vim on or off.
    • Esc (or Ctrl-[): back to normal. i, a, I, A, o, O: insert. v, V: visual. h j k l, w b e, 0 ^ $, gg G, { }, Ctrl-d / Ctrl-u (half a screen down / up, in visual mode extending the selection), counts, and the operators d, c, y with x, s, p.
    • On a suggestion: ga accepts, gr rejects, gc opens its chat.
    src/app/editor/vim.ts
    Normal mode: the block cursor

    The cursor is a block in normal mode.

    New-block line ProseMirror decoration

    WhereLeft of a block that just arrived from outside

    A block added by another editor or by the loop gets a line down its left edge, so you can see what is new.

    Use it for

    • See at a glance what appeared while you were away.
    • Throw a new block away: hover its line and click the cross.

    When touched

    • Hover the line: a cross appears. Click it: the block is deleted (an ordinary edit: Undo brings it back).
    src/app/editor/newBlocks.ts
    A block marked new

    An ordinary paragraph.

    This paragraph arrived from outside.

    Another ordinary one.

    Fresh text ProseMirror decoration

    WhereInline in the sheet

    Text that arrived from outside fades in, so the eye catches it.

    Use it for

    • Notice a change without a notification: the words glow for a moment, then settle.
    src/app/editor/freshText.ts
    Just arrived

    The deadline is end of Q3, and this sentence just arrived.

    HTML comment chip Tiptap extension

    WhereIn the sheet, where a hand-written <!-- … --> comment is

    A comment you wrote in the markdown (not one of ours) shows as a small chip with its first words; the file keeps it byte for byte.

    Use it for

    • Leave notes to yourself in the file without them showing as page text.

    When touched

    • Hover: the whole comment is the tooltip. The chip can't be typed into; delete it as a unit.
    src/app/editor/htmlCommentChips.ts
    A comment in a paragraph and between blocks

    Check the date ask finance before Friday before sending.

    TODO: add the budget table once…

    The next paragraph.

    Margin comments React component

    WhereLeft margin, level with the highlighted passage

    Questions about a passage, as cards beside it (Google Docs style). Closed, a card is its gloss: the two-to-five-word note a reader pencils in the margin.

    Use it for

    • Read a question about a passage without leaving the page.
    • Take one down (Dismiss) when you have considered it: the Reader never raises that passage again.

    When touched

    • Click a highlighted passage, or its card: the question opens in a window of its own, and the card counts as read, which keeps a better question from taking its place.
    • A card whose question carries a picture shows a small square; the picture itself is in the window.
    • Questions on nearby lines share the room around their passages and never cover each other. A click on a highlight inside a block a suggestion would change opens the question, not the suggestion's card.
    src/app/pages/Margin.tsxsrc/server/review/index.tssrc/server/place.ts
    Two questions, closed

    Page review React component

    WhereStatus bar or agent panel (the button); the left margin and the sheet (the questions)

    A reviewer reads the page and leaves questions beside the passages it can't follow. It writes nothing in the page: a question is a note, not a change.

    Use it for

    • Press Page review to have the page read like a reader would: what is unclear, unsupported or missing.
    • See where each question is about: the passage is underlined, and its card sits in the left margin.
    • Open a question to read it in full, take it down (Dismiss) or carry it into the chat (Ask).

    When touched

    • Page review blinks and reads “Reviewing…” while it runs; its steps are in the agent panel, and when it ends the panel says what became of every question.
    • A highlighted passage or its card opens the question. With room, the popover hangs in the margin beside the passage; on a laptop it opens just under it. A thin line joins it to the passage and the rest of the page steps back.
    • The status bar counts the questions, which matters when the window is too narrow for the margin.
    • Escape, a click away or ✕ closes it. Questions are stored in the page's hidden block and never change the text.
    src/app/pages/StatusBar.tsxsrc/app/pages/DebugPanel.tsxsrc/app/pages/Margin.tsxsrc/app/pages/CommentModal.tsxsrc/server/review/index.ts
    A question, open under its passage · the blue is the question's accent; suggestions are green, answers orange

    Why small teams ship faster

    Adding engineers to a late project makes it later, and yet we keep hiring.

    The alternative is duller than it sounds. You cut scope until the thing fits in one head, and you let that head decide.

    None of this is new. It is just rarely done.

    Closed, in the margin

    A question, opened React component

    WhereOver the page, from a margin card or a highlighted passage

    One review question in full: the passage it is about, the point, the reviewer's reasoning, the picture it drew, and who asked.

    Use it for

    • Read the whole question, which never fits in the margin.
    • See which reviewer and which model asked it — the same question from a small model and a large one is not the same question.
    • Take it down (Dismiss), or carry it into the chat (Ask).

    When touched

    • Escape, the backdrop or ✕ closes it; the margin keeps its cards where they are.
    • Dismiss: the question goes for good, and that passage is never raised again.
    • There is no Accept or Reject: a question puts nothing in the page, so there is nothing to accept.
    src/app/pages/CommentModal.tsx
    The window form, for a narrow screen · the reviewer's own picture, when it drew one, goes under the point
    03

    Asking the agent

    How a writer hands the agent a task from inside the text, and what the page shows while it is picked up and worked on.

    Completion point (gen) Tiptap extension

    WhereInline in the sheet, at the caret when you pressed ⌘.

    A spot where the writer asked the agent to decide what belongs (text, a list, a table, an image).

    Use it for

    • Hand over a gap: put the caret where the answer should go and press ⌘. (Ctrl-. on other systems).

    When touched

    • ⌘.: inserts the point at the caret; the agent picks it up.
    • It moves through four states: waiting, being worked on, a suggestion waiting, and done (nothing left to show). Its picture changes with each; when the answer is ready the picture goes and the suggestion shows in its place.
    src/plugins/gen/index.tssrc/app/editor/pointView.tssrc/app/editor/markers/loader.tssrc/app/editor/markers/indicators.tssrc/app/editor/markers/registry.ts
    Waiting to be picked up · a dot fading in and out

    The deadline is for all teams.

    Being worked on · a ring with an arc turning

    The deadline is for all teams.

    A suggestion waiting · no picture: the suggestion is the picture

    The deadline is 30 September for all teams.

    Request range (sel) Tiptap extension

    WhereInline in the sheet, around the text that was selected when you pressed ⌘.

    Text the writer asked the agent about or to change, with an optional instruction ("make it shorter").

    Use it for

    • Select text and press ⌘.: ask or tell the agent something about it. Type the instruction, Enter, and it is sent.

    When touched

    • ⌘. on a selection: opens the instruction input under it; Enter sends, Esc cancels.
    • Click its loader (pending): reopens the instruction to read or change it.
    • A selection that can't be marked says why under it: nothing selected, part of it already has a request, it holds a code block, or it starts or ends inside inline code.
    src/plugins/sel/index.tssrc/app/editor/rangeLoaders.tssrc/app/editor/markerCommands.ts
    Waiting

    Please check the end of Q3 date before we send it.

    Being worked on

    Please check the end of Q3 date before we send it.

    Image request (img) Tiptap extension

    WhereAround an image in the sheet, with a hint in the image's corner while it is selected

    An image the writer asked the agent to draw again, with what to change ("make the bars horizontal"). The agent writes a new file and suggests it in the old one's place.

    Use it for

    • Change a picture without drawing it: select the image and press ⌘., then say what to change.
    • In vim, `v` or `V` on the image's line selects it; otherwise click it or drag over it.

    When touched

    • While the selection holds one image: the image gets a dashed ring and "⌘. to change" in its corner. A selection of text that happens to hold an image is still a request about the text.
    • ⌘. on it: opens the instruction input over the image. An instruction is required: Enter with nothing typed shakes the box.
    • An image already being asked about says so instead of being asked about twice.
    • The suggestion is the new image where the old one is: the old one dimmed and ringed, the new one beside it (Accept, Reject, Ask again, Chat as for any other).
    src/plugins/img/index.tssrc/app/editor/imageTargets.ts
    Selected: the key is there · the hint the writer sees first

    Signups have risen every week.

    Signups by week, rising from 120 to 310

    Waiting

    Signups by week, rising from 120 to 310

    Being worked on

    Signups by week, rising from 120 to 310

    A new image suggested · the old one dimmed, the new one after it

    Signups by week, rising from 120 to 310

    Signups by week, rising from 120 to 310


    Instruction input DOM widget

    WhereA popup under the selection (or under a request's loader)

    One line that grows as it wraps: what the writer says to the agent about the selected text.

    Use it for

    • Tell the agent what you want done with the text, or ask a question about it.
    • Also opens again from the suggestion card's Ask again, with the old instruction in it.

    When touched

    • Enter or Shift+Enter: sends (an instruction is one line).
    • Esc, or a click away: closes without sending.
    • Enter with nothing typed when one is required: the box shakes and nothing is sent.
    • 500 characters at most.
    src/app/editor/instructionInput.tssrc/app/editor/markers/popup.ts
    Empty
    With an instruction
    Read only · a run is working on it
    04

    Reading its answer

    What the agent's result looks like in the page, and the ways to accept, reject or send it back.

    Suggestion preview ProseMirror decoration

    WhereIn the sheet, where the answer would go

    The agent's result drawn where it would land, marked, while the page itself stays unchanged until you accept.

    Use it for

    • Read the answer in context: inline text, whole blocks, or a replacement shown against the old words.

    When touched

    • Hover: the card appears beside it. Click: the card is pinned until Esc or a click away.
    • Nothing is written into the page until Accept.
    src/app/editor/suggestions.ts
    Inline text

    The deadline is 30 September for all teams.

    Blocks

    Plan

    Team

    Date

    Web

    3 Sep


    After.

    Replacing the writer's words · old struck through, new after

    Please check the end of Q3 date30 September today.

    After the writer's words

    Check end of Q3(30 Sep) here.

    Declined and answered chips ProseMirror decoration

    WhereIn the sheet, in place of a preview

    When the agent has nothing to put in the page, the marker says so: it declined (with its reason), or it answered a question about the text.

    Use it for

    • See why nothing was written, and read an answer that is not meant to go into the page.

    When touched

    • Declined: Dismiss takes the marker out; Ask again sends it back.
    • Answered: Done takes the marker out; Ask again asks again.
    src/app/editor/suggestions.ts
    Declined

    A Declined: Nothing says what goes here. b.

    Answered

    Please check the end of Q3 dateAnswered.

    Suggestion card DOM widget

    WhereRight margin, beside the diff (a floating card)

    What the agent says about its result, and the buttons to decide.

    Use it for

    • Decide: Accept puts the result in the page; Reject leaves the page as it is; Ask again turns it down and asks for another.
    • On a request about selected text, ▾ beside Accept offers Accept as a Button: the result goes in, with a button above it to run the request again.
    • Talk to the agent that made it (Chat).

    When touched

    • Accept ⌥⌘Y · Reject ⌥⌘N · Chat ⌥⌘C (vim: gc) · next ⌥⌘] · previous ⌥⌘[ .
    • ▾ (on a request that can have a button) opens a menu under it. A result that is one piece of text in place: Accept as a Button (see Accept as a Button). One that isn't (it changes other parts of the page, deletes the text, holds new requests, or starts or ends with a code block): Ask again as a button, saying which, and the agent is asked for one that can be. Asked for as a button, the card leads with Accept as a Button and ▾ holds Accept without a button. ▾ again, Esc or a click away closes the menu.
    • Ask again on a request with an instruction opens the instruction input first.
    • Esc closes the dropdown, then a pinned card; a click away closes it too.
    • A decision is your own edit: saved with the next save, undone with Undo.
    src/app/editor/suggestions.tssrc/app/editor/sideCard.ts
    A suggestion
    Suggestion

    Used the plan's own date.

    With changes to other blocks
    Suggestion
    • Changes a paragraph
    Declined
    Declined

    Nothing says what goes here.

    Answered
    Answer

    Yes: the plan says 30 September.

    Accept as a Button DOM widget

    WhereA popup under the diff, from ▾ beside a suggestion's Accept

    Says what a button does before the result becomes one: a press runs the request again and its result goes straight into the page.

    Use it for

    • Keep a result you will want redone (today's figures, the current time, a summary of a section that grows), with a button to redo it.

    When touched

    • Accept as a Button: the result goes in, and a button appears above it (see Request button).
    • Cancel, Esc or a click away: nothing changes; the suggestion still waits.
    src/app/editor/suggestions.ts
    Accept ▾: the result fits · one piece of text in place
    Accept ▾: the result doesn't fit · it also changes other parts of the page
    Accept ▾ after asking for a button · the card leads with Accept as a Button
    The popup
    Accept as a Button

    Pressing this button runs the request again and puts the new result straight into the page, in place of this text. You won't see a diff, and Undo won't bring the old text back.

    Request button ProseMirror decoration

    WhereIn the sheet, on its own line above the text a request's button holds

    A result the writer kept as a button. The text is ordinary text; the button runs its request again, and the new result replaces it without a diff.

    Use it for

    • Redo the request on the text as it is now.
    • Change what it asks for.
    • Have it redo itself on a schedule, page open or not (today's figures, the time).
    • Take the button off and keep the text.

    When touched

    • Press: runs the request again at once, with its own instruction (no input). While it runs the text shows as a waiting request.
    • The new result goes straight in, with no fade or new-block line, and the button comes back; its margin note says when it last ran (Last run 20:59; hover for the next scheduled run). A decline, an answer, or a result for text you changed during the run waits on its card instead; deciding it brings the button back.
    • Hover: the text it holds is highlighted, and ✎, ⏱ and × show.
    • ✎: the instruction input, filled in; Enter keeps the new instruction (it doesn't run).
    • ⏱: a menu, Only when pressed or every minute, 5 or 15 minutes, hour or day. The server runs a schedule, page open or not, as if you pressed it (on any engine; the page's agent switch and the cost limits still hold), and the button says how often (⏱ every 5 minutes; hover it for the next run). A run that ends on a card waits for you, and the schedule with it.
    • ×: removes the button, keeps the text (Undo brings it back).
    • Sync writes only the text: the button stays in the working copy.
    src/app/editor/taskButtons.tssrc/app/page.css
    Above its text

    The time is now half past three.

    The next paragraph.

    With a schedule
    ⏱ every 5 minutes

    The time is now half past three.

    Its schedule menu (⏱)
    Over a list

    Risks:

    • late data

    • a missed step


    Suggestion count React component

    WhereStatus bar, right side (only while suggestions wait)

    How many suggestions wait in the page, and a menu to go through them.

    Use it for

    • Know there is something to read; step through them; accept or reject them all at once.

    When touched

    • Click: opens the menu: Next, Accept all, Reject all.
    • ⌥⌘] / ⌥⌘[ : next / previous from anywhere in the page.
    src/app/pages/SuggestionCount.tsx
    One waiting
    05

    Watching the agent

    Quiet signs of what the agents are doing, and the panels that show everything.

    Agent pill (margin note) React component

    WhereRight margin, level with each placeholder's marker

    One line beside a placeholder that says where its agent is: waiting to be picked up, working (with its latest step), done, declined (with the agent's reason), asleep, or in a chat. After you accept its result it stays beside where the result landed, saying Accepted (Kept as a button beside a button), for as long as the page is open.

    Use it for

    • See, without opening anything, that the agent is on it, what it is doing, and when it is done.

    When touched

    • Click (or Enter): opens the chat with that agent, wherever there is one to talk to (done, asleep, in chat, accepted, or a run a Pi agent is working).
    • Hover: the whole step (a tool call's arguments, a result) in a panel under the pill.
    • Each state has its own icon and motion (see Primitives).
    src/app/pages/AgentFeed.tsxsrc/app/pages/NoteIcon.tsx
    Waiting to be picked up · a clock
    Waiting for agent to pick the task…
    Working · the engine's own mark, breathing
    Readplan.md
    {"file_path": "/docs/plan.md"}
    A step failed · a warning
    errorThe agent asked for permission (Write …), which can't be answered here
    The agent asked for permission (Write …), which can't be answered here
    Done: the agent is still here · a check that draws itself
    Done
    Declined · the agent's reason in place of Done, a crossed ring
    DeclinedNothing around the marker says what this section is about: add a line on its topic.
    Snoozed · a moon; the conversation is on disk
    Snoozed · finished 7:11 PM
    In chat · a bubble with rising dots
    In chat
    Working in the chat · the agent is answering there; the bubble stays
    Working…
    Accepted · beside where the result landed; the agent still here
    Accepted
    Accepted, agent snoozed · its conversation is on disk; a click wakes it
    Accepted · snoozed · finished 7:11 PM
    Kept as a button · beside a button that hasn't run since
    Kept as a button
    Pi's mark · the same pill, another engine
    Agent is working…

    Engine marks React component

    WherePills, the debug panel's header, the page-chat button

    The mark of the engine that runs an agent: Pi's pixel mark.

    Use it for

    • Tell at a glance that an agent is at work, and which engine it runs on.
    src/app/pages/EngineIcon.tsxsrc/app/pages/PiIcon.tsxsrc/app/editor/logo.ts
    Pi

    Status bar React component

    WhereBottom of the screen, full width

    Like an IDE's: editing mode, the model answering, single-agent mode, what the page has cost, the agent panel, and where the caret is.

    Use it for

    • Switch between Standard and Vim editing.
    • See which model is answering on this page, whether one lasting agent handles every request, and what the page's agents have cost since you opened it.
    • Open the agent panel; see suggestions waiting; the caret's line and column; the word count; which version of Solipsist is serving the page.

    When touched

    • Mode button: Vim on/off.
    • Version (last, e.g. v0.1.0; v0.1.0-dev from source): its title is the whole `solipsist --version` line, to give in a bug report.
    • Model: opens the agent panel, where the model is chosen and the agents are turned off and on.
    • Page review: one review, which leaves questions in the margin and writes nothing in the page. It blinks and reads “Reviewing…” while the run is in flight, and its title says so when a review raised nothing.
    • Debug: opens the same panel (its dot shows the agents' state).
    • In Vim, typed counts and operators show beside the mode (e.g. 2d).
    src/app/pages/StatusBar.tsx
    Standard editing, agent on
    Single agent offCost $0.01232 questions1:16 wordsv0.1.0
    Vim on, agent off, debug open
    Single agent onCost $0.01231:17 words

    Debug panel React component

    WhereRight edge of the screen, opened from the status bar

    Everything the page's agents say, as it happens: the state, the runs, every step.

    Use it for

    • See why nothing is happening, or what a run did, step by step.
    • Choose this page's engine and model (the picker); turn the page's agents off and on; clear the log.

    When touched

    • Model picker: changes this page's model (saved in its file); a run in flight finishes on the old one.
    • Agent on/off: stops or starts this page's agents (kept in the page's file, so a reload and every other tab agree; a run in flight stops).
    • Page review: one review, which leaves questions in the margin and writes nothing in the page. When it ends, the panel says what became of every question it raised.
    • Run tabs: show one run's messages; ‹ › cycle through them.
    • Clear: empties the log. ✕: closes the panel.
    src/app/pages/DebugPanel.tsx
    A page's agents at work
    The agents turned off · the switch is the page's own, kept in its file

    Model picker React component

    WhereDebug panel header, and the page chat's header

    The model this page's agents run on: a shortlist at a glance — your preferred models first, then each engine's — and a search over every model your engines can run, which for Pi is every model your own Pi has credentials for.

    Use it for

    • Choose which engine and model this page's agents use; the page-wide chat uses the same one.
    • Type to search the whole catalog by name, vendor or id, beyond the few the shortlist shows.
    • Read what a model holds and what a million tokens cost before picking it.

    When touched

    • Choosing saves the page's setting. A run in flight finishes on the old model; old agents keep their own engine.
    • ↑ ↓ move, Enter picks, Escape closes, and so does a click outside.
    • A model whose engine isn't set up is listed but can't be chosen, and says why on hover.
    • `agent.preferred_models` in solipsist.yaml pins models to the top under Preferred; the first that can run is a new page's default.
    src/app/pages/ModelPicker.tsx
    Closed: the model the page is on
    Open: the shortlist, preferred first
    Searching the whole catalog
    06

    Talking to it

    The chat window: the page-wide chat, and the chat behind a suggestion.

    Page chat button React component

    WhereTop-right corner of the sheet

    Opens a chat about the whole page with the engine this page is on, and shows how that chat's agent is.

    Use it for

    • Ask a question about the page, or ask for changes (they come back as suggestions on the page). The conversation is kept: opening it again goes on where it was.
    • See at a glance whether the page chat is working while its window is closed: quiet (no agent), a little brighter (snoozed, conversation kept), a breathing glow (agent up, or the chat open), a light running round the edge (replying), a dot (a reply came while it was closed).

    When touched

    • Click: opens the chat window. Its mark is the page's engine.
    • Its state comes from the page's agent stream (`pichat` events, `pageChat` in the hello). Under reduced motion it holds still and shows the state by colour.
    src/app/pages/ChatLaunch.tsxsrc/app/pages/Sheet.tsxsrc/app/pages/EngineIcon.tsxsrc/server/agent/pageChatStatus.ts
    No agent
    Snoozed, conversation kept
    Agent up (or chat open)
    Replying
    A reply came while it was closed

    Chat window React component

    WhereA window over the page

    A conversation with an agent: what you say, what it does (folded), and what it answers.

    Use it for

    • Talk to the agent behind a suggestion (from its card or its pill), or about the whole page.
    • Look in on a run that is still going.

    When touched

    • A call to one of Solipsist's own tools (suggest, answer, decline) is shown apart from the agent's own work, as the result it gave; the agent's calls fold away into one line of work.
    • Enter sends · Shift+Enter new line · Esc closes (also the ✕ and a click outside).
    • Stop (while it replies): stops the reply, keeps the conversation.
    • Send while it replies (an engine that takes it, Pi): the message is queued and the agent reads it after its current step; the same reply answers it. Closing the chat (Esc, a click outside) leaves the reply going.
    • The page chat's header has the model picker (changing it starts a new chat on that model) and New chat (forgets the conversation and starts over).
    • Closing the page chat leaves a reply going (its suggestion still lands on the page); opening it again shows the conversation where it is. Left alone, it snoozes and is taken up again on the next open.
    • While it looks in on a run, the box is disabled until the run ends.
    src/app/pages/ChatModal.tsx
    A conversation
    The page's chat, with the model picker and New chat · the picker is the page's model; changing it, or New chat, starts a new chat
    What it gives back · Solipsist's own tools (suggest, answer, decline) are the result the writer decides on, not work: the call the page refused says so, and the next one takes its place
    Waking the agent · before the conversation arrives
    Looking in on a run
    A message sent mid-reply · Send stays beside Stop; the message waits for the agent's next step
    An error

    Chat log parts React component

    WhereInside the chat window's log

    The kinds of thing in a conversation, each shown its own way.

    Use it for

    • Read the answer first; look at the work only if you want to.

    When touched

    • Task from Solipsist: folded; opens to the prompt the agent was sent.
    • Worked for 5s · 2 tools: folded work; open while it streams, and when a tool failed.
    • A tool: its arguments and result open under it.
    • Envelopes (suggestion, edit, answer, note, declined) are set apart from prose.
    src/app/pages/ChatModal.tsx
    Tool: running, done, failed
    Read/docs/plan.md
    {}
    ✓Read/docs/plan.md40 ms
    {}
    # Plan …
    ✕Bashdate -j …1.2 s
    {}
    date: illegal option
    Envelopes

    Here you go.

    Suggestion
    30 September
    Edit
    The deadline is end of Q3.
    (removed)
    Answer
    Yes.
    Note
    Used the plan's date.
    Declined
    Nothing to do.
    Reply stats
    13k in · 86 out · 42 tok/s · 5.1 s · $0.01
    Notices

    Your suggestion was updated on the page.

    Another run started on this placeholder.

    07

    Primitives

    The small parts everything above is made of: buttons, key chips, dots, spinners and the motion they use.

    Buttons CSS pattern

    WhereEverywhere

    Three variants: primary (rare, one per surface), the default, and ghost. An icon button is square.

    Use it for

    • Primary: the one thing to do next (Accept, Send, New page). Ghost: a quiet alternative (Reject, Clear, Close).
    src/app/chrome.csssrc/app/margin.css
    .btn .btn-primary · .btn · .btn-ghost · .icon-btn
    Inside a card: .task-btn

    Key chip CSS pattern

    WhereNext to the action a key performs

    A small raised chip for a key: shortcuts are shown, not shouted.

    Use it for

    • Show the key for an action beside it, in the chat's footer and on buttons.
    src/app/chrome.csssrc/app/tokens.css
    kbd
    ⌘ .   ⌥⌘Y   esc   ⇧↵

    Status dots and tags CSS pattern

    WhereStatus bar, chat header, debug panel, run tabs

    A 6-pixel dot says live, fine or wrong; the live one breathes. Tags are tinted, never filled.

    Use it for

    • Say a state in a glance: live (breathing), ok, error, idle.
    src/app/chrome.css
    .dot · .dot-live · .dot-ok · .dot-err
    Idle Writing Done Failed

    Spinners and motion DOM widget

    WhereWherever work is waiting or in progress

    Every indicator that moves, and what moves it. SVG ones animate themselves; the rest are CSS.

    Use it for

    • Placeholder pending: a slow-fading dot. Placeholder working: a turning arc. A pill's icons: a turning clock hand, a breathing mark, a check that draws itself, a floating z, rising dots. Chat: a caret while the agent thinks; a ring while a tool runs.

    When touched

    • All motion stops for people who prefer reduced motion.
    src/app/editor/markers/indicators.tssrc/app/margin.csssrc/app/chat.csssrc/app/pages/NoteIcon.tsx
    Placeholder: waiting (blinkingDot)
    Placeholder: working (spinner)
    Chat: thinking caret
    Chat: tool running
    Read/docs/plan.md
    08

    Keyboard

    Every shortcut, and where it works. On Linux and Windows ⌘ is Ctrl and ⌥ is Alt; the app's own hints name your keyboard's keys.

    ⌘ .Anywhere in the pageAsk the agent: at the caret it adds a completion point; on a selection it opens the request box; on a selected image, the box to change the image (src/plugins/*/index.ts, markerCommands.ts)
    ⌥⌘ YCaret on a suggestionAccept it
    ⌥⌘ NCaret on a suggestionReject it
    ⌥⌘ CCaret on a suggestionChat with the agent that made it
    ⌥⌘ ] · ⌥⌘ [Anywhere in the pageGo to the next · previous suggestion
    escA pinned card, an input, the chatClose it (the request box: cancel)
    ↵ · ⇧↵The request boxSend (an instruction is one line)
    ↵ · ⇧↵The chat's boxSend · new line
    ⌘ ZThe pageUndo, including a decision on a suggestion
    ga · gr · gcVim normal mode, caret on a suggestionAccept · reject · chat
    esc · ctrl-[Vim insert or visual modeBack to normal mode

    Generated from the code. Fonts load from node_modules when this file is opened from the repository.