Updates to terminals

This commit is contained in:
2026-04-25 06:10:08 +00:00
parent 5e02dc4ffb
commit b6b935fabc
4 changed files with 11 additions and 52 deletions
+1 -1
View File
@@ -54,7 +54,7 @@ Copy `[.env.example](.env.example)` to `.env`. BareCloud reads `**BARECLOUD_*`**
| `BARECLOUD_BARE_OS_NO_SPLASH` | Set `1` to hide bare-os boot splash in Pear. |
| `BARE_OS_BOOT_TIMEOUT_MS` | Optional; forwarded from host env into Pear (bare-os boot wait). |
| `BARECLOUD_TERMINAL_WS_PING_MS` | Browser WebSocket ping interval ms (`0` / empty rules → see `lib/terminal-proxy.ts`). |
| `BARECLOUD_BOOTER_TERM`, `BARECLOUD_TMUX_HISTORY_LIMIT`, `NEXT_PUBLIC_TERMINAL_SCROLLBACK` | Default `TERM` for Pear PTY / tmux session, tmux pane history, and browser xterm scrollback. Scrollback defaults to 1,000,000 lines. |
| `BARECLOUD_BOOTER_TERM`, `BARECLOUD_TMUX_HISTORY_LIMIT`, `NEXT_PUBLIC_TERMINAL_SCROLLBACK` | Default `TERM` for Pear PTY / tmux session (`xterm-256color`), tmux pane history (default 50,000; capped at 200,000), and browser xterm scrollback. Browser scrollback defaults to 1,000,000 lines. |
| `BARECLOUD_TERMINAL_TMUX`, `BARECLOUD_TMUX_BIN` | Resumable console: `tmux` detached session (default **on** when `tmux` is on `PATH`; set `0` to force direct PTY only). Override binary path if needed. |
| `BARECLOUD_TMUX_SOCKET` | Optional absolute path to a **dedicated tmux server socket** (`tmux -S …`). Use when the BareCloud host process inherits `TMUX` or you want Pear consoles isolated from your personal `tmux` server. |
| `BARECLOUD_DELETE_CORESTORE_ON_REMOVE` | Set `0` / `false` / `no` to keep instance dirs on delete. |
+2 -2
View File
@@ -650,7 +650,7 @@ export function Terminal({ booterId }: Props) {
return (
<div
className="barecloud-xterm-host relative flex h-full min-h-0 w-full flex-col overflow-hidden rounded-2xl border border-white/10 bg-black/40 shadow-inner shadow-black/60"
className="barecloud-xterm-host relative flex h-full min-h-0 w-full flex-col overflow-visible rounded-2xl border border-white/10 bg-black/40 shadow-inner shadow-black/60"
aria-label="Bare OS console"
onMouseDown={(e) => {
if (e.button === 0) termRef.current?.focus();
@@ -689,7 +689,7 @@ export function Terminal({ booterId }: Props) {
)}
<div
ref={containerRef}
className="relative z-0 flex min-h-0 flex-1 flex-col overflow-x-hidden px-2"
className="relative z-0 flex min-h-0 flex-1 flex-col overflow-visible px-2"
/>
</div>
);
+2 -2
View File
@@ -193,7 +193,7 @@ export function BooterPage() {
</header>
<div className="mx-auto flex min-h-0 w-full max-w-[1600px] flex-1 flex-col gap-4 overflow-visible px-3 py-3 sm:px-4 sm:py-4 lg:flex-row lg:items-stretch lg:gap-5 lg:overflow-hidden lg:px-5 lg:py-5">
<section className="flex min-h-[min(58dvh,680px)] min-w-0 flex-1 flex-col gap-3 overflow-hidden lg:min-h-0">
<section className="flex min-h-[min(58dvh,680px)] min-w-0 flex-1 flex-col gap-3 overflow-visible lg:min-h-0">
<div className="flex shrink-0 flex-col gap-1 sm:flex-row sm:items-end sm:justify-between">
<div>
<h2 className="text-base font-semibold tracking-tight text-white">Console</h2>
@@ -206,7 +206,7 @@ export function BooterPage() {
Interactive
</Badge>
</div>
<div className="relative min-h-0 min-w-0 flex-1 overflow-hidden">
<div className="relative min-h-0 min-w-0 flex-1 overflow-visible">
<Terminal key={`${id}-${terminalResetKey}`} booterId={id} />
</div>
</section>
+6 -47
View File
@@ -46,7 +46,7 @@ function tmuxAvailable(): boolean {
/** Default `TERM` for Pear in tmux / headless paths (matches terminal WebSocket stub). */
export function defaultPearTermEnv(): string {
return process.env.BARECLOUD_BOOTER_TERM?.trim() || process.env.TERM?.trim() || "xterm-256color";
return process.env.BARECLOUD_BOOTER_TERM?.trim() || "xterm-256color";
}
/**
@@ -92,51 +92,18 @@ function tmuxExactSessionTarget(booterId: string): string {
function tmuxHistoryLimit(): number {
const raw = process.env.BARECLOUD_TMUX_HISTORY_LIMIT?.trim();
if (!raw) return 1_000_000;
if (!raw) return 50_000;
const n = Number.parseInt(raw, 10);
if (!Number.isFinite(n) || n < 1_000) return 1_000_000;
return Math.min(n, 1_000_000);
}
function configureTmuxServerForWebTerminal(): void {
const override = ",xterm*:smcup@:rmcup@";
try {
const current = execFileSync(tmuxBin(), [...tmuxSocketArgs(), "show-options", "-gqv", "terminal-overrides"], {
env: tmuxClientEnv(process.env),
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
});
if (current.includes("xterm*") && current.includes("smcup@") && current.includes("rmcup@")) return;
} catch {
/* ignore and try to append below */
}
try {
execFileSync(tmuxBin(), [...tmuxSocketArgs(), "set-option", "-g", "-a", "terminal-overrides", override], {
stdio: "ignore",
env: tmuxClientEnv(process.env),
});
} catch {
/* ignore */
}
if (!Number.isFinite(n) || n < 1_000) return 50_000;
return Math.min(n, 200_000);
}
/**
* Ensure managed BareCloud tmux sessions have wheel-friendly behavior:
* - do not enable tmux mouse capture; the browser/xterm scrollbar owns wheel scrolling.
* - suppress tmux's outer alternate-screen entry so xterm can accumulate normal-buffer scrollback.
* - keep a large tmux history as a fallback for detached/resumed panes.
* Keep managed BareCloud tmux sessions close to tmux defaults while retaining resumable pane history.
* Browser/xterm owns scrolling; tmux keeps its normal mouse, alternate-screen, and terminal capability behavior.
*/
function configureTmuxSessionForWebTerminal(booterId: string): void {
configureTmuxServerForWebTerminal();
const target = tmuxExactSessionTarget(booterId);
try {
execFileSync(tmuxBin(), [...tmuxSocketArgs(), "set-option", "-t", target, "mouse", "off"], {
stdio: "ignore",
env: tmuxClientEnv(process.env),
});
} catch {
/* ignore */
}
try {
execFileSync(
tmuxBin(),
@@ -149,14 +116,6 @@ function configureTmuxSessionForWebTerminal(booterId: string): void {
} catch {
/* ignore */
}
try {
execFileSync(tmuxBin(), [...tmuxSocketArgs(), "set-window-option", "-t", target, "alternate-screen", "off"], {
stdio: "ignore",
env: tmuxClientEnv(process.env),
});
} catch {
/* ignore */
}
}
export function hasTmuxPearSession(booterId: string): boolean {