Releases: modem-dev/sideshow
Releases · modem-dev/sideshow
Release list
v0.11.0
Minor Changes
- 2bc9db6: Return per-surface ids, kinds, and indexes in write responses without echoing surface payload bodies, and remove the redundant top-level
kindsarray. Read kinds fromsurfaces.map((surface) => surface.kind)instead. - 28a3a6d: Add a host-overridable
ss:aside-headslot at the top of the sidebar, above the session list (mirrorsss:aside-foot). Self-hosted rendering is unchanged; an embedder can project a sidebar header — e.g. a workspace picker and a pinned Home link — above the session list. - 71bf606: Add a
hideBrandflag to the embed host contract. When set, the engine omits its own "sideshow" wordmark (the sidebar/header home-link brand) so a host that supplies its own branding — e.g. a workspace picker atop the sidebar and a wordmark in the footer — isn't doubled up. Self-hosted leaves it unset and shows the wordmark as before. - 1b7a28c: Add a
homeViewflag to the embed host contract. When a host owns its own session-less landing (e.g. a "home" feed), the engine no longer auto-selects a session on boot — it honors a deep-linked route session but otherwise stays session-less so nothing is highlighted behind the host's landing, and it clears the selection when the route later becomes session-less. Self-hosted leaves the flag unset and is unchanged (auto-selects the latest session on boot). - 5eba65a: Add a server
onEventfeed tap for hosts and aliveTransport: "ws"viewer-embed option so hosted wrappers can provide hibernation-friendly WebSocket live updates while self-hosted sideshow keeps using SSE by default. - ffe7099: Embed host contract:
onThemeChangenow receives a secondmetaargument —
{ theme, mode }— naming the resolved theme id and light/dark scheme behind the
tokens it already reports. Hosts that re-render surfaces out-of-band (e.g.
server-side preview frames they can't theme from the token values alone) can pass
those identifiers to/s/:id?theme=&mode=to reproduce the exact look; hosts that
only paint from the token values ignore it. Additive — the tokens argument is
unchanged and the default self-hosted host is unaffected.
Patch Changes
- ed8b987: Validate
sideshow surface addhas at least one surface flag before resolving or creating a session, and resolve long-poll waits promptly when clients disconnect. - 7698b1f: Hydrate session post streams from the session list endpoint to avoid N+1 post detail requests on open.
- 23dad90: Lazy-load sandboxed surface iframes to reduce initial viewer work on long sessions.
- 46cf918: Fix markdown/code/diff/mermaid surfaces rendering on a white canvas (washed-out
text) on a dark board. These rich-part frames are sandboxed opaque-origin
iframes, which default tocolor-scheme: normal(light), so in dark mode the UA
painted a white backdrop behind the transparent body. They now pincolor-scheme
to the resolved scheme — like html surfaces already do — so the frame's canvas
tracks the card in both light and dark. - 2bc9db6: List session posts with canonical
surfacesentries that include surface ids and omit elided html bodies. - cc6504c: Slides kit now grid-stacks its deck so it cross-fades in normal flow. Previously
it swapped slides withdisplay:none, which can't fade — so decks were hand-rolled
withposition:absoluteslides over amin-heightstage, an out-of-flow layout the
surface-page height bridge can't measure (the overlay growsscrollHeightbut not
the box its ResizeObserver watches), leaving the frame clipped/frozen. The kit now
stacks slides in one grid cell (in flow, sized to the tallest slide) and fades with
opacity/visibility, so the frame follows it. DESIGN_GUIDE documents the out-of-flow
trap and the grid-stack recipe alongside the existingposition: fixedban. - 2bc9db6: Expose derived 0-based surface indexes on post detail, session post list, and post history read responses.
- 0a094ac: Let direct rich-surface renders without an explicit mode follow the browser's system color scheme.
- 565c85f: Fix intermittent clipping in surface iframes when async content settles after the initial resize pass.
v0.10.0
Highlights
- Added per-surface operations across CLI, HTTP, and MCP, including stable surface ids and add/edit/remove/reorder flows.
- Improved CLI multi-surface publishing: repeated surface flags now work and flag order is preserved.
- Added a system/light/dark color-mode switcher in the viewer.
- Added
GET /api/surfaces/recentfor recent post previews across sessions.
Fixes and polish
sideshow updatenow preserves each surface kind instead of converting updates to HTML.- Fixed configured base paths for uploaded asset URLs and native image/trace surfaces.
- Improved mobile drawer behavior in embedded WebKit viewers.
- Added page title/share metadata improvements and safer CLI handling for ids that start with
-or_.
0.9.0
New
- Post / surface vocabulary — a published artifact is now a post (an ordered list of surfaces). New
/api/posts,/p/:idroutes andpublish_post/update_post/list_postsMCP tools join the legacy ones; all old routes, tools, and keys remain as deprecated aliases. - Open-as-image — each surface footer gains an action to open it as a PNG (
/s/:id.png), live on Workers deployments. sideshow --version— prints the installed version and checks npm for updates.- Sidebar empty-state slot —
ss:aside-emptyis now host-overridable; shows a "Connect an agent" nudge when empty.
Fixes
- Data dir moved to
~/.sideshow/— fixesEACCESundersudo npm i -gand data loss on upgrade; one-time migration from the old package-relative location. - SQLite parent-dir guard — first-run crash when the db paths parent directory doesnt exist.
- Submit-time validation — rejects diffs and mermaid diagrams that wont render.
- Connection cap — held SSE / long-poll connections bounded per workspace (default 32).
- Mobile viewer — improved layout for phone-sized screens.
Breaking (embedders)
identity.accountSlug→identity.workspaceSlugon the injected host contract.
v0.8.0
Minor Changes
- f8fb7b3: Sidebar wordmark is now a clickable home link that clears the session and returns to the board.
- 4822f77: Embeddable engine: add
host.onReady()and stop the empty-board onboarding flash before sessions load. - 760320f: Embeddable engine: add
host.onThemeChange(tokens)so a host can mirror the resolved palette onto its own chrome. - 38992d7: Embeddable engine: expose
layout("stream") andreadonlyon the host contract. - 23be3a1: Link unfurls — bare
/s/:idURLs serve Open Graph + Twitter Card metadata (with a 1200×630.pngcard) so links render rich in Slack/X/Discord/iMessage. - 12bb6b4: Embeddable engine: add a
ss:mainhost-overridable slot wrapping the main content pane. - bd8df08: Screenshot any surface as PNG by appending
.png(supports?mode,?theme,?w,?nocache). - e924954: Breaking (library consumers): rename the data model —
Surface→Post,*Part→Surface,parts→surfaces, plus matching type/Store/helper renames. SQLite boards migrate in place; route paths and MCP tool names are unchanged. - eb2001d: Embeddable engine: add a
ss:session-actionshost slot in the session header (empty by default). - 9da948d: Local Node server now defaults to SQLite (
node:sqlite) — the same store as the Cloudflare deploy; an existingsideshow.jsonmigrates in once.SIDESHOW_STORE=jsonkeeps the legacy store. - f5e89d7: Direct links to a surface open a full-page standalone view (just that surface, no sidebar or feed).
- 5436598: Embeddable engine: publish the theme-token contract as data via a new
sideshow/theme-tokensentry.
Patch Changes
- b60c9a2: Cap the asset-upload body while streaming so a chunked request can't OOM the server (413).
- eb269b5: Cap every request body via a global
bodyLimit, closing the same OOM vector on JSON/MCP endpoints. - ff217bf: The pi extension's tool schema now accepts the
mermaidsurface part kind. - c8f7c68: Input validation: clean 400 on malformed asset base64, cap comment/title sizes, fail fast on non-numeric CLI
--after. - c04a9ac: Mermaid diagrams now fully re-theme on a light/dark flip (arrowheads and text track the active scheme).
- 58c515f: Validate the
openLinkscheme host-side so a surface can't open non-http(s) URLs. - 6e3c1b6: Refresh two README surface-gallery examples (html data table, image SaaS ad); no runtime changes.
- 134a926: Reserve the
usercomment author so surface content can't impersonate the user to the agent. - bd3ea88: Render rich parts (markdown/code/diff/terminal) server-side from
/s/:id?part=N, fixing blank/clipped reloads under a Chrome 149 field trial. - 3752061: Sandbox the
/s/:iddocument with a CSP response header so agent script can't run in the board origin on a top-level load. - 57829c0: Fix an auto-resize feedback loop that could pin a CPU core.
- 7f86b13: Share-link ids are now 11-char url-safe base64 (~64 bits) instead of a 32-bit UUID segment.
v0.7.0
Minor Changes
-
ee75c8d: Embeddable viewer engine —
mountViewer(el, host)(newsideshow/viewer-embedexport) lets a host app embed the viewer. Self-hosted is unchanged. -
a4033cf: Embedders can override the empty-board and sidebar-footer regions via named
<slot>s. Self-hosted markup is unchanged. -
91db9a3: Support deployments mounted below an origin root.
-
3f45e76: New
jsonandcodepart kinds for surfaces.json— a JSON value rendered natively as a collapsible tree (objects/arrays expand on click, type-colored primitives). Like image/trace it's data, not markup, so no sandbox is needed.code— source highlighted with shiki in a sandboxed iframe, with line numbers, an optional filename header, and a copy button.lineStartshows original line numbers for excerpts. CLI:sideshow code app.ts --title "app.ts" --line-start 80.
Also extracts the shared shiki highlighter into
viewer/src/highlight.ts. -
ddbfab2:
SIDESHOW_PUBLIC_READenv var for read-only board access —sessionfor unlisted-link sharing,fullto expose the whole board.
Patch Changes
- 5e3f292: Fix invisible markdown/mermaid/diff/terminal surfaces caused by a Chrome field trial that breaks layout measurement in srcdoc iframes. The viewer now retries the srcdoc parse after 2s if still stuck at minimum height.
- c2e4443: Honor
lineStartin code-part gutter numbers — shiki's<pre>markup wasn't matched by the counter-reset injection, so excerpts now number from their original line. - 3c56cc1: Deep links to
/session/:id/s/:surfaceIdnow scroll to the target surface card. - 84e7057: Reject oversize asset uploads before buffering the body into memory, so a multi-GB upload can't exhaust the heap before the 413 fires.
- 6962019: Fix cursor lag in
waitForComments.lastSeq/agentSeqnow derive from the unfiltered comment list, so an agent reply no longer makes everyauthor=userpoll re-read it and waste a round-trip. - a18f210: Pin surface iframes to the chrome's color scheme so light/dark no longer diverges across the frame boundary (html parts via a
modequery param, markdown/code/comment frames viarenderSandboxedPart). With no mode passed, the OS media query is kept, preserving self-hosted parity. - f0c6cd4: Fix a lost-update race in
SqlStore.updateSurface. ConcurrentPUT /api/surfaces/:idcalls could lose one caller's parts; now uses compare-and-set with retry. - db463ce: Improve intro readme.
v0.6.0
Sideshow 0.6 focuses on richer surfaces, safer rendering, and better agent setup.
Highlights
- Timeline traces. Sessions can show the prompts, reasoning, and commands behind a surface. Claude Code users can install the Stop hook with
sideshow install-hook, or runsideshow trace-syncmanually. - Themes. The board now has seven light/dark theme presets — GitHub, Gruvbox, One, Solarized, Catppuccin, Rosé Pine, and Everforest — applied across viewer chrome, html tokens, markdown/diff highlighting, mermaid, and terminal parts.
- Mermaid parts. Agents can publish Mermaid diagrams directly with
sideshow mermaid,--mermaid, MCP, or HTTP. - HTML kits. Opt-in
issuesandslideskits give agents ready-made, theme-aware building blocks for issue trees, status boards, and decks. Discover them withsideshow kitsorGET /api/kits. - Deep links. Viewer URLs now track the current session and surface (
/session/:id,/session/:id/s/:surfaceId), including back/forward navigation. - Pi extension. Installing the package in Pi adds native
sideshow_*tools for publishing, updating, uploading assets, waiting for feedback, replying, listing surfaces, and fetching the guide.
Agent and viewer polish
- Added
/agent-howtoandsideshow agent-howto; the bundled skill/setup block is now a small bootstrap that asks the running server for current Sideshow guidance. - Changed the default local server from
http://localhost:4242tohttp://localhost:8228. - Sidebar sessions now show agent logos, a surface count, and cleaner metadata.
- The card comment footer is flatter and quieter.
- Comments now always attach to a surface;
sideshow commentrequires--surface. - The agent design guide is shorter and frames kits/theme tokens as optional scaffolding, not a required house style.
Safety and reliability
- Markdown, Mermaid, diff, terminal parts, and comment text now render inside opaque-origin sandboxed iframes, matching html parts and reducing the impact of sanitizer regressions.
- The viewer only accepts host-affecting
postMessageevents from frames it embedded. - Added focused unit and e2e coverage for sandbox isolation, themes, kits, trace ingest, and cross-channel feedback delivery.
v0.5.0
Added
- Surfaces: a published card is now an ordered list of parts, not a single HTML
blob. New part kinds render natively in the viewer alongside sandboxedhtml:
diff(a syntax-highlighted code review from a patch),markdown(prose with
highlighted fenced code),terminal(monospace output with ANSI colors), plus
imageandtrace. Publish any of them across all three tiers — MCP
(publish_surface/update_surface),POST /api/surfaces, and the CLI. - Uploads: push images, traces, and files across all three tiers (
POST /api/assets, theupload_assetMCP tool,sideshow upload/image/trace).
Assets are content-addressed by SHA-256, identical uploads dedupe, and an
asset lives as long as any surface references it. Capped at 5 MB each. - A Claude Code plugin (
plugin/, via a repo-hosted marketplace) bundles the
MCP server, the skill, and a background monitor — browser comments arrive in
the agent as notifications without pasting or re-arming a watcher. Install with
/plugin marketplace add modem-dev/sideshowthen
/plugin install sideshow@sideshow. sideshow watchstreams user comments to stdout, re-arming the long-poll
forever (exactly-once across watch, wait, and piggyback).- A "connect Claude Code" link in the viewer opens an integrations panel with
the plugin install commands and caveats. - A copy button on each comment puts an agent-ready paste block (surface title +
id + comment) on the clipboard. - The npm package exposes a stable
sideshow/serverentrypoint so integrations
can reusecreateApp/JsonFileStorewithout importing private internals.
Changed
- Snippets are now "surfaces" throughout the API (
/api/surfaces,surface-*
SSE events, comments keyed bysurfaceId). The old snippet endpoints and
publish_snippet/update_snippettools remain as back-compat aliases; stored
boards migrate in place on load. - The session sidebar groups sessions by recency (Today / Yesterday / Earlier),
and sessions with no surfaces yet are dimmed and sunk to the bottom. - The viewer is framed around leaving comments rather than messaging an agent —
composers read "Leave a comment…", with no delivery receipts or "listening"
indicators. - A surface card's open and delete actions are now minimal Lucide icons.
sideshow-termauto-starts a local server when needed (baresideshow-term
opens the watcher, default port 4243), supports mouse input, and gains
clear/clear --all.
Fixed
sideshow-termhardens STML parsing/rendering for untrusted markup (tested
entity decoding, bounded size/depth, neutralized control characters, render
failures degrade to an in-view error).- Local JSON storage shares a single cold-load promise across concurrent first
requests, fixing a race that could overwrite persisted board data. - The viewer shows a neutral "refresh sideshow to update the viewer" hint for an
unrecognized part kind instead of a broken-diff error. - Malformed
POST/PUT /api/surfacespart payloads are rejected before they
reach storage. sideshow-termcan be packaged and installed standalone (declared server
dependencies, reuses thesideshowserver core, runs built JavaScript).
v0.4.0
Added
- Cmd+Option+Up/Down switches between sessions in the viewer without reaching
for the sidebar — Down moves to the next session in the list, Up the
previous, wrapping at the ends. - The viewer notices new releases: a dismissable banner in the sidebar names
the latest version with a copyable upgrade command (npm install locally,
redeploy for workers), and the release notes render as a card at the top of
the stream. Dismissing either hides both until the next release. The check
lives server-side at/api/version(npm registry + GitHub release notes),
is cached for six hours, and fails silently — offline costs nothing but the
absence of the notice. - The CLI now runs on Windows: session detection walks the process tree with a
single PowerShell call instead ofps, andsideshow serve --openlaunches
the browser viacmd /c start. macOS and Linux are unchanged.
v0.3.0
Added
- A session thread at the bottom of each session in the viewer: a composer
for messaging the agent without picking a snippet. - Feedback now reaches agents without polling: publish/update/reply responses
carry auserFeedbackarray with any comments the user left since the
agent's last call (delivered once; a consumedwaitalso counts as seen). - The design guide, setup block, and Claude Code skill teach the background
watch pattern: armsideshow waitas a background process after publishing
and react when it exits, instead of blocking or polling. - Agents can name their session at creation:
sessionTitleon the publish
body and both MCPpublish_snippettools,--session-titleon
sideshow publish. Applied only when the publish creates the session —
it never overwrites a title, including renames made in the viewer. - A snippet kit baked into every snippet doc, so agents publish compact
markup instead of hand-written inline CSS: barebutton/input/select/
textareapre-styled to match the viewer, SVG utility classes (t/ts/
thtext presets,box,arr,leader,node,c-*color ramps with
dark-mode-aware text), and a shared#arrowmarker injected into every
doc. The design guide documents it as a compact reference table.
Changed
- New snippets no longer steal the scroll position: the viewer only follows
them when already at the bottom of the stream, and shows a "new snippet ↓"
pill otherwise. - Activity the user isn't looking at — another session, or any session while
the tab is hidden — badges the tab title with an unread count. - The Claude Code skill now documents the repo-local CLI fallback and a
checkpoint-drain feedback pattern for harnesses that cannot surface
background watcher output.
Fixed
- Feedback was re-delivered when channels were mixed: a fresh
sideshow wait
process (or restarted stdio MCP server) started from seq 0 and replayed
comments the agent had already received via piggyback or another channel.
author=usersession reads with no explicitafternow resume from the
server-side agent cursor, and the CLI and stdio MCP keep no cursor of their
own — delivery is exactly-once across CLI, MCP, and piggyback. Pass
--after <seq>(CLI) orafterSeq(MCP at/mcp) to deliberately re-read. - A comment that failed to send was silently lost (input cleared, no error).
The viewer now echoes comments immediately (pending until confirmed) and on
failure restores the text to the input with an error toast. - After an SSE reconnect the viewer refetches the selected session, so
snippets and comments that arrived during the gap can no longer be
silently missing from a live-looking board. - The viewer layout no longer breaks at phone widths: below 700px the
sidebar collapses into a drawer behind a slim top bar (hamburger toggle,
unread dot), the stream takes the full width, and hover-only actions
(card open/delete, session delete) stay visible on narrow or touch
screens. - Comments not attached to a snippet (e.g.
sideshow commentwithout
--snippet) were stored and delivered to agents but never shown in the
viewer; they now render in the session thread. - The viewer is now usable by keyboard and assistive tech: session rows are
focusable and activate with Enter/Space (focus survives live re-renders),
hover-only actions (session delete, card open/delete) are reachable and
shown on focus, the editable session title is labeled and Escape cancels
an edit, snippet iframes carry the snippet title, and toasts are announced
via a polite live region.
v0.2.0
Added
sideshow demoseeds two example sessions (a sequence diagram with a
comment thread, an interactive explainer, a metrics card) so the viewer can
be explored without an agent.