Repository navigation
Keep Prism's terminal and Prism Terminal in sync: one shared core #15
Description
Owner, 2026-09-19: "this terminal app we're building is just an extraction of the main Prism app and should therefore be reflected in both apps. How can we best make sure the two terminals are synced and serve the same options and features?"
Planned, not started. Needs an owner decision on approach and order (below).
The problem, stated plainly
Prism Terminal was made by COPYING Prism's terminal (Prism 4196c3a, 2026-09-18), on the recommendation "new repo, Prism untouched". A copy drifts from the first commit, and it already has. Nothing keeps the two in step except remembering to port by hand.
Drift so far (one day)
In Prism Terminal, NOT in Prism:
- Links highlighted in a theme-adaptive colour (Links in the terminal are always highlighted, in a colour that adapts to the theme #10).
- The panel paints the ground: no strip under the last row (A grey strip under the terminal's last row #6). Prism very likely has the same strip.
- Agent indicator wears the theme's accent; Minimal by default; renamed settings (Agent indicators follow the theme's accent; minimal by default #4).
- Closing a tab asks whenever an agent is present (Closing a tab that hosts an agent does not ask #8). Prism has its own three-mode version of this.
- Ctrl+T / user-folder new tab, start screen, cog, quit-on-close, hairline edge: app-shell decisions, arguably Prism Terminal's own.
material.ts: material-before-colour (Electron 43 rewrites the window background to white). Prism sets them the other way round and likely has the bug.- The indicator rules lifted out of
App.tsxintolib/useAgentIndicator.ts(same rules, testable shape).
In Prism, NOT in Prism Terminal (by owner decision, so not drift): split dock, several shells per tab, sidebar/cwd sync and the Set-Location write, "Open terminal here".
Coming next, and each would have to be built twice or ported: dictation (#13, large), help panel (#12), attach (#14).
Options
A. One shared package, consumed by both apps (RECOMMENDED)
A third repo, prism-term-core, holding everything that IS the terminal. Both apps depend on it at a pinned version; a feature is built once and reaches both by a version bump.
- What goes in: main side (
terminal,shells,termPrompt,agentDetect,agentPoll,agentResume, later the dictation engine); renderer side (TerminalPanel,TermFind, link paint,useAgentIndicator,agentTitle,termActivity,agentClock,termTheme,termLook,termAnsi,termPaste, the agent colours, and the TERMINAL SETTINGS SECTIONS as components, so the options are literally the same code in both apps). - What stays in each app: its shell. Prism: roots, sidebar, split dock, several shells, cwd sync, app styles. Prism Terminal: cwd tabs, start screen, chrome-from-theme, window lifecycle.
- The seam: a typed
TermHostinterface the app's preload implements (spawn / input / resize / kill / clipboard / external links), and a small options object for the places the apps legitimately differ (Prism follows its app style; Prism Terminal drives the chrome from the theme). Differences are declared, not forked. - Delivery: an npm dependency pinned to a git tag (
"prism-term-core": "github:Maxaubert/prism-term-core#v1.4.0"): no registry needed. It ships TypeScript SOURCE, compiled by each app's own Vite, with Tailwind pointed at it (@source), since both apps share a toolchain. Local iteration withnpm link. - What keeps them honest: the core has its own unit tests and CI; each app keeps its own e2e; and a PARITY TEST in each app asserts that the terminal options it shows are exactly the list the core exports, so an option can never exist in one app and not the other without a test going red.
- This is the same idea as the
prism-coreviewer package Prism's CLAUDE.md already plans to share with Filesmith. - Cost, honestly: a real refactor in BOTH apps. Prism is the hard half: its terminal wiring lives inside a 4000-line
App.tsx, and Prism is stable and shipping, so it must be done behind Prism's own terminal e2e scenarios, in steps. Several focused PRs, not an afternoon.
B. Keep two copies, add a drift report
A script that diffs the shared files between the two checkouts and lists what differs, run before every PR, plus a checklist line "ported to the sibling? yes / no / not applicable". Cheap and immediate. But every feature is still built or ported twice, the files have already legitimately diverged (theme model, keys) so the report is noisy, and it relies on discipline, which is what has already failed once.
C. One repo for both apps (monorepo)
Both apps and the shared code in one repository. The strongest guarantee, and the biggest upheaval: Prism's repo, CI, releases and history all move. Not recommended; A gets the same result without it.
Recommendation: A, and BEFORE dictation
Dictation is the largest terminal feature yet (engine, model manager, a settings tab, recording UI). Built in Prism Terminal first, it is a large port later. Built in the core, it lands in both apps at once. Suggested order:
- Create
prism-term-corefrom PRISM TERMINAL's copy (the newer, cleaner one, already split into small tested files). Prism Terminal switches to consuming it. No behaviour change; its 12 e2e scenarios are the proof. - Prism adopts the core in steps, behind its own terminal e2e, keeping its split dock / several shells / cwd sync as its own code around the core's panel. Prism gains links, the strip fix, the theme-following indicator and the material fix on the way.
- Dictation (Dictation when using the agents #13), then attach (Attach a file or folder: pick it, and its path is pasted into the agent #14) and the help panel (Help panel: a searchable catalogue of shell commands #12), are built in the core and ship to both.
Until step 2 is done the honest status is: Prism's terminal is BEHIND Prism Terminal, and B's checklist line is worth adopting in the meantime.
Decisions needed from the owner
- A, B or C?
- If A: do the extraction before dictation, or build dictation first and extract after?
- Which app-shell differences are intentional and stay different (start screen, quit-on-close, Ctrl+T, cog), and which should Prism pick up too?
Activity
Maxaubert commentedon Sep 19, 2026
Decided (owner, 2026-09-19):
corearea that Prism consumes at a pinned git tag; Prism Terminal is both the app and the library. Reasons it is better than a separate package: one place, the shared code is always exercised inside a real shipping app and its e2e, and it is simply true (Prism Terminal IS the terminal; Prism embeds it).coreboundary that may never import from the app shell (lint-enforced), relative imports only inside it (no@shared/@rendereraliases, which a consumer's bundler cannot resolve),exportson the root package, Prism's electron-vite told to BUNDLE it rather than externalise it (it ships TypeScript source), Tailwind pointed at it with@source, andnode-pty/ xterm / React kept at identical versions in both apps so npm dedupes them to one copy.refactor(host): the host speaks from a module imported first (#15)
Maxaubert commentedon Sep 19, 2026
Status, 2026-09-19 (built while the owner was away; everything is on branches, nothing merged)
Built and verified
core/in this repo (The terminal moves into core/, shared with Prism (#15) #18, draft, stacked on fix: a dropped file types its path; the terminal answers a right-click (#16) #17). Prism Terminal runs entirely on it: 366 unit tests, all 13 e2e scenarios, CI green, installed on the owner's machine.core-distbranch (git subtree split --prefix=core), tagcore-v0.1.0-rc.1: 29 files, 164 KB, no install scripts.npm ciin about 2 minutes).termLook,termTheme, the agent poll, the resume lookup and the bridge on both sides come from the core; Prism is a HOST whose every setting is what Prism already did. 1375 unit tests, full e2e 756 checks.../Prism-core) fromorigin/main(de5b43f), never the shared working tree, because a Codex session has PR Agent indicator: restored tabs show Finished after a restart, though nothing finished #151 open there.Found on the way
terminale2e scenario fails on untouchedorigin/main: "the original shell retains its scrollback" (a terminal pinned into a split pane). Pre-existing, not caused by the core, not fixed.rowPaste(Prism e2e) timed out once in a full run and passes alone: it uses the real Windows clipboard.maincheckout is one release behindorigin/main, and Prism Terminal was copied from that older commit. The terminal's own files had barely moved, excepttermPaste(a copied image FILE should paste as its path), which Prism Terminal never got. The core now carries it.Decisions only the owner can make
The core already has a host setting for each of these, so none blocks the PRs above. They decide whether a difference STAYS or goes.
stylein Prism,prismpreset here), acrylic (on / off), indicator (full orange / quiet, theme-coloured). Making them one value changes what existing Prism users see on update. "All synced": does that cover defaults?App.tsx. The core has it asuseAgentIndicator; adopting it changes two small behaviours in Prism (a finished mark dies when its agent leaves;workingis only scored while an agent is present). Take it?core-v*tag, a pin-bump PR in Prism, its e2e, install, "merge?". That is two approvals per terminal fix. Acceptable, or should a pin bump that passes Prism's e2e be pre-approved?main/index.ts, the preload,Settings.tsxandTabStrip.tsx, which PR Agent indicator: restored tabs show Finished after a restart, though nothing finished #151 also touches. Land Agent indicator: restored tabs show Finished after a restart, though nothing finished #151 first and rebase, or the other way round?Next, once decided
The remaining three pieces in Prism (8, 9 and
TabStrip), then dictation (#13), attach (#14) and the help panel (#12) are built ONCE, incore/, and reach both apps.Maxaubert commentedon Sep 19, 2026
Decided (owner, 2026-09-19):
core/, and each app composes its own page round them.--p-accent, which is what its tab strip already wears; the finished colour follows the same rule as here.These change what an existing Prism user sees on update (a quiet accent-coloured line instead of a filled orange tab), knowingly.
Maxaubert commentedon Sep 19, 2026
Decided (owner, 2026-09-19), the rest of the twelve:
useAgentIndicatorreplaces Prism's inline wiring (a finished mark dies when its agent leaves; 'working' is only scored while an agent is detected), and Minimal/Full is never reset by a theme pick nor stored in a saved theme.feat(core): the terminal's settings, indicator colours and close ques…
feat(core): the terminal's settings, indicator colours and close ques…
build(core): export the settings sections, so Prism can mount them (#15)
build(core): export the settings sections, so Prism can mount them (#15)
fix(core): the indicator's forget is stable, so a host can subscribe …
fix(core): the indicator's forget is stable, so a host can subscribe …
fix(core): the theme hint says what is true in a host with styles of …
fix(core): the theme hint says what is true in a host with styles of …
docs(core): the pin-bump gate in Prism, and where adoption stands (#15)
Maxaubert commentedon Sep 19, 2026
Progress, 2026-09-19 afternoon. All twelve decisions are applied.
core-v0.1.0-rc.5.npm run e2e:terminal, the required gate for any pin bump.core-v0.1.0and repoint Prism.core/.refactor(core): the terminal moves into core/, behind a declared host…
chore(core): the lint wall, the host seam's tests, and the sync contr…
refactor(host): the host speaks from a module imported first (#15)
feat(core): the terminal's settings, indicator colours and close ques…
build(core): export the settings sections, so Prism can mount them (#15)
fix(core): the indicator's forget is stable, so a host can subscribe …
fix(core): the theme hint says what is true in a host with styles of …
docs(core): the pin-bump gate in Prism, and where adoption stands (#15)
The terminal moves into core/, shared with Prism (#15) (#19)
The terminal moves into core/, shared with Prism (#15) (#19)
Maxaubert commentedon Sep 19, 2026
Merged, 2026-09-19: PrismTerminal #17 and #19 (the core; it replaced #18, which GitHub closed when #17's branch was deleted),
core-v0.1.0tagged from main, and Prism #155, #156, #157 (Prism 0.53.0, pinned tocore-v0.1.0). Both apps are installed on the owner's machine from merged main. Open: Prism's release workflow is broken by an upstream ffmpeg rotation (Maxaubert/Prism#159 fixes it); the strip fix and the window edge still want a look on real glass. Next: dictation (#13), built once incore/.fix(security): code review part 1, what reaches a shell, what main ru…
fix(security): code review part 1, what reaches a shell, what main ru…
Maxaubert commentedon Oct 15, 2026
Done: the shared core (core/, released from the core-dist branch as core-v* tags, Prism pinned to it) is how both apps stay in sync, with the rules in docs/two-apps.md. Checked and closed 2026-10-15.