Summary
The MCP/HTTP API can publish a post with any list of surfaces — repeats and arbitrary order allowed (publish_post({ surfaces: [...] }) / POST /api/posts). The CLI sideshow publish cannot express this: it composes the post from one flag per surface kind, so you get at most one of each kind, in a fixed order, with no way to repeat a kind.
What works today
sideshow publish summary.html --md notes.md --diff a.patch --json metrics.json
→ one post: html, markdown, diff, json (one of each).
What you can't do
- Two surfaces of the same kind — e.g. two diffs, two code blocks, two markdown sections:
sideshow publish base.html --diff a.patch --diff b.patch
--diff is not multiple, so node:util parseArgs silently keeps only the last value (b.patch); a.patch is dropped with no error.
- Control the surface order — it's hard-coded (html → markdown → mermaid → diff → terminal → json → code → image), regardless of flag order on the command line.
- Omit the leading html surface — the first positional is always read as an html surface.
Root cause
bin/sideshow.js publish command (~L760–821): each surface-kind option is declared { type: "string" } (not multiple: true — only --kit is), and each is appended at most once behind an if (flags.X !== undefined) guard. The parts array is therefore a fixed-shape menu, not a free-form list.
md: { type: "string" }, mermaid: { type: "string" }, diff: { type: "string" }, ...
const parts = [htmlPart];
if (flags.md !== undefined) parts.push({ kind: "markdown", ... });
if (flags.diff !== undefined) parts.push({ kind: "diff", ... });
// ...one push per kind, fixed order
Impact
Agents/users who want a richer multi-surface post (e.g. "summary md, then diff #1, then diff #2, then a code excerpt") must drop to raw HTTP or MCP. The CLI silently truncating a repeated flag is also a footgun — it looks like it worked.
Possible directions (not prescriptive)
- Surfaces manifest:
sideshow publish --surfaces surfaces.json where the file is the full surfaces array (or - for stdin) — exact parity with the API, full control of order/repeats.
- Repeatable, ordered flags: make the kind flags
multiple: true and build parts in the order the flags appeared on argv (requires reading process.argv order, since parseArgs values lose cross-flag ordering).
- At minimum: error instead of silently dropping when a non-
multiple surface flag is passed more than once.
Found while documenting multi-surface publishing during the post/surface vocabulary rename.
Summary
The MCP/HTTP API can publish a post with any list of surfaces — repeats and arbitrary order allowed (
publish_post({ surfaces: [...] })/POST /api/posts). The CLIsideshow publishcannot express this: it composes the post from one flag per surface kind, so you get at most one of each kind, in a fixed order, with no way to repeat a kind.What works today
→ one post:
html, markdown, diff, json(one of each).What you can't do
--diffis notmultiple, sonode:utilparseArgssilently keeps only the last value (b.patch);a.patchis dropped with no error.Root cause
bin/sideshow.jspublishcommand (~L760–821): each surface-kind option is declared{ type: "string" }(notmultiple: true— only--kitis), and each is appended at most once behind anif (flags.X !== undefined)guard. Thepartsarray is therefore a fixed-shape menu, not a free-form list.Impact
Agents/users who want a richer multi-surface post (e.g. "summary md, then diff #1, then diff #2, then a code excerpt") must drop to raw HTTP or MCP. The CLI silently truncating a repeated flag is also a footgun — it looks like it worked.
Possible directions (not prescriptive)
sideshow publish --surfaces surfaces.jsonwhere the file is the fullsurfacesarray (or-for stdin) — exact parity with the API, full control of order/repeats.multiple: trueand buildpartsin the order the flags appeared on argv (requires readingprocess.argvorder, sinceparseArgsvalues lose cross-flag ordering).multiplesurface flag is passed more than once.Found while documenting multi-surface publishing during the post/surface vocabulary rename.