Repository navigation
Orbit Pi 0.2.13
Added
-
Optional sidebar message previews. The sidebar view menu's Show first
message toggle hides or restores the first-message line in grouped and flat
session lists. Enabled by default, remembered across restarts, and leaves titles,
metadata, session content, and actions intact. -
Branch pickers show when each branch last moved. Every row carries the
age of its tip commit (3d ago) in a right-aligned column: in the status-bar
branch popover the dates read as a timeline, newest work first, with the
current branch marked by an accent glyph and a check in a slot every row
reserves so the dates never shift; the header counts what the filter found.
The Git panel's branch menu dates its Recent, Local, and Remote sections the
same way (the age is the row's last element, so all dates share one right
edge next to theCurrentmarker or the hover delete), and remote refs now
carry their tip date inlist_refs. Filtering still matches branch names. -
Session execution status in the sidebar. Open and background sessions show
Running, Waiting for approval/input, Retrying, Compacting, Completed, Failed,
Stopped, Disconnected, or Idle from real pi events. Completed/Failed/Stopped
remain after opening a result and after warm-process reaping for this launch.
Historical and external sessions have no guessed status until observed.
Onlyagent_settledfinishes a run, and its abort flag distinguishes a stopped
run even when no assistant message was produced. Native approvals, dialogs,
and questionnaire answers now stay with their session when switching away;
requests arriving in the background wait for the user instead of being cancelled. -
Mermaid flowcharts render in the transcript. A
flowchart/graphfence
(TD/TB, BT, LR, RL) now paints as a diagram — nodes, shapes, orthogonal edges,
arrowheads, and edge labels — drawn with GPUI paths and text, so there is no
webview, no JavaScript, and no network involved. The fence is still a code
block underneath: the copy button and a Show source disclosure keep the
exact Mermaid source selectable, and anything outside the supported subset
(sequence/gantt/pie/class diagrams) keeps the existing source block rather
than drawing a partial graph.subgraph … endgroups render as titled frames,
and an edge that skips a rank routes around the boxes instead of through them.
Layout is cached per fence and interface font, so a streaming run re-renders
the same diagram for free. -
A session that finishes while you are not looking stays marked. Its sidebar
row carries an unread mark — a green eye and "Needs review" for a finished turn,
a red cross with a small corner dot for one that failed — until the session is
actually shown in a foreground window. That mark then gives way to the read
glyph, while a separate execution state distinguishes Completed from Failed and
remains after the mark is spent. The mark is what is left after the toast has
gone: with several sessions open, or after stepping away, the finished one is
findable instead of merely somewhere in the list. It is independent of the
running, pinned, and archived glyphs (it never replaces one) and a marked row
stays visible under a collapsed project group, the same way a running row does.
Opening the session spends the mark; selecting it while Orbit is behind another
app does not, because that is not reading it, and neither is settling behind a
full-page surface (Files, Git, Usage, Worktrees, or a full-width Review).
Marks live in memory only — what happened while Orbit was closed is not claimed,
since there is no way to know whether it was already read elsewhere. The labels
distinguish a finished turn from a failed one without relying on colour. -
Onest interface font — available in Settings → Appearance → Interface font,
bundled in Regular, Medium, SemiBold, and Bold weights for offline use. -
Git page → commit bar → model chip: the Generate button now chooses its
own model instead of always borrowing the chat session's. Commit messages are a
short, cheap task, so a small local model is often enough, and a model with a
different context window changes how much of a large change set fits the prompt.
The chip opens a searchable catalog with each provider's mark, an
Active session model row that restores the default, and ↑/↓/Enter/Escape
navigation; the pick persists to~/.orbit-pi/commit-model.json, and the prompt
budget is sized from the picked model's own window. Issue and PR draft generation
keeps using the session model. -
Attachments in the composer — images, non-image files, and collapsed long
pastes now share one tray above the input. Each item is a chip leading with the
same 20px slot — the image thumbnail, or the file type's devicons mark — then its
name, its size or line count, and its own remove button; the text sits in one
line_height(1.)box and the chip's insets are symmetric, so the mark and the label
share one centreline with balanced edges. The file mark is drawn bare, with no tinted
square behind it — a rounded square behind a glyph whose art is itself a box read as
an avatar monogram, not a file icon — and it is centred by its ink rather than its
line box, because glyph artwork is not centred inside its font cell. The type's short
label (MD,PDF,ZIP, …) on a tinted square fills the slot when no Nerd Font or
no glyph is available; two or more chips add a count header with Clear, and all three kinds
share one eight-item budget that the send button and the paste/drop paths read
through a single predicate. Attaching a file queues it as a chip instead of
splicing its path into the middle of the message; on send it folds into the
prompt as an@pathmention (relative to the workspace, backticked when the
path has whitespace) so the agent opens it with its own tools. The sent user
message reads that block back out of its own text and renders it as the same
file chips under the bubble — the path stays selectable — so an attachment no
longer appears as a raw@/Users/…line, and a reloaded session shows the same
chips because the split is derived from the message, not from local state.
Re-attaching the same path is a no-op, and a file-only message is sendable. -
Appearance → Design system, an opt-in switch between the existing Classic
design and the new Operational (Restrained Operational Minimalism) system.
Operational adds dark and light near-black/neutral palettes with a lime
interaction accent, a separate olive selected-row wash, tighter radii, 11px
captions, and flatter elevation. The choice is persisted alongside the existing
Light/Dark/System preference; switching back restores the previous Classic
palette, and every Classic palette and geometry stays unchanged. -
Settings → Agent → Agent call details chooses whether a tool call or
activity group you have not opened yourself follows the run (the previous
behavior: open while streaming, closed once the turn settles), stays always
expanded, or stays always collapsed. Opening or closing one call yourself
still wins over the setting, which only moves the default. Persisted to
~/.orbit-pi/agent-calls.json.
Changed
-
Refined session navigation. Tinted project marks, tonal count and status
badges, clearer title/preview hierarchy, and distinct selection and keyboard
focus outlines. Provider marks overlap less, and truncated titles, prompts,
and branches have tooltips. Existing session information and actions remain. -
Session rows carry three lines. Title, the first message, and a metadata
strip — age, workspace, and branch with↑n/↓nagainst its upstream (green
ahead, amber behind). The message line always shows the prompt, because the
title is capped and the row is narrower still: a title that happens to be the
same sentence is cut short, not redundant, so the message is the only place
the ask reads end to end. Branches are fetched off-thread per project (git branch+rev-list, one pair at launch and whenever the project list or the
current checkout changes), so painting a row never shells out. A project that
is not a git repository has no branch item rather than an empty slot. The
workspace item appears in the flat list only — under a project header it would
repeat the header one line up. -
Session row actions moved to the right-click context menu. The
hover-revealed…is gone, so the title owns the full line width; pin,
archive, copy path, reveal, clone, and delete are all on the context menu
(the palette still carries its own commands). The keyboard and palette delete
paths anchor the same confirmation to the row instead of to a button that no
longer exists. -
Sidebar project names no longer look like the session titles under them. A
group header takes the palette's accent hue at body-ink brightness — a quiet
warm cast by default — or, when the project has a mark tint, that hue on its
name and not only on its icon. Session titles stay a step below at secondary
ink. The three sidebar levels now read as section label, project, session
instead of one wall of identically colored rows. -
Standardized corner radii by component role: buttons and header chips use the
button token, text fields and composers use the input token, cards/panels/
popovers/dialogs usepanel::RADIUS, list rows uselist_item::RADIUS, and
badges/checkboxes use the small radius. Fixed the outliers (header controls,
the top-bar quota/usage chip, terminal and file-viewer tabs, the Worktrees
dismiss button, MCP row action, star-project banner, several alert/preview
cards, and the Git commit composer).
Operational now gives every standard field and composer one input radius;
Classic keeps its legacy composer silhouette. -
The Usage page is now one continuous page instead of a Simple | Details
switch: the Daily-activity calendar leads, then the Summary board, Usage
over time, Breakdown, and Records read top to bottom in one scroll, with
each section's own selector (chart metric, breakdown dimension, records
table) inside its card. Summary figures are larger, and the metric the
trend is currently plotting is picked out in the accent color on the board,
so the click-through from a figure to its chart reads before it is made.
Removed
- Usage: the trend's duplicate Buckets data table, the Signals notes card,
and the Token health panels are gone. Their headline figures live on: cache
hit rate is a Summary metric, every metric still plots on the trend chart,
and the day/week/month table remains under Records. The JSON export no
longer carries theinsightsblock.
Fixed
-
Auto session titles now actually land. The bundled title extension decided
a session was worth naming only when its branch held exactly one user prompt at
settle time, and it treated a settle with nothing to describe as final:- sending a steering message or follow-up during the first run added a second
prompt, so the settle looked like a resumed session and no title was asked for; - a session Orbit reopened from disk (its warm-process pool makes this the
normal case) was permanently ineligible, however untitled it was; - one transient provider error was enough to lose the title for good — the
"retry on the next settle" path needed another settle with one prompt,
which a new prompt makes impossible, so the retry was dead code; - a settle that arrived before the assistant had produced any text wrote the
session off for the life of the process.
The rule is now the one a reader expects: any session without a name gets a
title, from its first exchange, on the first settle that has something to
describe. An existing name is never replaced (that is the user's rename or an
earlier title) except by the details popover's explicit Generate title. A
settle with no reply yet leaves the session open for the next turn, and a
transient failure is retried up to three times instead of once. A completed ask
that produced no text is still final, so a model that keeps answering nothing is
not asked on every turn. - sending a steering message or follow-up during the first run added a second
-
The status bar no longer prints extension color codes as literal text. An
entry set withctx.ui.setStatus()that styled itself viactx.ui.theme.fg()
used to render the raw SGR escape (e.g.[38;5;71m●[39m), because the status
line drew its string verbatim. It now passes through the same ANSI parser the
extension-widget path already uses, so the codes are stripped and the entry
reads● ADHD ONas intended. -
The Git page's Generate button now writes a commit message that describes
what the commit actually records, including long files. Four things were
wrong: the prompt always read the index (git diff --cached) even when
Include unstaged changes was on, so most of a worktree commit arrived
labelled "context only, not part of this commit" and untracked files arrived
as a bare path with no diff at all; ORIGINAL CODE was the first 48 KiB of the
HEAD file with no line numbers, so a change deep inside a long file had no
surrounding code to read; diffs were capped per file but never in total, so
a set of long files overflowed the model's context window and silently
became the filename-based fallback; and every body line was rewritten into a
-bullet, mangling the headings and footers a long change produces. The
prompt now picks its diff source from what the commit will record
(synthesizing untracked files' diffs), windows a line-numbered ORIGINAL CODE
excerpt around each hunk, sizes the whole prompt from the selected model's
context window so a commit of a hundred-plus files still gets a diff for every
one of them (and keeps each long diff's first and last hunks), and passes the
model's fenced message through verbatim. Regenerating now tells the model
about the previous attempt, so it stops repeating the message you rejected,
and a fallback is reported in the failure banner instead of being passed off
as generated. SetORBIT_COMMIT_PROMPT_DUMP=/tmp/prompt.txtto write the exact
prompt the model sees. -
The Usage page's daily-activity calendar no longer lets its hover readout
paint over the shade key. Hovering a day in the middle of the grid pushed
the readout past the bottom of the calendar, where it covered the "Less /
More" legend and the text under it. The readout now sits beside the day
under the pointer and is clamped inside the calendar, so the hovered day
stays visible and the readout never reaches the legend or the section
below. -
A failed command or shortcut no longer leaves Orbit stuck on a banner that
never clears and a session that answers nothing. A failed write to pi's stdin
used to kill the writer thread for good while the process kept running, so
the app still reported it alive and every later command and shortcut went
into a pipe nobody read. The dead transport is now reported as an exit, so
the reconnect action appears instead of a zombie session, and the app no
longer leaves a response waiter behind for a command that never landed. -
An error banner now clears when the thing that raised it succeeds, decided by
the raising command rather than by matching the banner's text. Failures whose
wording never matched a command label — a failed write, or a banner raised
under one language and read under another — used to stay up indefinitely. -
Stopping or restarting pi now drops that process's modal dialog, approval
bar, queued messages, and retry counter with it; the dialog could never be
answered, and its reply would have gone to the process that replaced it. -
Extension UI left over a dead pi process is dropped with it. A
custom
surface (what a command like/reviewopens) stayed on screen after the
process that owned it went away, swallowing keystrokes into a client that
could never answer it, and a compaction or title command in flight kept the
composer on Stop becauseis_compactingstayed set. -
Commands pi runs itself no longer leave the app "working" forever. A slash
command pi hands to an extension (/review) answerspromptwith
disposition: "handled"and starts no turn, but the composer had already
armed the live "Working for…" row at the send, so the row and the Stop button
stayed up with nothing that could ever clear them — cancelling the command's
custom UI could not help, because there was no run to settle. Only the
composer's own prompt is unwound this way: the title regenerator sends a
prompttoo, and regenerating a title mid-run used to close the live row and
the checkpoint turn of the run that was still streaming. -
Cancelling a run no longer reports it as a failure. pi answers a stopped
automatic retry withauto_retry_end { success: false }, which the app read as
a failed retry and left on screen as a banner; the request itself now decides,
so a stop is a stop and an exhausted retry still reports. That applies to the
Retry strip's Cancel button as well as to Escape. -
A pi process that exits mid-session is respawned automatically, so the next
command or shortcut lands on a live process instead of a toast saying nothing
is running. The respawn is bounded (three consecutive tries, a budget a
healthy run refills) and yields to a Start or Stop in the meantime, so a pi
that is broken on startup shows the Reconnect banner instead of crash-looping.
It also comes back on the session that was open: a fresh launch opens a new
one, which would have left the transcript showing a conversation pi no longer
had and the next prompt reaching a model with none of it. Restart and
Reconnect do the same. -
A pi process that dies at launch now says why. The banner carries pi's own
last stderr line (redacted, clipped to one line) instead of only "pi process
exited", which read as a connection problem even when the launcher never
connected to anything. The case it was hiding: a bundled.appstarts with a
minimalPATH, and pi's#!/usr/bin/env nodelauncher exits with
env: node: No such file or directorywhennodelives under nvm, fnm,
volta, mise, or asdf. The childPATHnow includes those install dirs (the
newest nvm/fnm version, and pi's own managed node), and every spawn that
needs node — the RPC session,pi update, the MCP probe, the RPC patcher —
resolves it from a.applaunch. Settings → Runtime's stderr panel redacts
known MCP secret values before showing the child's lines.
What's Changed
- fix(runtime): recover from pi exits and clear stale per-process state by @imrj05 in #87
- feat(git): give commit-message generation its own model picker by @imrj05 in #88
- fix(status-bar): strip ANSI from extension status text by @imrj05 in #89
- Render mermaid flowcharts and subgraphs natively in transcript by @imrj05 in #90
- fix(mentions): search workspace files with fd by @JoyPanda in #93
- fix(transcript): copy a selection with ctrl+c on windows by @JoyPanda in #92
- Show session review and execution status in the sidebar by @rj05xdev in #94
New Contributors
Full Changelog: v0.2.12...v0.2.13