xuender / dsh-history

Listed

Recall and re-run the current session's command history with ↑/↓ keys in the DSH Web composer.

mainSession View source

Installation

npx -y @deepseek-ai/dsh plugin --profile web add github:xuender/dsh-history

This installation command is an unverified starting point generated from the GitHub repository address.

README

Maintainer-authored documentation snapshot.

View on GitHub ↗
Commit 9062803Synced Aug 18, 2026

English · 简体中文

dsh-history — DSH Web command history plugin

Remembers the current session's command history in the DSH Web GUI: with the composer input focused, press ↑ / ↓ to step through previously sent commands, edit them, and press Enter to re-send.

✨ Features

  • Recording — every message you send in the current session (plain messages and /xxx slash commands) is recorded automatically, isolated per session. History is derived from the session log (user/command nodes), so it is rebuilt automatically after a page reload — no extra storage needed.
  • — step back to the previous command; keep pressing to go further back. The first press saves the draft you were editing, and pressing ↓ afterwards returns to it.
  • — step forward to a newer command; from the newest entry, one more ↓ returns to the saved draft.
  • Edit & re-run — a recalled command lands in the composer draft; edit it directly and press Enter to re-send.
  • Safe fallbacks — while a / or @ trigger menu is open, during IME composition (e.g. Chinese input), when the composer is busy/locked, or when the input is not focused, ↑/↓ keep their native behavior and never interfere.

📦 Installation

The plugin is a standard DSH static plugin (see the develop/basic tutorial). The entry name must be the bare package name dsh-history, and the package directory must be resolvable from both resolution trees (the host loader resolves the bare name from the DSH installation's node_modules; the client-modules scanner resolves dsh-history/package.json upward from the profile directory), so two symlinks are required:

# 1) profile side (client-modules scanner): $DSH_HOME defaults to ~/.dsh
ln -s /absolute/path/to/dsh-history ~/.dsh/profiles/node_modules/dsh-history

# 2) install side (host loader bare-name resolution): point to the dsh installation's node_modules
ln -s /absolute/path/to/dsh-history /home/ender/.npm/_npx/1e7f6d9597241db0/node_modules/dsh-history

Then launch with the patch:

dsh web --patch /absolute/path/to/dsh-history/cordis.yml

Or merge the cordis.yml contents (the insert stanza) into $DSH_HOME/profiles/web/cordis.patch.yml to load it permanently.

🗂️ Directory layout

dsh-history/
├── package.json         # dsh.client declaration (platform: web) → scanned into __DSH_BOOT__ by client-modules
├── cordis.yml           # patch: inserts the plugin entry into the loader
├── lib/
│   ├── index.js         # host half: placeholder only (the loader needs a resolvable module)
│   └── client.js        # browser bundle: history recording + ↑/↓ navigation + dock indicator
├── scripts/
│   └── smoke-test.mjs   # Node smoke test (npm test)
├── README.md            # this file (English)
└── README.zh-CN.md      # 简体中文版

⚙️ How it works

  • Client-module mechanism — the package declares dsh.client: { platform: "web" } with exports["./client"] pointing at lib/client.js; dsh-client-modules then bundles that entry into window.__DSH_BOOT__ and serves it at /plugins/<entry>/client.js. The browser side registers the plugin through window.__ModuleLoader__.load({ id, factory }).
  • Recording — a component registered on the conversation.input.dock slot subscribes to the session snapshot (useSession((s) => s.nodes)) and incrementally scans user/command nodes by seq (the list is seq-ascending and untruncated), collapsing adjacent duplicates, capped at 100 entries, stored in a module-level Map<sessionId, …>.
  • Navigation — a capture-phase keydown listener on document takes over ↑/↓ only when the focus is inside [data-composer-card], no trigger menu is open (claim is empty), not composing IME input, no modifier keys are held, and the composer is not busy — writing the draft via inputActions.setDraft(text). The editing check returns you to the live position automatically after you type.
  • Indicator — while browsing, a small “history n/m” badge is shown above the composer.

⚠️ Limitations

  • History is per-session and in-memory (rebuilt from the session log after a page reload, so nothing is lost within a session; it is discarded when the browser closes).
  • Slash commands are recalled as /name args (from command nodes).
  • Image-only messages (no text) are not recorded.

🤝 Community

  • Contributing Guide — how to report bugs, request features, and open pull requests (including beginner-friendly good first issue tasks).
  • Code of Conduct — the expectations we hold for everyone in this community.
  • Security Policy — how to report a vulnerability privately.
  • Support — where to ask questions (Issues vs. Discussions).

📄 License

MIT © xuender

Project files and signals

Shown items are public repository signals detected in the directory snapshot.

Security policyDetected
Contributing guideDetected

Repository information

Language
JavaScript
License
MIT
Last updated
Aug 14, 2026, 6:39 AM

Install deliberately

Review source code, permissions, lifecycle hooks, dependencies and network access. Test untrusted plugins in an isolated environment.