Releases: cfpperche/picode
Release list
v0.3.1
PiCode v0.3.1
Fixed
- The tray reopens the shell again. Closing the shell window destroyed it
instead of hiding it, so tray click and Open PiCode silently did
nothing. Close now hides the window; reopening returns to the same page. - No more console window beside the shell. The shell built as a console
app, so every start opened a terminal window titled with the exe path that
lived as long as the tray icon. It now builds as a GUI app (debug builds
keep the console).
v0.3.0
PiCode v0.3.0
Added
-
Terminals appear in Agent permissions (ADR-0143): the section now lists
the terminals you started in PiCode beside the managed agents — name, tier
and domains, with the same editor — and says plainly that apistarted
outside PiCode has no identity and always reads the tab on screen. -
Muse Code and Antigravity accept native handoffs.
Continue in…
now offers them innativemode, not justbrief: the conversation
lands as a session their own CLI lists and resumes (Muse: an index row
plus a session log; Antigravity: a summaries row plus the brain
transcript). Both were proven against the real CLIs, including a
same-shape round trip before the write counts. -
Terminals are listed as principals in the browser grants API (ADR-0143):
GET /api/browser/policiesreturns each terminal with its effective grant,
andPOST /api/browser/policyacceptstermbesideagent— the key
carries the namespace (term:<id>), so a terminal can never widen an
agent's grant or the other way round. The settings rows that show them are
the next slice. -
One release, two binaries, one resident to swap (ADR-0142, slice 3).
The release workflow buildspicode-shell-windows-amd64.exebeside the
Go binaries (Rust + cargo-xwin recipe, proven on a fresh Ubuntu 24.04
container) and stamps the tag into the shell.picode-desktop update
downloads both exes, verifies them againstSHA256SUMS— refusing an
unverified binary like the daemon's updater — and swaps both or neither,
rolling the tool back if the shell fails.scripts/desktop-swap.sh
relaunches whoever thePiCodeDesktoptask points at (tray today, shell
after the migration). -
Terminal agents identify themselves to the built-in browser (ADR-0143):
thebrowsertool now sends the house identity tuple — managed agent id
first, then the PiCode terminal id — and the daemon resolves a terminal's
own grant (browser.policy.term:<id>) beside the existing per-agent key.
A caller with neither stays read-only on the tab on screen. -
The shell tray reaches disk parity (ADR-0142, slice 2). The tray now
shows the disk line (WSL … · ≈… held · C: … free, with thelow
warning), a Give-back item with the readiness interlock, an explicit
stop-the-distro confirmation and a measured result, plus Restart PiCode
and View logs — every duty the Go tray menu owned. One board composes
status, disk and tooltip so no timer erases another's write; the
keepalive re-arms itself after a compact. -
Antigravity launch is editable. Same honest shape as Muse Code in
the previous slice: real defaults editor, profiles, the Customize
checkbox and the row menu's Launch settings. No hook surface in
its build either, so Activity reporting stays off with the one-line
note andintegration: trueis refused. -
ADR-0143: terminal agents are principals in the browser permissions —
the identity tuple (managed agent → terminal → unmanaged), the
term:<id>grant key and the decision table behind it. -
The shell is becoming the only Windows resident (ADR-0142, slice 1).
picode-shell.exenow holds the WSL distro open with a supervised
keepalive, polls daemon health every 5 seconds, and reports it in a tray
status line and tooltip — the duties the Go tray owned.--hiddenstarts
the resident with no window (the logon-task mode); a second launch brings
the window up.picode-desktop startup-repair --retarget-shellmoves the
PiCodeDesktoptask to the shell, refusing foreign tasks and missing
executables; plain repair now accepts either resident. -
Muse Code launch is editable. Its Launch tab has the real defaults
editor (executable, arguments, PATH, environment), profiles, the
Customize checkbox and the row menu's Launch settings — the gaps in
the terminal···menu are closed for Muse. Sessions and resume are
unchanged. -
JavaScript (Settings ▸ Browser ▸ Browser permissions): sites may use
JavaScript — on by default, applied to every open tab at once and to the
ones created later, through the platform's own setting. -
ADR-0142: the shell becomes the only Windows resident. The Go systray
(picode-desktop.exe --tray) retires;picode-shell.exetakes autostart,
the WSL keepalive, health/disk polling and the single tray icon, while the
Go binary stays as the headless CLI tool the shell drives. Window close
hides, tray Quit exits. Migration runbook in
docs/plans/retire-go-tray.md. -
Site settings (Settings ▸ Browser ▸ Browser permissions): one dialog
with the six kinds that matter — camera, microphone, location,
notifications, clipboard, autoplay — each set to Allow, Block or
the platform's own default, applied to every site through the shell's
policy, plus Recent decisions: every standing the browser recorded,
with the site, the kind and a Reset. Until the Ask prompt lands, a kind
with no choice follows the platform's default (deny), which the dialog
says plainly. -
Site permissions, the shell half (Settings ▸ Browser): every tab now
answers permission requests — camera, microphone, location, notifications,
clipboard, autoplay, sensors, MIDI, fonts, file system — from the policy
the user set (btab_set_permission_policy), and reports each outcome as
btat://permission. The app records the standing through the daemon's
API, so the Site settings dialog has real data to list and edit. -
Site permissions, the data half (Settings ▸ Browser): the daemon now
keeps one standing per site and kind — camera, microphone, location,
notifications, clipboard, autoplay, sensors, MIDI, fonts, file system —
withGET/POST /api/browser/permissions,DELETE /api/browser/permissions/{id}andPOST /api/browser/permissions/clear
(optionally one kind), all tested, on migration 050 and the events
invariant. The shell feeds it and the Site settings dialog reads it in the
next slice. -
Muse Code and Antigravity sessions can be continued elsewhere.
Both are now handoff sources:Continue in…appears on their session
rows, offering every CLI that can receive the conversation. Muse reads
through its ownexport --session(official transcript); Antigravity
reads the CLI's per-conversation transcript, deliberately not the
SQLite protobuf (unversioned field numbers). Reasoning never travels;
oversized sessions fall back to the brief, which both already support. -
Muse Code and Antigravity can receive a brief handoff.
Continue in…
(on a session row, a terminal row, or the pane menu) now lists them as
destinations: the conversation travels as an opening brief —
muse "<brief>"starts the session with it,
agy --prompt-interactive "<brief>"does the same. They are the first
prompt-only targets (no native session import yet), sobriefis the
only mode offered until their writers land. -
Downloads (Settings ▸ Browser): Location shows where the built-in
browser saves files (the system Downloads folder until changed), with a
Change dialog; "Ask where to save downloads" decides between a save
prompt and writing straight to the folder; Download history lists every
file with its size, time and outcome, searchable, with Open file /
Show in folder / Copy path / Remove per row and a two-step Clear all. -
The shell reports each download (start and outcome) through
btab://download; the list lives in the daemon store
(GET/POST /api/browser/downloads,POST /api/browser/downloads/status,
DELETE /api/browser/downloads/{id},POST /api/browser/downloads/clear). -
Every Agent CLI now shows the same tabs. Launch, Terminals, Sessions,
Providers, Settings, Keyboard, Packages and Connectors appear for all of
them, so the pane has one shape instead of three. The tabs a CLI has no
native editor for — today all of them except Pi — say
"… for are in development — coming soon" instead of pointing at Pi,
and a deep link on a phone scrolls its own tab into view. -
The tmux app shows the machine's tmux servers. A new Sockets tab
lists every tmux server this instance can see — the default socket, every
named one, and PiCode's own dedicated socket — with what each holds: N
session(s), how many are PiCode's, and whether anything is listening (a
socket file with no server is labelled as the leftover it is). The tab
badge counts the running servers, and the row for PiCode's own socket says
where new terminals will land. -
Custom provider form: per-model display name, input (
text,
image) and cost (USD per 1M tokens, all four rates or none), a
streaming usage compat flag, and a provider string per thinking level
(xhigh→high), so a gateway likemeta-aiis fully describable in
the GUI — no hand-editedmodels.json. Clearing a row field removes the
stored key; Edit prefills everything the file holds. The API key flow is
unchanged: a literal credential intoauth.json, exactly as
cheaperinference. -
Servers in the inspector rail: what is listening on this machine, who owns it (the PiCode terminal or agent whose process holds the port) and what the page calls itself, with one Open that shows it in PiCode's own browser tab.
-
A loopback URL printed in a terminal (Ctrl+click, or the pane menu's Open …) opens in PiCode's own browser instead of the system browser — unless Browser settings says local development sites should open externally, in which case nothing changes.
-
Without the desktop app, that browser tab renders a page from this machine in a frame, with one line saying so, and its address survives a reload.
-
POST /api/browser/history/deleteremoves a selection of visits in
one transaction. -
PiCode terminals get their own tmux server. Each instance runs tmux on
a socket inside its data directory (~/.picode/tmux.sock...
v0.2.0
PiCode v0.2.0
Added
-
Matrix: a managed agent's panel is now its live conversation. Where a managed agent's panel said Managed agent — open to read., it shows what the agent is saying as it says it — the same turns, tool cards, diffs and markdown its tab shows, scrolling itself, in a read-only layout with no composer and no queue controls. When the agent is waiting on a person the chip says Needs you, the body shows the question and the choices it offers, and a line across the bottom of the panel carries it with Open, which takes you to the tab where you answer. The chip comes from the fleet, not from the panel's connection, so a panel that is asleep, paused or zoomed down to a name-plate still tells you which agent is blocked.
-
Link two Matrix panels, and the two sessions can message each other
(ADR-0116). On a matrix canvas, hover a panel and drag the connector in
its header onto another panel. The line grants exactly one thing: those
two sessions gain each other as a contact in PiCode's existing messaging
(ADR-0104). One can send the other a message and read the replies — that
is all it does. -
A link never grants a transcript. It does not let one session read the
other's history, scrollback, session file or anything typed into it. The
supported way to get context out of another session is to ask it and let
it answer in its own words. The guide says so in plain words. -
Two sessions in different project folders can now be paired, per pair,
by hand. The workspace rule is unchanged and there is no owner-wide
switch: the blast radius of a link is two named sessions you drew a line
between. -
Nothing is connected quietly. Drawing a line to a session that is not
connected offers the existing connection in one line, with what it grants;
drawing across two project folders asks again, separately, naming both
folders. Cancel at either point writes nothing at all — no link, no
connection. -
Removing the line removes the permission, with nothing left over:
PiCode derives who may message whom from the links that exist right now,
so deleting the line, either panel, or the matrix revokes it immediately. -
A link that grants nothing reads broken, in amber and marked
Broken, with the reason when you point at it — the connection was
revoked, the session moved, the target is gone, or it was never connected.
It is never a faded version of a working link. -
Matrix links, in the Messages view. Every link you have drawn,
anywhere: both ends, the matrix it lives on, whether it works right now,
and a Remove that revokes it exactly as the canvas does. It is not
filtered by the folder picker, because links across folders are the ones
worth seeing. Grid mode, which has no plane to draw on, shows a per-panel
link count in the header and sends you here. -
Matrix: a panel can be a pinned note. Add one from Add panel →
Pins: the panel shows that pin's markdown, read-only, follows it as
you edit it elsewhere, and its header opens Pin Studio. A note whose pin
was deleted says so and offers Remove, the way a deleted terminal does. -
Matrix: a panel can be a file. Add panel → Open files offers
the files you already have open in a tab; the panel is the same editor,
with Save. It says Unsaved while you have changes, keeps them when you
maximize it or switch layout, and never goes to sleep holding them. -
Matrix: a panel can be the changes to a file. The same list offers
each open file as Changes to an open file: the panel shows that
path's diff and keeps it current as the file changes, with Open file
to jump to the editor. One file can be on a matrix twice, as the file and
as its diff. -
The Matrix canvas — your panels on a plane you pan and zoom. A matrix header now has a Grid | Canvas switch. On a canvas a panel goes anywhere: drag it by its header, resize it from any edge or corner, drag a box around several and move them together, pan with the middle button or by holding Space, zoom with the wheel or the
+/−buttons, and0fits everything on screen. A minimap in the corner shows the whole plane. The arrow keys still move between panels — an off-screen one is brought into view — Enter still starts typing in that panel's terminal, and Delete still removes it with an Undo. Switching to the canvas converts the whole matrix in one step and switching back packs it into the 12 columns again (it asks first, since the plane positions are not kept). Where you left the camera is remembered per browser, so two people looking at the same matrix never yank each other's view. -
Zoomed out, a panel shows its last screen instead of a live one. Below about 75 % a panel stops being a connected terminal and shows the text of the screen it last had — sharp, free, and stamped with its age in the header if the panel has done something since; below about 40 % it becomes a name-plate with the face, name and status, sized so it stays readable however far out you are. Zoom back in and the same terminals reconnect where they left off. That is what lets a canvas hold hundreds of panels without hundreds of connections.
-
A terminal takes the mouse at 100 % only, and says so. A terminal panel is readable and typeable from 80 % up, but a click is only accurate at 100 %: below it the terminal would put your click on the wrong cell, and with mouse reporting on that wrong cell reaches the program running inside. So away from 100 % the panel body does not take clicks — clicking it zooms the canvas back to 100 % first, and then your click lands where you aimed it. The zoom percentage sits next to the minimap and takes you back to 100 % in one press.
-
Tidy. The matrix menu gains Tidy panels on a canvas: it lays them out again in reading order, keeping each panel's size, and saves once.
-
Mobile: Back from an agent or terminal lands where the work lives. A workspace's agent or terminal returns to Workspaces focused on that workspace's group; a free one returns to its own Agents or Terminals list — never a flat section it was never in.
-
A matrix can be a canvas, from the API. Every matrix now has a layout mode: the 12-column grid it has always had, or a
canvaswhere panels sit on a plane with no columns and no bottom — coordinates in 8 px units that may run negative.PATCH /api/matrices/{id}takesmodeand answers with the matrix plus every panel it moved: switching converts the whole matrix in one step (a grid cell becomes 8 units across and 3 down; coming back divides, rounds and tidies the panels so none overlap and none is lost), and switching to the mode it already has changes nothing. Matrices made before this keep the grid. There is no canvas to look at yet — the panels, the mode switch and the pan-and-zoom surface are the next step; this release is the model underneath, exercised by tests. -
Fullscreen hands the browser's keys to your agent. In a normal window the browser keeps its reserved shortcuts (
Ctrl+Tnew tab,Ctrl+Wclose tab,Ctrl+Nnew window) before PiCode can see them — so a CLI chord like Codex'sCtrl+Topened a browser tab instead. Fullscreen mode (Ctrl+Shift+Enter) now also locks the keyboard (Chrome/Edge/Opera): every key reaches the page, terminals get their chords back,Escapestill leaves the mode outside a terminal, and holdingEscapefor about two seconds is always an exit. Firefox and Safari keep the previous behavior until they support the API. -
Fullscreen: any tab can take the whole window. Right-click anywhere in the desktop app — a terminal, an app, a file, the conversation — and choose Fullscreen (
Ctrl+Shift+Enter,Cmd+Shift+Enter, or the command palette). The sidebar, the tab strip and the Inspector rail step out of the way and the tab you are on fills the screen. Nothing is closed: touch the left edge with the pointer and the sidebar slides back over the page, the top edge brings the tabs back — with a Leave fullscreen button at their right end — and the right edge brings the Inspector back if it was open when you started. Each edge waits a moment before opening, so crossing it on the way somewhere else does not flash it, and it stays while the pointer is on it. Esc leaves. The mode is remembered per browser, so a reload comes back into it, and it is offered on every tab except the git graph's own commit menu. -
The browser goes fullscreen too. Turning it on also asks the browser for real fullscreen, so the app is the whole screen and not just the whole page; leaving gives the window back, and if you exit fullscreen yourself (F11, Esc) the mode ends with it. A browser that refuses fullscreen still hides the app's own chrome. A reload cannot ask for fullscreen — there is no click to ask with — so it returns to the in-app mode, with the top edge still there to leave from.
-
Matrix — a live grid of your agents and terminals. The Apps tab has a Matrix tile: create a matrix, add panels from a picker of your agents and terminals, drag them by the header and resize them by the corner or an edge. Each panel shows the real terminal or agent screen — the same one its tab shows — with the sidebar's Working / Needs you / Ready word in its header. Only the panels near what you are looking at stay connected, so a matrix can hold hundreds; layouts save as you go and every browser sees the same matrices (
#/app/matrix/<id>). The guide is Matrix. -
Keyboard across a matrix. Click a panel or tab into one, then move with the arrow keys (the target scrolls into view and wakes up), Home and End for the first and last, Enter to start typing in that panel's terminal, Shift+Esc to come back out to the panel, Delete to remove it with an Undo. A plain Esc still belongs to the program in the terminal.
-
**Maximize a panel.*...
v0.1.0 — Bootstrap (M0)
First public release: repository, living documentation system (architecture, philosophy, benchmarks, handoff, ADRs), Pi agent harness (AGENTS.md contract + quality-gate/uiux-review/handoff-update skills), Go server skeleton with embedded UI, CI on 3 OSes.
Moat: Pi users control their agents from the moment of creation.