dsh-title-curator
Stable, human-recognisable session titles for DeepSeek Harness.
Every session ends up as category emoji + object|goal, for example 🧩 邮箱注册|验证码过期修复. The naming policy is ported from oil-codex-title; the scheduling, state machine and host integration are written against DSH's official session-title API.

Real sidebar capture (default width; the host truncates long titles).
Why
A sidebar full of "回应中文问候"、"继续修改" is useless once several projects run in parallel. This plugin keeps the title on the main line of work instead of the last sentence: the object stays stable, the goal updates only when the work actually changes, and anything you renamed yourself is never touched again.
What it does
| Trigger | user/message (debounced), turn/end, session/created (opening an old conversation), first request/header |
| Model | the session's own route via ctx.llm.stream, cheapest supported reasoning effort |
| Write | ctx.sessionTitle.rename(), metadata only — no message is added, nothing enters model context |
| Failures | silent: the current title stays, the reason goes to audit.jsonl |
Behaviour worth knowing:
- Idempotent — a content fingerprint (policy version + cwd + title + recent message hashes) skips unchanged opportunities without a model call.
- Manual rename wins forever — the plugin records the title event seq it wrote; any change afterwards locks the session permanently.
- No duplicate titles — a candidate equal to another live session's title is retried once with the conflict list, then dropped rather than decorated with a fake suffix.
- Keep-only-when-compliant — a
keepanswer against a title that does not matchemoji + object|goalis rejected and retried with explicit feedback. - Cheap — pure acknowledgements ("ok", "thanks", "继续") skip the model, and a session is evaluated at most once every 90 seconds.
Install
From GitHub:
dsh plugin --profile desktop add github:chancecc99-gif/dsh-title-curator
From a local checkout:
dsh plugin --profile desktop add /absolute/path/to/dsh-title-curator
Restart the host afterwards (a new package needs a fresh module generation). Uninstall:
dsh plugin --profile desktop remove dsh-title-curator
Titles already written are ordinary session/title events and survive uninstall.
Configuration
Override the row in the profile's cordis.patch.yml:
- id: title-curator
config:
enabled: true
debounceMs: 6000
minIntervalMs: 90000
maxTokens: 700
sweepDelayMs: 4000
See README.zh.md for the full table.
Privacy
Only the last 5 human messages (600 chars each), the current title, the last cwd segment and up to 16 titles of other live sessions are sent to the model. Assistant answers, tool output, file paths and attachments are never included.
State lives in $DSH_HOME/plugin-data/dsh-title-curator/ (state.json, audit.jsonl). Deleting it degrades safely to "never touch a user-sourced title".
Limits
- Only live sessions can be renamed: DSH exposes no public write path for a session that is not mounted. Opening a conversation triggers a pass; an untouched, never-opened session keeps its old title.
- Titles are metadata, not folders — the emoji is a visual group, not a category tree.
- A session with thousands of events costs one log scan per evaluation.
Development
npm test # 24 tests: validators, parser, assembler, fingerprint, decision table, end-to-end host fake
Licence
MIT. Naming rules and the original Codex implementation: oil-oil/oil-codex-title (MIT).
No comments yet. Be the first to write one.