diff --git a/docs/web-ui/dashboard.md b/docs/web-ui/dashboard.md
index ae22d0b3..a8cfaff2 100644
--- a/docs/web-ui/dashboard.md
+++ b/docs/web-ui/dashboard.md
@@ -622,9 +622,10 @@ frontend reads.
Operator-local preferences. State lives in the browser's
`localStorage` — preferences do NOT sync between devices and
-do NOT survive a profile wipe. Two sections today (browser
-notifications, agent terminal); future preferences (theme, density,
-etc.) land here as sibling `
` blocks in `settings.html`.
+do NOT survive a profile wipe. Today the tab holds one section
+(browser notifications); future preferences (theme, density,
+etc.) land here as sibling `
` blocks
+under the same ``.
**◇ browser notifications** — `🔔 enable notifications` button when
permission ungranted; `🔕 mute / 🔔 unmute` toggle once granted
@@ -635,19 +636,6 @@ single status line explains why. See `### Browser notifications`
below for the dispatch model + the three signals the dashboard
emits OS notifications on.
-**◇ agent terminal** — a single `☐/☑ expand tool output panels`
-toggle button (`role="switch"`, live `aria-checked`). Controls whether
-every per-agent page's terminal defaults otherwise-collapsed
-`` rows (long tool-results, Write/Edit diffs, …) open; rows
-that already default open regardless (send/ask/answer/recv) are
-unaffected either way. Pure client-side — the key + get/set live in
-`@hive/shared/prefs.js` (`getExpandDetailsPref`/`setExpandDetailsPref`)
-so this page and every agent page's `app.js` read/write the exact same
-`localStorage` key without a backend field; the shared terminal
-factory reads it live via its `expandDetails` option (see
-docs/web-ui/shape.md::Shared terminal pane), so a change here applies
-to any already-open agent tab's next rendered row without a reload.
-
The FL0W page does NOT host this pane — settings live only on the
dashboard's S3TT1NGS tab (reach it via the FL0W page's `← home`
back-link → Dashboard). Notifications still fire on the FL0W page when
diff --git a/docs/web-ui/shape.md b/docs/web-ui/shape.md
index 0de8445c..bd657f15 100644
--- a/docs/web-ui/shape.md
+++ b/docs/web-ui/shape.md
@@ -115,11 +115,7 @@ event picture), `onBackfillDone?(count)` (one-shot after replay; `count=0` on
failed/skipped fetch), `onStreamOpen?()` (fires on every EventSource
(re)connect — use to re-sync snapshot-derived state after a reconnect gap),
`pillAnchor?` (parent element for the "↓ N new" pill; defaults to
-`logEl.parentElement`), `expandDetails?` (boolean or zero-arg function
-returning one, re-read on every `api.details`/`api.detailsDiff` call rather
-than captured once — lets a page default otherwise-collapsed panels open
-per a live browser-local preference; renderers that force a row open
-regardless, e.g. message-bearing tool_use, are unaffected either way).
+`logEl.parentElement`).
**Sticky-bottom + snap animation.** `stickToBottom` is the
operator's intent: true means "keep snapping to bottom on every
diff --git a/frontend/packages/agent/src/app.js b/frontend/packages/agent/src/app.js
index 94661e0e..33e0af8c 100644
--- a/frontend/packages/agent/src/app.js
+++ b/frontend/packages/agent/src/app.js
@@ -6,7 +6,6 @@ import { create as termCreate, linkify as termLinkify } from '@hive/shared/termi
import { asyncBtn, bindAsyncForms } from '@hive/shared/forms.js';
import { themedConfirm } from '@hive/shared/modal.js';
import { el } from '@hive/shared/dom.js';
-import { getExpandDetailsPref } from '@hive/shared/prefs.js';
import '@hive/shared/side-panel.js'; // registers — side-effect import
import { marked } from 'marked';
import DOMPurify from 'dompurify';
@@ -1614,9 +1613,6 @@ window.marked = marked;
// (e.g. /agent//) still hits the right SSE upstream.
historyUrl: 'events/history',
streamUrl: 'events/stream',
- // Re-read live (not captured once) so flipping the overflow-menu
- // toggle mid-session affects the next rendered row immediately.
- expandDetails: () => getExpandDetailsPref(),
renderers: {
turn_start(ev, api) {
if (api.fromHistory) openTurnsFromHistory += 1;
diff --git a/frontend/packages/dashboard/src/settings.html b/frontend/packages/dashboard/src/settings.html
index 7fd6ed28..1f98dfec 100644
--- a/frontend/packages/dashboard/src/settings.html
+++ b/frontend/packages/dashboard/src/settings.html
@@ -31,12 +31,6 @@
-
-
◇ agent terminal
-
applies to every agent's terminal viewed in this browser — whether otherwise-collapsed tool-output panels (long results, Write/Edit diffs, …) default open. rows that already default open (send/ask/answer/recv) are unaffected either way.
-
-
-
diff --git a/frontend/packages/dashboard/src/settings.js b/frontend/packages/dashboard/src/settings.js
index 3a4f4a6e..c6d5fc29 100644
--- a/frontend/packages/dashboard/src/settings.js
+++ b/frontend/packages/dashboard/src/settings.js
@@ -1,37 +1,15 @@
// /settings.html — operator-local preferences page.
//
-// Extracted from the dashboard S3TT1NGS tab. The browser-notification
-// toggle: NOTIF.bind() wires the enable / mute / unmute buttons and
-// persists state to localStorage. The dashboard's NOTIF.show() calls
-// (approvals / questions) read that same localStorage state + the
-// browser-level permission, so firing still works from the dashboard
-// even though the toggle UI now lives on its own page.
-//
-// The agent-terminal-verbosity toggle below is a second, unrelated
-// browser-local preference — @hive/shared/prefs.js owns the key name +
-// get/set so this page and every per-agent page's app.js agree on it
-// without a backend field. Both preferences are per-origin localStorage,
-// so they only apply within this browser (per the page's own copy).
+// Extracted from the dashboard S3TT1NGS tab. Today the only setting is
+// the browser-notification toggle: NOTIF.bind() wires the enable / mute /
+// unmute buttons and persists state to localStorage. The dashboard's
+// NOTIF.show() calls (approvals / questions) read that same localStorage
+// state + the browser-level permission, so firing still works from the
+// dashboard even though the toggle UI now lives on its own page.
//
// initServerWarnings() renders the shared top-of-page warnings banner,
// matching the other stand-alone pages (FL0W / L0GS / H0M3).
import { NOTIF, initServerWarnings } from './common.js';
-import { getExpandDetailsPref, setExpandDetailsPref } from '@hive/shared/prefs.js';
initServerWarnings();
NOTIF.bind();
-
-(function bindExpandDetailsToggle() {
- const btn = document.getElementById('expand-details-toggle');
- if (!btn) return;
- function render() {
- const on = getExpandDetailsPref();
- btn.textContent = on ? '☑ expand tool output panels' : '☐ expand tool output panels';
- btn.setAttribute('aria-checked', String(on));
- }
- btn.addEventListener('click', () => {
- setExpandDetailsPref(!getExpandDetailsPref());
- render();
- });
- render();
-})();
diff --git a/frontend/packages/shared/package.json b/frontend/packages/shared/package.json
index 5134f006..b0dde490 100644
--- a/frontend/packages/shared/package.json
+++ b/frontend/packages/shared/package.json
@@ -17,7 +17,6 @@
"./terminal.css": "./src/terminal/terminal.css",
"./chrome.css": "./src/chrome.css",
"./forms.js": "./src/forms.js",
- "./prefs.js": "./src/prefs.js",
"./dom.js": "./src/dom.js",
"./modal.js": "./src/modal.js",
"./shadow-css.js": "./src/shadow-css.js",
diff --git a/frontend/packages/shared/src/prefs.js b/frontend/packages/shared/src/prefs.js
deleted file mode 100644
index f73fb005..00000000
--- a/frontend/packages/shared/src/prefs.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// Tiny browser-local (localStorage) preference helpers shared by the
-// dashboard's /settings.html and the per-agent page — both need the
-// exact same key name to actually talk to each other via the browser's
-// shared per-origin storage (settings.html is where the operator sets
-// the preference; every per-agent page's terminal reads it), so the
-// get/set pair — and the key itself — live here once rather than as
-// independent copies in each package that could drift out of sync.
-
-const EXPAND_DETAILS_KEY = 'hive-agent-expand-details';
-
-// Whether a per-agent terminal's otherwise-collapsed `` panels
-// (long tool-results, Write/Edit diffs, …) should default open. Pure
-// client-side — no backend field, nothing round-trips through
-// `/api/*`. Read live (not cached) by the shared terminal factory's
-// `expandDetails` option — see docs/web-ui/shape.md::Shared terminal
-// pane — so a preference change on /settings.html applies to the next
-// rendered row in any already-open agent tab without a reload.
-export function getExpandDetailsPref() {
- try { return localStorage.getItem(EXPAND_DETAILS_KEY) === '1'; }
- catch { return false; }
-}
-export function setExpandDetailsPref(v) {
- try {
- if (v) localStorage.setItem(EXPAND_DETAILS_KEY, '1');
- else localStorage.removeItem(EXPAND_DETAILS_KEY);
- } catch { /* localStorage unavailable — preference is session-only */ }
-}
diff --git a/frontend/packages/shared/src/terminal/terminal.js b/frontend/packages/shared/src/terminal/terminal.js
index 5830e0cb..e00a55cd 100644
--- a/frontend/packages/shared/src/terminal/terminal.js
+++ b/frontend/packages/shared/src/terminal/terminal.js
@@ -231,23 +231,11 @@ export function create(opts) {
afterAppend(wasNearBottom);
return [e, tn];
}
- // `opts.expandDetails` (boolean or zero-arg function returning one) lets
- // the caller default every otherwise-collapsed `` row open —
- // e.g. an "expand panels by default" browser-local preference. Read
- // live (not captured once) so a mid-session preference flip takes
- // effect on the next row without recreating the terminal. Renderers
- // that need a row open regardless (message-bearing tool_use/tool_result)
- // already set `d.open = true` themselves after calling this — this only
- // changes the *default* for panels that would otherwise start closed.
- function wantsExpandedDefault() {
- return typeof opts.expandDetails === 'function' ? !!opts.expandDetails() : !!opts.expandDetails;
- }
function details(cls, summary, body, icon) {
clearPlaceholder();
const wasNearBottom = isNearBottom();
const d = document.createElement('details');
d.className = 'row ' + (cls || '') + (currentNoAnim ? ' no-anim' : '');
- if (wantsExpandedDefault()) d.open = true;
d.appendChild(buildSummary(summary, icon));
const pre = document.createElement('pre');
pre.className = 'tool-body';
@@ -262,7 +250,6 @@ export function create(opts) {
const wasNearBottom = isNearBottom();
const d = document.createElement('details');
d.className = 'row ' + (cls || '') + (currentNoAnim ? ' no-anim' : '');
- if (wantsExpandedDefault()) d.open = true;
d.appendChild(buildSummary(summary, icon));
const pre = document.createElement('pre');
pre.className = 'tool-body diff-body';