Inbuilt Terminal
A real shell terminal inside Omniscio, scoped to a project's folder — open it from the sidebar, keep the last 100 KB of scrollback across a close and reopen, fuzzy-search saved command snippets, and find within the output. In development: it appears only when its Labs toggle is on.
What it is
A real shell terminal inside Omniscio, scoped to a project. In-development feature — visible only when Labs → Inbuilt terminal is on (or the env var AMC_SHOW_INBUILT_TERMINAL=1 is set).
Where to find it
Click the terminal icon in the sessions sidebar header to open a terminal in the current project's folder. While a terminal is focused, Ctrl/Cmd+T opens another. Saved snippets are managed in Settings → search "Terminal snippets" — a deep-link-only page, since the feature is unreleased.
How it behaves
What it does
- Open a terminal in the current project's folder by clicking the terminal icon in the sessions sidebar header (or Ctrl/Cmd+T when a terminal is focused).
- Runs whatever shell your OS picks up (
$SHELLon macOS/Linux; on Windows, PowerShell 7pwsh.exewhen it's installed, else Windows PowerShellpowershell.exe, elsecmd.exe). The Windows shell is resolved on PATH before use, so an uninstalled shell is never handed to node-pty (that mismatch was the "File not found:" spawn crash). Renders viaxterm.js; the PTY isnode-ptyin the main process. - Persistent scrollback — the last 100 KB of output survives closing and reopening the panel. Restored via
@xterm/addon-serializeon mount. - Ctrl/Cmd+K opens a snippet palette — fuzzy-search over your saved snippets, arrow keys navigate, Enter pastes the command into the terminal (paste-only; you press Enter yourself to run it).
- Save a snippet with the bookmark-icon button in the panel header — opens a dialog with Name + Command fields.
- Ctrl/Cmd+F reveals a Find bar over the terminal (uses xterm's SearchAddon).
- Live theme rebind — switching light/dark or changing the accent color re-applies the terminal theme without recreating it.
Manage snippets
Settings → search "Terminal snippets" (deep-link only — no nav row while the feature's unreleased). Full CRUD list: Add / Edit / Delete rows. Deletes go through ConfirmDialog and register an undo via useUndoStore (a toast surfaces the restore action).
Snippets are user-wide (one shared list across every project). Storage: terminal_snippets table (id, name, command, position, is_deleted, timestamps).
Command blocks (v3)
Additional gate: command blocks require BOTH AMC_SHOW_INBUILT_TERMINAL=1 AND AMC_SHOW_INBUILT_TERMINAL_BLOCKS=1 (or Labs → Inbuilt terminal blocks). The block overlay is completely invisible unless both flags are on.
What it does
Every command you run in the terminal gets a "block" — a visual unit in the gutter to the left of the xterm viewport:
- A green check or red X gutter dot marks exit-code 0 vs non-zero.
- Hovering the gutter reveals three icon buttons: Fold (collapse the block's output rows), Copy (copy just that command's output to the clipboard), and Re-run (types the original command text at the prompt — you press Enter yourself; it never auto-executes).
- Blocks are fully persistent: they survive closing and reopening the terminal panel, restoring with the same fold/copy/re-run affordances. The restore sequence waits for both the scrollback content and the block metadata before mounting (see Invariant 3 below).
Shell integration — how it works
When the inbuilt-terminal-blocks feature is visible, TerminalPtyService.spawn() injects per-shell env vars that load bundled shell-init scripts without touching any user rc file:
| Shell | Mechanism | User rc |
|---|---|---|
| zsh | ZDOTDIR → scratch tempdir whose .zshrc sources Omniscio's init, then Omniscio's init sources the real ~/.zshrc via $AMC_USER_ZDOTDIR |
read-only (never written) |
| bash | BASH_ENV → Omniscio's init script, which sources ~/.bashrc via $AMC_USER_HOME |
read-only |
| pwsh | AMC_USER_PROFILE → Omniscio's init script; $PROFILE.ps1 sourced from inside the init |
read-only |
Omniscio's init scripts emit OSC 133 sequences (\x1b]133;A\x07, B, C, D;<exit>, P;cwd=<path>) around each command lifecycle. Nothing writes to ~/.zshrc, ~/.bashrc, or $PROFILE.ps1.
Data flow
Shell (zsh/bash/pwsh)
└─ emits OSC 133 sequences on PTY output stream
│
▼
terminal-osc133-parser.ts (Task 4)
└─ strips OSC 133 markers from stream (xterm never sees \x1b]133)
└─ emits BlockEvent[] (prompt-start, command-start, command-end, cwd-change)
│
▼
terminal-block-processor.ts (Task 5)
└─ accumulates BlockEvent[] into PartialBlock drafts → seals TerminalBlockRow on command-end
│
▼
terminal-session-manager.ts (Task 6)
└─ persists sealed blocks to terminal_blocks (SQLite, additive migration)
└─ emits TERMINAL_BLOCK_EVENT push to renderer
│
▼
TerminalBlockOverlay.tsx (Task 7)
└─ subscribed via usePushListener(TERMINAL_BLOCK_EVENT)
└─ positioned absolutely over xterm viewport
└─ renders TerminalBlockGutterRow per block (exit-code dot + fold/copy/re-run actions)
Key files
- Main/backend:
src/main/services/engines/terminal-osc133-parser.ts(pure OSC 133 parser),src/main/services/engines/terminal-block-processor.ts(draft accumulator → sealed blocks),src/main/services/engines/terminal-shell-init.ts(resolve bundled init script path by shell),src/main/services/engines/terminal-shell-init-env.ts(build per-shell env map for PTY spawn),src/main/db/queries-terminal/blocks.ts(SQLite persistence),src/main/ipc/terminal-blocks-handlers.ts(Zod-validated IPC:TERMINAL_BLOCKS_LOAD,TERMINAL_RUN_COMMAND_IN_SESSION). - Renderer/UI:
src/renderer/src/features/terminal/TerminalBlockOverlay.tsx(overlay container, subscribes to push events),src/renderer/src/features/terminal/TerminalBlockGutterRow.tsx(per-block gutter row + hover actions),src/renderer/src/features/terminal/terminal-blocks-store.ts(Zustand store for block state),src/renderer/src/features/terminal/useTerminalSession.ts(mounts blocks alongside scrollback on open). - Shell scripts:
resources/terminal-shell-init/amc-init.{zsh,bash,ps1}— bundled init scripts; copied to the ZDOTDIR/BASH_ENV tempdir at spawn time. - Migration: the additive
terminal_blockstable migration (id,session_id,block_index,start_row,end_row,command,exit_code,cwd, timestamps — nois_deleted; blocks are append-only).
IPC channels (v3 additions)
TERMINAL_BLOCKS_LOAD— renderer hydrates its per-session block store on mount.TERMINAL_BLOCK_EVENT(push) — main pushes aTerminalBlockEventto the renderer whenever a block seals or updates.TERMINAL_RUN_COMMAND_IN_SESSION— "Re-run" click: main callsterminalPtyService.write(sessionId, command)with NO trailing newline (user must press Enter).
Known limits + roadmap
- Only one terminal per session row for now (open multiple terminals by creating multiple terminal sessions — sidebar handles them like any other session).
- No SSH profile manager, no split panes, no session recording (roadmap v4).
For agents
Where the code lives
- Main / backend:
src/main/services/engines/terminal-pty-service.ts(node-pty lifecycle),src/main/services/engines/terminal-session-manager.ts(session-manager wrapper),src/main/db/queries-terminal/{scrollback,snippets}.ts(persistence),src/main/ipc/terminal-{handlers,scrollback-handlers,snippet-handlers}.ts(Zod-validated IPC). - Renderer / UI:
src/renderer/src/features/terminal/{TerminalPanel,TerminalCommandPalette,SaveSnippetDialog,TerminalSearchOverlay,useTerminalSession,terminal-{palette,search,new,snippets}-store}.tsx?. - Settings CRUD:
src/renderer/src/features/settings/sections/terminal-snippets/TerminalSnippetsSettings.tsx. - Scoped keyboard dispatchers:
src/renderer/src/hooks/keyboard-shortcuts/{terminal-palette,terminal-search,terminal-new}.ts— Ctrl+K / Ctrl+F / Ctrl+T are dispatched BEFORE the general binding lookup so they beatglobalSearchetc.; the combos are hardcoded (not user-rebindable), mirroring the Team Chat quick-switcher pattern.
IPC channels (all Zod-validated, wrapHandler-wrapped)
- Session lifecycle:
SESSION_CREATE_TERMINAL,TERMINAL_INPUT,TERMINAL_RESIZE,TERMINAL_KILL,TERMINAL_OUTPUT(push). - Scrollback:
TERMINAL_SCROLLBACK_SAVE,TERMINAL_SCROLLBACK_LOAD. - Snippets:
TERMINAL_SNIPPET_LIST,TERMINAL_SNIPPET_CREATE,TERMINAL_SNIPPET_UPDATE,TERMINAL_SNIPPET_DELETE.
Related
Running apps covers the dev-server preview panel — the other place Omniscio starts and shows a process for you — and Drive Omniscio covers the watch-and-steer cockpit that drives the app's own UI. Where Omniscio runs shell commands on your behalf in general — and what it refuses — is described under the app's shell settings.
Last verified 2026-10-06