# Installation, operations, and troubleshooting English | [中文](usage.zh.md) ## Choose a distribution - Install **Oh-DSH Desktop** for the complete local workbench. - Install **Oh-DSH Web** for browser-only use without Electron. - Install **Oh-DSH TUI** for terminal-only use without Electron or browser UI. Releases provide Full, Web-only, and TUI-only distributions. The command-line installer installs TUI by default; choose another surface explicitly when needed. ## Install with install.sh `install.sh`, at the repository root, installs the latest stable Release without cloning the repository on macOS and Linux. It needs `curl` and `tar` (`ditto` or `unzip` for the macOS desktop package), and it never requires root for user-local web/tui installs. ```sh curl -fsSL \ https://raw.githubusercontent.com/hust-open-atom-club/oh-dsh/main/install.sh \ | bash ``` On Windows, `install.ps1` is the counterpart and installs the same surfaces (the desktop through the NSIS installer's silent mode). It needs PowerShell 5.1+ and `tar`, both bundled with Windows 10 1803+: ```powershell irm https://raw.githubusercontent.com/hust-open-atom-club/oh-dsh/main/install.ps1 | iex ``` Both scripts accept the same options; PowerShell uses `-Surface`, `-Version`, `-Dest`, `-BinDir`, `-Force`, and `-Uninstall` parameters instead of the lower-case flags. Surface matrix and default locations: | Surface | macOS (arm64/x64) | Linux (x64) | Windows (x64) | | --- | --- | --- | --- | | desktop | `Oh-DSH Desktop.app` into `/Applications` with a Launch Services refresh; registers `ohdsh desktop` in `~/.local/bin` | AppImage into `~/.local/bin/oh-dsh-desktop`; registers `ohdsh desktop` in `~/.local/bin` | NSIS installer run silently (per-user); registers `ohdsh desktop` | | web | payload in `~/.local/share/oh-dsh/web` plus a dispatching `ohdsh` launcher in `~/.local/bin` | same | payload in `%LOCALAPPDATA%\oh-dsh\web` plus an `ohdsh.cmd` shim in `%LOCALAPPDATA%\oh-dsh\bin` (added to the user PATH) | | tui (default) | payload in `~/.local/share/oh-dsh/tui` plus a dispatching `ohdsh` launcher in `~/.local/bin` | same | payload in `%LOCALAPPDATA%\oh-dsh\tui` plus an `ohdsh.cmd` shim in `%LOCALAPPDATA%\oh-dsh\bin` (added to the user PATH) | Only the desktop surface creates a desktop application entry. web and tui never register with Launch Services or create `.app` bundles. Desktop also registers the unified `ohdsh` dispatcher. The web and tui payloads each carry only their own surface's dependencies, so both can be installed side by side: the shared `ohdsh` launcher records each surface's payload and routes `ohdsh web` and `ohdsh tui` to the installation that provides them. Uninstalling one surface keeps the other usable through the same launcher. Options: | Option | Default | Description | | --- | --- | --- | | `--surface` | `tui` | `desktop`, `web`, or `tui`; each installs only its own files and launcher | | `--version` | latest stable | Pin a release tag such as `v0.1.8`. Prereleases are never selected implicitly; they install only when pinned explicitly | | `--local` | off | Install the artifacts this checkout's `pnpm run dist:` commands placed under `release/` instead of downloading a Release. The version comes from the checkout's `package.json`; combine with `--force` to reinstall a rebuilt same version | | `--local-root` | script directory | Point `--local` at another repository checkout | | `--dest` | see matrix above | Destination directory | | `--bin-dir` | `~/.local/bin` | Directory for the `ohdsh` launcher | | `--repo` | `hust-open-atom-club/oh-dsh` | Install from another fork | | `--force` | off | Reinstall when the same version is already present | | `--uninstall` | off | Remove the installed surface | | `--os`, `--arch` | detected | Override target selection (`darwin`/`linux`, `arm64`/`x64`) | Equivalent environment variables: `OH_DSH_SURFACE`, `OH_DSH_VERSION`, `OH_DSH_INSTALL_DIR`, `OH_DSH_BIN_DIR`, `OH_DSH_REPO`, `OH_DSH_OS`, and `OH_DSH_ARCH` (`OH_DSH_LOCAL=1` matches `--local`); options win over the environment. To test a branch you are hacking on, build the surfaces you changed and install straight from the checkout — no release publishing or network round-trip involved: ```sh pnpm run dist:tui && sh install.sh --local --surface tui --force pnpm run dist:web && sh install.sh --local --surface web --force pnpm run dist:mac && sh install.sh --local --surface desktop --force ``` `GH_TOKEN`/`GITHUB_TOKEN` authenticate the GitHub API request (useful behind rate limits), and `OH_DSH_API_BASE`/`OH_DSH_DOWNLOAD_BASE` override the endpoint bases for testing. Upgrade, verification, and uninstall behavior: - The installer reads the SHA-256 digest GitHub publishes for each Release asset and verifies the download before touching the previous installation. A failed download, checksum mismatch, or interrupted extraction leaves the previous install usable and reports the failure; partially staged files are cleaned up. - Re-running the installer with the same version is a no-op unless `--force` is passed. A newer version replaces the payload and refreshes the `ohdsh` launcher atomically. - Upgrades are replace-in-place: once the new installation is validated, the previous app bundle, AppImage, or payload is deleted along with any stale staging directories and pre-upgrade backups, so exactly one Oh-DSH installation remains per surface. - On macOS the desktop surface refreshes Launch Services and retires a stale `Oh-DSH-Desktop.app` bundle, so a single application entry shows. An unnotarized build may still need the right-click **Open** approval described below. - Uninstall with `sh install.sh --uninstall --surface ` (or `install.ps1 -Uninstall` on Windows), honoring the same destination overrides used at install time. ## Automatic update checks Every surface checks for a newer stable Release once per launch: - **TUI** prints one notice line before the first frame, for example `Oh-DSH 0.1.8 -> 0.2.0 is available. Run "ohdsh update" to upgrade.` - **Web** prints the same notice after the listening URL. - **Desktop** checks through its update window and shows a system notification when a new version is found; clicking it opens the update window. The desktop still installs updates through its own verified updater, not the shell installer. `ohdsh update` (or `ohdsh update web` / `ohdsh update tui`) upgrades a packaged web/tui distribution on macOS, Linux, and Windows by re-running the matching installer script with the same verification and atomic replacement as a fresh install. The installation source is inferred the way Codex does it — from the running path, the payload's install marker, and the destinations recorded in `launcher.env` — never from a flag baked into the build, and the recorded `--dest`/`--bin-dir` are reconstructed so an update lands exactly where the install did. An installation at a location the installers do not own is refused with guidance. From a source checkout it asks you to use git instead. Updates are release-based only: every surface compares against published stable GitHub Releases with semver; there is no commit-level or rolling update channel. The checks use the public GitHub API, never block startup for more than about a second and a half, and fail silently offline. Set `OH_DSH_UPDATE_CHECK=0` to disable them everywhere. `ohdsh update` prefers the installer script bundled inside the package at `lib/oh-dsh/install.sh` (or `install.ps1`) and only downloads it from the repository's `main` branch over TLS when the bundle is absent; `OH_DSH_INSTALL_SCRIPT_URL` can point the download at a mirror or a local copy for testing. On Windows the update runs detached after the current process exits, because the running payload cannot be replaced while it executes. ## Install the full distribution ### macOS 1. Download the DMG from the latest Release. 2. Drag **Oh-DSH Desktop** into Applications. 3. For an unnotarized test build, right-click the app in Finder and choose **Open** on first launch. If a verified Release download remains quarantined, apply this to the actual downloaded file: ```sh xattr -d com.apple.quarantine ~/Downloads/Oh-DSH-Desktop-*.dmg ``` Install the unified command: ```sh sudo ln -sf \ "/Applications/Oh-DSH Desktop.app/Contents/Resources/bin/ohdsh" \ /usr/local/bin/ohdsh ``` ### Linux AppImage: ```sh chmod +x Oh-DSH-Desktop-*.AppImage ./Oh-DSH-Desktop-*.AppImage ``` deb: ```sh sudo apt install ./Oh-DSH-Desktop-*.deb ``` ### Windows Run the Windows installer from the Release and start **Oh-DSH Desktop**. The unified CLI is `bin\ohdsh.cmd` under the application resources directory; add that directory to `PATH` if desired. An unsigned installer may trigger Windows SmartScreen. After verifying that it came from the project Release, choose **More info**, then **Run anyway**. The installer may request administrator approval. The window title bar, menu bar, and tool strip are merged into a single row; open the application menu from the labels in the row's left corner. Closing the window minimizes Oh-DSH Desktop to the system tray instead of quitting: click the tray icon to restore the window, and use **Quit Oh-DSH Desktop** in the tray (or application) menu to exit. macOS and Linux keep their usual close behavior. ### Desktop online updates Choose **Oh-DSH Desktop -> Check for Updates...** from the application menu. The updater checks only stable GitHub Releases from `hust-open-atom-club/oh-dsh`; it does not need a GitHub login or token. - macOS, Windows, and Linux AppImage can restart and install after a verified download, or install on the next application quit. - `.deb` downloads and opens the system package installer. It never runs `sudo`, `apt`, or `dpkg` around the system permission boundary. - The updater uses the system proxy configuration. When the configured proxy cannot be reached, the updater retries once without any proxy and keeps the direct connection for the rest of the session. Offline, proxy-auth, 404, insufficient-space, verification, cancellation, and retry states are shown in the update window. A verification failure never replaces the current app. - An update replaces only the application. DSH data, workspace settings, sessions, installed plugins, and marketplace receipts remain in the existing data directory. Automatic updates require a signed packaged Desktop build. Versions installed before the first updater-enabled Release need one manual install; local development builds and Releases without a matching platform package fall back to the official Release page. ### DSH runtime updates (decoupled from the application) The same update window also lists the DSH runtime version. Runtime updates ship as independent `oh-dsh-runtime---.tar.gz` Release assets, so a new DSH release can be applied without reinstalling Oh-DSH Desktop. - **Check Runtime** looks for the newest runtime bundle published for this platform. **Update Runtime** downloads it, verifies the published SHA-256 checksum, stages it under `~/.ohdsh/runtimes//`, and smoke-checks `dsh --version` before activating anything. - Activation writes the pointer `~/.ohdsh/runtimes/current.json` and restarts only the Harness process; the application keeps running. - **Use Bundled Runtime** removes the pointer and restarts the Harness on the runtime bundled with the application build. A failed verification never changes the active runtime. ## Install Web-only ```sh tar -xzf oh-dsh-web-*.tar.gz cd oh-dsh-web-*/ ./bin/ohdsh web ``` Windows: ```bat bin\ohdsh.cmd web ``` Common options: | Option | Default | Description | | --- | --- | --- | | `--host` | `127.0.0.1` | Bind address | | `--port` | `3080` | Listen port; `0` selects a random port | | `--data` | `~/.ohdsh` | Shared Oh-DSH data root for all surfaces | | `--no-open` | off | Do not open the browser automatically | | `--trusted-host` | none | Add a trusted authority; repeatable | Equivalent environment variables include `DSH_OH_WEB_HOST`, `DSH_OH_WEB_PORT`, `DSH_OH_WEB_HOME`, and `DSH_OH_WEB_OPEN`. `OH_DSH_HOME` overrides the data root for Desktop, Web, and TUI together. Press `Ctrl+C` for a graceful shutdown. Do not bind to `0.0.0.0` without an access boundary. For LAN exposure, add `--trusted-host` and put authentication and TLS in a trusted reverse proxy. ## Install TUI-only ```sh tar -xzf oh-dsh-tui-*.tar.gz cd oh-dsh-tui-*/ ./bin/ohdsh tui ``` Use `bin\ohdsh.cmd tui` on Windows. TUI requires a real interactive terminal. It keeps the current terminal position by default, matching the Codex-style inline startup; pass `--fullscreen` to use the alternate screen. ## Unified commands ```sh ohdsh desktop ohdsh gui ohdsh web ohdsh tui ``` - `desktop` opens the installed app and falls back to the Electron development entry when run from a source checkout. - `gui` is an alias for `desktop`. - `web` starts the HTTP service and prints its URL. - `tui` initializes its Profile and attaches the upstream renderer to the current terminal. Common TUI options: | Option | Default | Description | | --- | --- | --- | | `--cwd` | Current directory | Workspace | | `--data` | `~/.ohdsh` | Shared Oh-DSH data root for all surfaces | | `--resume` | New session | Resume a Session id | | `--lang` | Upstream preference | `zh` or `en` | | `--preset` | `standard` | Initial Agent preset | | `--inline` | On | Preserve terminal scrollback instead of alternate screen | ### Agent presets Desktop, Web, and TUI use the same Agent preset roster. The distribution ships `liangshen`, which keeps the root and delegated agents on Minimal's two-tool surface for the first request, promotes to the full catalog after the first tool call, and re-anchors after compaction. Choose it from the Agent preset settings in Web/Desktop; in TUI, enter: ```text /preset liangshen ``` You can also select it at TUI startup with `ohdsh tui --preset liangshen`. The blank-only rule applies after a conversation has started; that choice is saved as the default for the next new session. ## Image input Desktop, Web, and TUI use DSH's native multimodal input. Paste a PNG, JPEG, WebP, or GIF into the message composer (`⌘V` on macOS, `Ctrl+V` on Windows/Linux) or use the attachment button: DSH owns the thumbnail, remove, drag-and-drop, size limits, and submission through its native attachment rail. Models with native image understanding — such as DeepSeek V4 Flash — consume the attachments directly, so no vision bridge, extra model, or separate API key is involved. The former `@oh-dsh/vision` bridge plugin, which described images through an OpenAI-compatible VLM for text-only models, has been removed together with the native-multimodal model line. Its `oh-dsh-vision` settings namespace and the `ZHIPUAI_API_KEY`/`VISION_API_KEY` credentials are no longer read. TUI has no graphical thumbnail; provide a workspace-local image path or an HTTP(S) URL in the prompt to use the same native image input. ## Context insight Desktop and Web bundle [dsh-context](https://github.com/bowenliang123/dsh-context) (pinned release `v0.41.0`) as a built-in plugin. It contributes a Context panel with capacity, remaining, composition, history, event, and message statistics, and a `/context` command that summarizes the current context composition inside the conversation. The plugin is read-only insight: it observes the session through the same projections DSH drives and never mutates the conversation. The panel coexists with the composer's native context ring; both present the same capacity facts. The TUI surface does not bundle the plugin — it is built around interactive panels, and the upstream maintainer does not target TUI. Oh-DSH upgrades the pin deliberately through the submodule revision with each release; it does not follow npm latest automatically. ## Subscription OAuth sign-in Desktop and Web bundle the upstream [dsh-auth](https://github.com/ccch1mneyyy/dsh-auth) host plugin (pinned inside the dsh-TUI submodule; the TUI loads the same package through its renderer). It registers subscription-account LLM routes — ChatGPT/Codex, Claude Pro/Max, and SuperGrok — and contributes the `/auth` command for sign-in, status, and sign-out. The interactive login flow runs through the same question UI each surface already uses; when no interactive surface is present, the command refuses with guidance instead of assuming a browser. Credentials stay in the existing Oh-DSH data directory. ## Desktop operations ### Conversation input history With the main conversation composer focused, `ArrowUp` at the start of the first line recalls the preceding submitted message. `ArrowDown` at the end of the last line moves forward and eventually restores the draft that was present before browsing. In a multi-line draft, arrows away from those boundaries keep their normal caret movement. History is scoped to the current session, contains only confirmed text user messages, and remains in memory only for the current application run. The composer keeps the most recent 100 entries and loads older session messages on demand while that window has capacity. | Action | macOS shortcut | | --- | --- | | Toggle the left sidebar | `⌘B` | | Toggle the bottom Terminal | `⌘J` | | Toggle the right sidebar | `⌥⌘B` | | Open Review | `⌃⇧G` | | Open Browser | `⌘T` | | Open Files | `⌘P` | | Start a Side chat | `⌥⌘S` | | Leave sidebar focus mode | `Esc` | Settings covers language, models, permissions, Agent presets, plugin config, and Oh-DSH skins. Its modal covers and blurs every workspace and sidebar. The About section lists this build's versions: Oh-DSH itself, the pinned upstream DeepSeek Harness runtime, bundled plugins, and key dependencies. On Desktop the same section also runs the full update flow — check for updates, download with live progress, and install — without leaving the page; if GitHub cannot be reached during a check, the updater retries once through a release mirror. Web shows the version inventory without the update card. Choose a skin from Settings on Web or Desktop. In TUI, run `/theme` to select the same Deep Current, Jade Circuit, Porcelain, or Ember Dusk palette. The choice applies immediately and survives restarts. While a skin is active, Appearance changes update the fallback used by **Original**; choose **Original** in the skin gallery to leave the skin. ## Plugin marketplace Desktop, Web, and TUI share one plugin marketplace: all three surfaces can search plugins, prepare candidates, preview, apply, enable, update, and uninstall. Desktop and Web use the sidebar marketplace; in TUI run `/plugins` (or press `Ctrl+M`) to open the terminal marketplace. The catalog labels the surfaces where each plugin is expected to take effect. Installation itself succeeds on all three surfaces when the required preview sandbox is available; if a plugin declares Web or Desktop support only, it will not take effect in TUI after installation, and the cards and details call that out explicitly. Linux x64 uses the staged Landlock launcher for scripted builds. If no write-restricted sandbox is available, a direct human can separately accept an explicitly labelled unsafe build; Agents cannot authorize that mode. Recommended flow: 1. Choose a plugin from Not installed. 2. Inspect its source, commit, permissions, and risk level. 3. Prepare a candidate and preview it in an isolated Profile. 4. Discard it if the result is unsuitable; the current Desktop is unchanged. 5. Apply it explicitly, then enable it separately when needed. 6. Recover the previous state if an update fails. An Agent can initiate the same operation through chat, but still passes through preview, risk approval, and apply. It cannot directly mutate the current Profile. ## Run and package from source ```sh git submodule update --init --recursive pnpm install pnpm run build:dsh pnpm run build pnpm run stage:dsh export PATH="$PWD/bin:$PATH" ohdsh desktop ohdsh web --port 3080 ohdsh tui ``` For faster surface-local development, the repository Makefile stages only the packages required by the selected interface: ```sh make build make tui ARGS="--inline --lang en" make web ARGS="--port 3080" make desktop ``` `make tui` and `make web` do not stage Desktop or other surface packages. Oh-DSH also disables the upstream TUI background update check; pinned runtime updates are handled by the Oh-DSH release flow. Make uses `~/.ohdsh` by default and accepts an `OH_DSH_HOME` override for isolated runs. `pnpm run stage:dsh` remains the full shared stage used by release-oriented workflows. Packaging commands: ```sh pnpm run dist:mac # macOS full distribution pnpm run dist:linux # Linux full distribution pnpm run dist:win # Windows full distribution pnpm run dist:web # Web-only lightweight distribution pnpm run dist:tui # TUI-only terminal distribution ``` The release workflow produces formally signed packages when all GitHub Actions secrets for macOS signing/notarization and Windows Authenticode signing are available. If either credential set is incomplete, the workflow emits an explicit warning and falls back to an ad-hoc-signed macOS package or an unsigned Windows installer without blocking Web, TUI, and Desktop packaging. Fallback artifacts support only the manual installation described above and must not be treated as supporting automatic updates. Formal signing requires `MACOS_CSC_LINK`, `MACOS_CSC_KEY_PASSWORD`, `APPLE_ID`, `APPLE_APP_SPECIFIC_PASSWORD`, `APPLE_TEAM_ID`, `WINDOWS_CSC_LINK`, and `WINDOWS_CSC_KEY_PASSWORD`. Installers, embedded or external blockmaps, and `latest*.yml` metadata remain strictly validated and stop the release when missing. Run the Release workflow manually from Actions for a four-platform packaging check; manual runs upload workflow artifacts without creating a GitHub Release. ## Data and troubleshooting Desktop, Web, and TUI share `~/.ohdsh` by default and do not load global plugin configuration from `~/.dsh`. They keep separate `profiles/desktop`, `profiles/web`, and `profiles/tui` compositions while sharing sessions, credentials, skins, and plugin caches. Electron-specific data lives under `~/.ohdsh/desktop`. Override all surfaces with `OH_DSH_HOME`, or isolate one Web or TUI process with `--data`. Configure the DeepSeek API key in Models settings or in `~/.ohdsh/.env`. On first use of the shared root, Desktop imports sessions, credentials, plugins, and UI preferences from the old system `Oh-DSH-Desktop` application-data directory. Web imports the former `~/.oh-dsh-web/dsh` root and a nested `dsh/` inside the selected data directory, plus root-level skin and sidebar preferences. Migration copies only missing data and leaves legacy directories in place for rollback; existing shared state is not replaced. Only one Oh-DSH surface owns the shared data root at a time. Other surfaces can start in read-only mode to view history, but cannot write to active sessions while the owner is running. Troubleshooting order: 1. Run `ohdsh --help` to confirm the CLI source. 2. Run `ohdsh web --help` to inspect options. 3. Run `ohdsh tui --help`, then use `ohdsh tui --inline` to isolate alternate-screen terminal compatibility. 4. Test a random port with `ohdsh web --port 0 --no-open`. 5. Confirm that required plugins are both installed and enabled in the Profile. 6. If Desktop does not start, run its bundled `bin/ohdsh desktop` in a terminal to capture logs. See [design and plugin boundaries](./design.md) for architecture and upstream relationships.