Bundle
dsh-agent-preset-recommender
Privacy-safe local activity scanner and agent preset recommender for DeepSeek Harness
- Source
- LeemanCheung
- stars
- 3 stars
- License
- MIT
- Updated
- Updated 4 days ago
Readme
# dsh-agent-preset-recommender
[](https://awesome.re) [](https://awesome-dsh-plugin.com) [](https://github.com/LeemanCheung/dsh-agent-preset-recommender/actions/workflows/ci.yml)
English | [中文](README.zh.md)
A persistent, host-side [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) bundle that privately summarizes local Codex, Claude Code, and WorkBuddy/CodeBuddy activity and recommends a built-in DSH agent preset. It is advisory only: there is no LLM call, installation, preset mutation, or network request.
Compatibility baseline: DeepSeek Harness `0.1.2-rc.1`, Cordis `4.0.2`, and Schemastery `3.18.2`.
The installed Host result is recorded in [Windows DSH 0.1.2 acceptance](docs/WINDOWS_DSH_0.1.2_ACCEPTANCE.md).
## Preview


> These previews use synthetic aggregate fixture data. They illustrate the bounded tool results only; no user sessions, paths, prompts, commands, or secrets appear.
## Capability map
| Area | What the plugin does | Deliberate boundary |
| --- | --- | --- |
| Local inventory | Boundedly scans supported session, project, and workflow metadata from Codex, Claude Code, CodeBuddy, and WorkBuddy. | Skips caches, builds, `.git`, symlinks, inaccessible roots, and unknown content. |
| Privacy-preserving evidence | Aggregates tool, session, workflow, and day-level activity under installation-local HMAC project IDs. | Never persists prompts, replies, commands, arguments, raw events, paths, usernames, secrets, or file bodies. |
| Deterministic advice | Maps observed evidence to `minimal`/`standard` capability presets plus optional delegation, workflow, web, MCP, and LSP capabilities. | Knows the shipped `minimal`, `standard`, `ptc`, and `cordis` roster, but never changes the user's current selection. |
| Agent-facing access | Provides `scan_agent_projects` for a fresh bounded scan and `get_agent_preset_recommendations` for the saved report. | Both tools return bounded readable text; neither installs, enables, or authenticates anything. |
| Durable local operation | Atomically persists a private report, supports startup and scheduled scans, and serializes all scan triggers. | No LLM call, network request, discovered-command execution, or background work survives plugin disposal. |
## Install
```sh
dsh plugin --profile web add github:LeemanCheung/dsh-agent-preset-recommender
```
Restart the selected DSH profile after installation. The package declares `dsh.bundle.patch` and mounts one host plugin.
## What it recommends
Observed aggregate behavior is mapped to:
- capability presets: `minimal` or `standard`.
DSH `0.1.2-rc.1` ships `minimal`, `standard`, `ptc`, and `cordis`. The scanner lists that roster for accuracy, but automatic advice remains limited to the general-purpose `minimal` and `standard` choices. It never writes a default or current preset, so an explicit user selection remains unchanged.
- optional capabilities: Codex delegation, Claude Code delegation, workflows, web, MCP, and LSP.
Every recommendation includes confidence and numerical evidence. Thresholds are deterministic and local; results never automatically change DSH.
### Exact recommendation and evidence rules
- `standard` is recommended when **at least one** recognized session, workflow, or categorized tool call exists. Metadata files alone—and an empty observation set—yield `minimal`.
- Codex/Claude Code delegation needs a recognized session from that source. Workflows need a workflow count or `workflow`-category tool call; `web`, `MCP`, and `LSP` need their corresponding category count.
- Confidence is `0` with no observations; otherwise it is `min(0.95, 0.35 + 0.2 × log10(observations + 1))`, rounded to two decimal places, where observations are sessions + workflows + categorized tool calls.
- Tool names first use exact delegation aliases, then the fixed heuristic order **delegation → workflow → MCP → LSP → web → shell → search → files**; the first match wins and unmatched names are `other`. These are trend signals, not an audit of every product tool.
## Architecture
```text
cordis.patch.yml → src/index.js (Cordis lifecycle + raw model tools)
├─ scanner.js (bounded traversal and aggregation)
├─ extractors.js (selected JSON/JSONL metadata fields)
├─ recommender.js (deterministic rules)
├─ store.js (atomic private report file)
└─ render.js (bounded readable tool output)
```
Runtime code is plain ESM JavaScript for Node.js 20+. It uses Node built-ins plus `@deepseek-ai/schemastery` for plugin configuration validation. Tool definitions are registered directly through `ctx.tools.register` and do not import unpublished DSH tool runtime helpers.
## Privacy
The scanner persists aggregate metadata only:
- source and installation-keyed project identifier;
- categorized tool counts;
- session, workflow, and project-metadata counts;
- first/last observation dates (day-level);
- recommendation, confidence, and evidence counts;
- an explicit machine-readable privacy declaration.
It **never persists** prompts, responses, commands, tool arguments, raw events, absolute paths, usernames, secrets, or file contents. Project identifiers are derived with a random installation-local HMAC key, so report IDs cannot be dictionary-matched without the private key. WorkBuddy/CodeBuddy memory metadata is counted from file presence and modification time only; workflow/plan files are likewise never opened. The scanner makes no network requests and runs no discovered command.
Cache, dependency, build, output, coverage, virtual-environment, and `.git` directories are skipped. Symbolic links are not followed.
The default report is:
```text
$DSH_HOME/state/agent-preset-recommender/report.json
```
If `DSH_HOME` is unset, `~/.dsh` is used. The directory also holds a private random `identity.key` used only to derive project IDs. Report writes use a same-directory temporary file and atomic rename; restrictive permissions are requested where the platform supports them.
## Supported locations and formats
| Source | Defaults | Read behavior |
| --- | --- | --- |
| Codex | `$CODEX_HOME/sessions`, `$CODEX_HOME/archived_sessions` or `~/.codex/*` | Bounded `.jsonl`/`.json`; selected session/project and tool-name fields |
| Claude Code | `$CLAUDE_CONFIG_DIR/projects` or `~/.claude/projects` | Bounded `.jsonl`/`.json`; selected project and `tool_use` name fields; workflow sidecars, journals, task/session/plan stores, and global history are excluded |
| Claude personal workflows | `$CLAUDE_CONFIG_DIR/workflows` or `~/.claude/workflows` | `.js` file presence and day only; scripts are never opened. Add project-local `<repo>/.claude/workflows` explicitly to `claudeWorkflowRoots` if desired |
| Claude transcripts | Disabled | Scanned only when `claudeTranscriptRoots` is explicitly configured |
| CodeBuddy CLI | `$CODEBUDDY_CONFIG_DIR/projects` or `~/.codebuddy/projects` | Bounded canonical project `.jsonl` records; `~/.codebuddy/workflows/*.js` and project-local workflow scripts are inventoried by presence only. Process maps, tool-result/blob directories, and workflow runtime sidecars are excluded |
| WorkBuddy | `$WORKBUDDY_CONFIG_DIR/projects` or `~/.workbuddy/projects`, `~/.workbuddy-ai/projects` | Heuristic, version-sensitive project `.jsonl` inventory; native session layout is not vendor-contracted, so it is never treated as proof of CodeBuddy session equivalence |
| Project-local CodeBuddy/WorkBuddy metadata | `<project>/.codebuddy` or `<project>/.workbuddy` `memory`, `workflows`, `plans`, or `automations` | Count and day only, including workflow `.js`; content is not read; memory never becomes workflow evidence |
Formats vary between product releases. CodeBuddy paths/workflow scripts are documented; WorkBuddy session-file detection is an observed heuristic. Unknown fields are ignored, malformed records are skipped, and malformed files are counted as errors without stopping the scan.
## Configuration
Configure the inserted `agent-preset-recommender` row in a DSH patch:
```yaml
- id: agent-preset-recommender
config:
scanOnStart: true
intervalMinutes: 360 # 0 disables scheduled scans
maxFilesPerSource: 500
maxBytesPerFile: 1048576
recentDays: 90
stateDirectory: '' # empty = $DSH_HOME/state/agent-preset-recommender
codexRoots:
- ~/.codex/sessions
- ~/.codex/archived_sessions
claudeRoots:
- ~/.claude/projects
claudeTranscriptRoots: [] # opt in explicitly
claudeWorkflowRoots:
- ~/.claude/workflows # inventory only; script content is never read
workbuddyRoots:
- ~/.codebuddy
- ~/.workbuddy
- ~/.workbuddy-ai
- ~/WorkBuddy
- ~/CodeBuddy
```
Defaults honor `CODEX_HOME`, `CLAUDE_CONFIG_DIR`, `CODEBUDDY_CONFIG_DIR`, and `WORKBUDDY_CONFIG_DIR` when DSH starts. Supplying an explicit root list in the plugin configuration takes precedence over those defaults.
Bounds are validated: `intervalMinutes` is 0–35,791, `maxFilesPerSource` 1–100,000, `maxBytesPerFile` 1 KiB–64 MiB, and `recentDays` 1–3,650. Missing/inaccessible roots are skipped. Startup, scheduled, and tool-triggered scans share one serialized queue and are aborted on plugin disposal.
Set both `scanOnStart: false` and `intervalMinutes: 0` to disable **automatic** scans; the model tool can still scan on demand. Before deleting the state directory to reset the report, stop the plugin: this also removes `identity.key`, intentionally rotating every keyed project ID.
## Model tools
### `scan_agent_projects`
Runs and persists a fresh scan. Optionally refresh only selected sources:
```json
{ "sources": ["codex", "claude"] }
```
Unselected source aggregates from the previous report remain intact.
### `get_agent_preset_recommendations`
Reads the persisted report without scanning:
```json
{}
```
Or retrieve one keyed project:
```json
{ "project_id": "codex-0123456789abcdef" }
```
Both tools return bounded readable text strings. Omitting `sources` or passing an empty list scans every source; a selected-source scan preserves the prior aggregate for unselected sources.
Each persisted source report exposes `filesConsidered`, `truncatedFiles`, `skippedOld`, `skippedOversize`, `skippedLimit`, and `parseOrAccessErrors` alongside counts. Summary output lists at most 50 projects and is capped at 12,000 characters; query a `project_id` for its bounded detail.
## Limitations
- Metadata schemas are intentionally conservative; unrecognized tool events may be undercounted.
- Keyed IDs are stable only while the private state directory remains available; deleting `identity.key` intentionally creates a new identifier set.
- A recommendation reflects observed local frequency, not task quality or organizational policy.
- The plugin does not verify that optional products or capabilities are installed or authenticated.
- JSONL files above the byte cap are prefix-sampled within the byte/record bounds; their remaining data, oversized JSON files, old files, and older files beyond a source limit are intentionally omitted. Compressed Codex `.jsonl.zst` rollouts are not read in 0.1.7. Claude workflow scripts and dynamic workflow sidecars are deliberately not parsed.
## Development
```sh
npm install
npm test
```
Tests use synthetic temporary fixtures and Node's built-in `node:test`; no local product data is read. See [SECURITY.md](SECURITY.md) for private vulnerability reporting guidance.
## License
[MIT](LICENSE)
Install
dsh plugin --profile web add github:LeemanCheung/dsh-agent-preset-recommender
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-agent-preset-recommender from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.