Bundle
dsh-oh-my-terminal
DSH Web GUI 底部终端面板插件——node-pty 驱动的多标签交互式终端(Windows ConPTY / POSIX openpty)
- Source
- btsd321
- stars
- 1 stars
- License
- Apache-2.0
- Updated
- Updated 2 hours ago
Readme
# dsh-oh-my-terminal
[](package.json)
[](LICENSE)
[](package.json)
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.
[中文文档](README.zh.md)
## 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
## Installation
This package is not yet published to npm. Install directly from GitHub:
```bash
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
```bash
# 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)
│ ├── 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](LICENSE)
Install
dsh plugin --profile web add github:btsd321/dsh-oh-my-terminal#d9b47ce20256b47ef096a1ea3d935a2d61e7ac60
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-oh-my-terminal from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.