DSH Plugin Store
Back to home

xuender

dsh-history

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

Stars
2
Language
JavaScript
Created
Aug 14, 2026
Updated
Aug 14, 2026
Other
GitHub repo

Introduction

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