Development & Runtime

dsh-oh-my-terminal

btsd321/dsh-oh-my-terminal · ★ 1

btsd321

DSH Web GUI 底部终端面板插件——node-pty 驱动的多标签交互式终端(Windows ConPTY / POSIX openpty)

License
Apache-2.0
Added
2026-10-30
Maintenance
active
Install kind
github
Manifest status
Declared
Manifest path
package.json#dsh
Manifest checked
2026-10-30T09:39:09.038Z
Lifecycle scripts
None found

Static manifest checks report declarations only; they are not compatibility or security review.

安装

dsh plugin --profile web add 'github:btsd321/dsh-oh-my-terminal#e40df7b16a162b4df57bd9f77001474d347da748'

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

For install and environment setup, plus plugin development tutorials, see DSH community docs ↗

README

Source README · body: en · Read Chinese README

Table of contents
  1. Features
  2. Installation
  3. Configuration
  4. Terminal profiles
  5. Development
  6. About the build output
  7. Native dependency notes
  8. Architecture overview
  9. License

license node

A bottom terminal panel plugin for DSH Web GUI. Powered by @lydell/node-pty, it provides multi-session interactive terminals over WebSocket using xterm.js in the browser. Supports Windows ConPTY and POSIX openpty with no local compilation required.

中文文档

Features

  • Multiple terminal sessions: manage several sessions simultaneously; a side list replaces the traditional horizontal tab bar, with right-click rename support
  • Split terminals: horizontal splits within the same group; a VSCode-style dropdown next to the + button (new / split / new by kind)
  • Session persistence: sessions survive panel close/reopen and are automatically restored on startup
  • Configurable shortcut: toggle the panel with a keyboard shortcut; integrates with the host shortcut system and the panel label updates to reflect the current binding
  • Resizable panel: drag the top edge of the panel to adjust its height
  • Cross-platform: Windows ConPTY and POSIX openpty are selected automatically by @lydell/node-pty; pre-compiled binaries ship with the package, nothing to compile
  • Profile-driven terminals: a configurable terminal profile table (type / name / path) drives new-terminal creation; profiles are auto-detected at startup and can be added, renamed, and edited in the settings UI
  • Configurable fonts: font family, size, and line height are adjustable and hot-reload on open terminals
  • DSH-better-sidebar compatibility: auto-detects DSH-better-sidebar at runtime and switches to compat mode — registers a "Terminal" tab in its bottom workbench instead of the standalone dock; PTY sessions are not bound to the DSH session write handle, eliminating conflicts with DSH-better-sidebar's own terminal. When the host supports TabDescriptor.rightActions (v0.25.0+), the terminal's action buttons (new / split / restart) are injected into the tab strip's right end, VSCode-style; otherwise it falls back to a header row inside the tab content area

Installation

This package is not yet published to npm. Install directly from GitHub:

dsh plugin --profile web add github:btsd321/dsh-oh-my-terminal

Configuration

Option Description Default
toggleShortcut Shortcut to toggle the terminal panel (legacy host only; see below) Ctrl+Shift+`
fontFamily Terminal font family (CSS font-family string); empty = built-in default stack with CJK fallback ''
fontSize Terminal font size in pixels 12.5
lineHeight Terminal line height multiplier 1.25
terminalProfiles Terminal profile table (JSON array); empty = use auto-detected $PATH terminals ''

Terminal profiles

The terminal profile table is a JSON array of { id, type, name, path, origin } entries:

  • type: determines spawn semantics — pwsh / powershell / cmd / bash / zsh / fish / gitbash / nushell / custom
  • name: display name shown in the dropdown menu (user-editable)
  • path: executable path; empty = resolve by type in $PATH
  • origin: auto (startup-detected) or user (manually added)

Auto-detected profiles (origin: auto) cannot be deleted and their path is read-only, but the name is always editable. The profile table is editable in the settings UI with inline editing, add-row, and delete support.

Development

# Install dependencies (@lydell/node-pty ships pre-compiled binaries — ready to use immediately)
pnpm install

# Type check
pnpm run typecheck

# Build (esbuild, two entry points, output to lib/)
pnpm run build

# Unit tests
pnpm exec tsx --test tests/unit/*.test.ts

Use pnpm, not npm. Peer dependencies pin exact versions; npm's incremental resolution on an existing tree will produce ERESOLVE errors.

About the build output

lib/ is committed to version control. The DSH loader imports plugins as plain ESM; it does not run tsx. This repo also declares no lifecycle scripts (prepare, postinstall, etc.) because pnpm 11 rejects git-hosted packages that declare install-time scripts with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED. Run pnpm run build manually and commit the output alongside source.

Native dependency notes

Terminal capability comes from @lydell/node-pty (a pre-compiled distribution of microsoft/node-pty with the same API), pinned exactly to 1.1.0. The ^ range is intentionally omitted: the package's dist-tags.latest points at the 1.2.0-beta series.

It is an N-API package. Binaries are split into six platform sub-packages and shipped inside the tarball; no download or compilation happens at install time. A single binary supports both Node 22 and Node 24. Its package.json has no scripts field at all, so pnpm 10, 11, and 12 never enter the build-authorization path, giving consistent behavior across versions.

The host side lazy-loads the package (await import() on first session creation). If the native binding fails to load, the error is contained to session creation; the plugin module itself remains importable and all other routes stay available.

Architecture overview

src/
├── index.ts              # Host entry (Cordis plugin + settings + session lifecycle)
├── routes.ts             # HTTP route handlers
├── ws-handler.ts         # WebSocket handler (pty data forwarding)
├── client.tsx            # Browser entry (React components + plugin registration)
├── client/
│   ├── types.ts          # Shared types
│   ├── hooks.ts          # useReducer state management + custom hooks
│   ├── term-pane.tsx     # xterm.js terminal pane component
│   ├── dropdown.tsx      # Dropdown menu next to the + button
│   ├── side-list.tsx     # Right-side terminal list panel
│   ├── styles.ts         # CSS constants + Campbell dark theme
│   ├── icons.tsx         # SVG icon components
│   ├── clipboard.ts      # Clipboard utility functions
│   ├── shortcut-bridge.ts # Shortcuts service integration (command registration + toggle bridge)
│   ├── compat.ts          # DSH-better-sidebar compat mode detection (soft-probe ctx.betterSidebar + service interface)
│   ├── sidebar-tab.tsx    # Sidebar terminal tab (compat mode: embed in DSH-better-sidebar bottom workbench, no DSH session binding)
│   ├── settings/         # Settings UI (types / store / card / profile-table / api / styles)
│   └── terminal/         # Terminal tab state (use-tabs / reducer / use-terminal-state / geometry)
├── persistence.ts        # Session persistence (log storage, metadata, startup restore)
├── platform.ts           # Platform adapter (POSIX / Windows + shell detection)
├── terminal/             # Terminal kinds, detection, resolution, profile store
├── settings/             # Settings bridge (namespace, bridge routes, patch ops)
├── constants.ts          # Protocol, size, shortcut, and env var constants
├── server-command.ts     # Command-line parsing utilities
├── shortcut.ts           # Shortcut parsing utilities
└── logger.ts             # Structured logger

The host side and browser side communicate over WebSocket at /api/dsh-oh-my-terminal and do not import each other directly.

License

Apache-2.0