Bundle
dsh-glob-rules
Glob-activated rule prompts for DeepSeek Harness (DSH): when the agent reads or edits a matching file, the rule activates and is injected into the conversation (Claude Code rules.md / # Path: style).
- Source
- TURIING
- License
- MIT
- Updated
- Updated 13 hours ago
Readme
# dsh-glob-rules
[](LICENSE)
[](https://github.com/topics/dsh-plugin)
**English** | [中文](./README.zh.md)
Glob-activated rule prompts for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH) — a Claude Code `rules.md` / `# Path:`-style mechanism. Each rule declares glob patterns; when the agent **reads or edits** a matching file, the rule activates and its content (any prompt or markdown document) is injected into the conversation as a superseding `<rules>` snapshot.
> A TypeScript re-creation of [`dsh-rules`](https://github.com/rj-jiangyichen/dsh-rules) with the same behavior, written against the current [plugin development guide](https://deepseek-harness.github.io/deepseek-harness/en/develop/basic/) and the installed framework surface (cordis 4.x, `dsh-*` rc packages). The one breaking API change versus the original: session history is now read through `session.snapshotEvents()` — the old `session.events` array no longer exists — and the package ships TypeScript compiled with `tsc` like today's plugins.
> Works in **every DSH deployment**: desktop / web / tui / headless / custom profiles — nothing about this plugin is desktop-specific.
## Contents
- [Features](#features)
- [How it works](#how-it-works)
- [Installation](#installation)
- [Rule format](#rule-format)
- [Configuration](#configuration)
- [Discoverability](#discoverability)
- [Development](#development)
- [License](#license)
## Features
- **Glob activation** — rules activate per file the agent touches: `**`, `*`, `?`, `{a,b}`, `[abc]`, and `!` negation (picomatch).
- **Claude Code compatible** — plain rule files (`.dsh/rules/*.md`) *and* `# Path:` sections inside `CLAUDE.md` / `AGENTS.md`.
- **Visible & durable** — active rules are injected as a user message the UI shows and the session log persists; each snapshot supersedes earlier ones, so the model always sees the current set.
- **Budget-bounded** — byte-budget rendering (32 KB default): low-priority rules are dropped first, then the last rule is truncated; content is escaped so it can never break out of the framing tags.
- **Resume-friendly** — on session resume the last snapshot and its matched files are restored from the log (`session.snapshotEvents()`), preventing duplicate injection.
- **Per-session tracking** — every agent/session tracks its own touched files (subagents included); global rules (no `path:`) are always active.
## How it works
```
workspace
.dsh/rules/*.md ← rule definitions (frontmatter declares globs)
~/.dsh/rules/*.md ← user-level rules (optional)
AGENTS.md/CLAUDE.md ← optional: # Path: sections (Claude Code compatible)
agent reads/edits a file (fs/observed) → record per-session touched path
↓ every step (agent/pre-step)
match touched paths against globs → collect active rules → render a <rules> snapshot into the conversation
```
- **Injection point**: an `agent/pre-step` waterfall listener appends a `<rules>`-framed user message; a new message is only appended when the snapshot text changes.
- **Discovery & caching**: rule sources are re-probed per step with version caching (`fs.stat().version`, or `mtimeMs:size` on the Node fallback) — edits to rule files take effect on the next step.
- **Reads**: prefer the harness `fs` service (containment-aware); fall back to Node's filesystem when no `fs` service is mounted.
## Installation
Published as a DSH **bundle** (declares `dsh.bundle.patch`), so `dsh plugin` installs **and activates** it in one step:
```powershell
# Adjust the profile name: desktop / web / tui / headless
dsh plugin --profile desktop add dsh-glob-rules
```
The reconcile pass appends `dsh-glob-rules` to the profile's `dsh.profile.bundles` layer list automatically — **no manual `cordis.patch.yml` edits are needed**. Restart DSH (restart the desktop app; restart the web/headless process) and the plugin loads with the next Cordis composition.
Installing from a local checkout or a git host (development): the package ships a `prepare` script that builds `lib/` from `src/` with `tsc`, so `dsh plugin --profile desktop add .` (or `add github:you/dsh-glob-rules`) works too. pnpm ≥10 asks you to allow the git dependency's `prepare` script first — copy the exact package key pnpm prints into the profile's `pnpm-workspace.yaml` under `allowBuilds`, then re-run the `add`.
Per-profile configuration (optional): the plugin loads with its code defaults; to customize, override the entry's `config` in `<profile>/cordis.patch.yml`:
```yaml
- id: dsh-glob-rules
name: dsh-glob-rules
config:
includeClaudeSections: true
projectRootMarkers: [".git", ".dsh"]
```
Remove: `dsh plugin --profile desktop remove dsh-glob-rules`, then restart.
## Rule format
### Source A: rule files (`.dsh/rules/*.md` and `~/.dsh/rules/*.md`)
```markdown
---
path:
- "src/**/*.ts"
- "!src/**/*.test.ts"
---
Rule body (markdown, injected verbatim when active — any prompt content works)
```
| Frontmatter field | Description |
| --- | --- |
| `path` | String or list of globs, relative to the project root, `/` separators; `!` prefixes mark exclusion patterns. **Absent or empty = always-active global rule** (active for any session in the workspace). |
| `name` | Optional; rule identity (used for same-name deduplication). Defaults to the file name without `.md`. |
### Source B: `# Path:` sections (requires `includeClaudeSections: true`)
Parses `# Path: <globs…>` headings out of `AGENTS.md` / `CLAUDE.md` (including `.local.md` variants and `~/.dsh/AGENTS.md`):
```markdown
# Project notes (content before the first heading is handled by the built-in agent-instructions baseline, not by this plugin)
# Path: src/**/*.ts, scripts/**
This section activates only when a file under src/**/*.ts or scripts/ is touched
```
- Each `# Path:` heading starts a rule that runs until the next heading (or end of file).
- Globs may be comma- or space-separated.
- Content before the first `# Path:` heading is intentionally **not** injected by this plugin — DSH's built-in `agent-instructions` already injects the full AGENTS.md/CLAUDE.md baseline.
### Precedence & deduplication
Project rules (rank 100) > user rules (rank 200) > `# Path:` sections (rank 300). Same-name rules keep the highest-priority entry; rendering order is (rank, name) — deterministic across steps.
## Configuration
| Option | Default | Description |
| --- | --- | --- |
| `dshHome` | `$DSH_HOME` / `~/.dsh` | Root for user rules and `~/.dsh/AGENTS.md` |
| `projectRootMarkers` | `[".git"]` | Marker files/dirs used to find the project root by walking up |
| `ruleDirNames` | `[".dsh/rules"]` | Rule directories inside the project (relative to the project root, multiple allowed) |
| `includeUserRules` | `true` | Enable `~/.dsh/rules/*.md` |
| `includeClaudeSections` | `false` | Parse `# Path:` sections |
| `instructionFileCandidates` | `["AGENTS.md", "CLAUDE.md"]` | Candidate file names for `# Path:` sections |
| `localInstructionFileCandidates` | `["AGENTS.local.md", "CLAUDE.local.md"]` | Per-directory candidate file names |
| `maxBytes` | `32768` | Per-injection render budget (UTF-8 bytes); `<= 0` disables the plugin |
| `maxSourceBytes` | `1048576` | Per-rule source size cap; larger files are skipped |
| `maxTouchedPaths` | `512` | Touched-path cap per session (FIFO eviction) |
## Discoverability
This plugin is discoverable through the GitHub [`dsh-plugin`](https://github.com/topics/dsh-plugin) topic — the channel recommended by the [DeepSeek Harness README](https://github.com/deepseek-ai/deepseek-harness) ("Community and support": *Add the `dsh-plugin` topic to your plugin repository for discoverability*). Community plugin lists and marketplaces (e.g. awesome-dsh-plugin, dsh-plugin-marketplace) scan that topic to pick up new plugins; the tag can be viewed/edited in the repository's About section.
## Development
```powershell
pnpm install
pnpm run check # typecheck + build (tsc)
pnpm test # node --test: parsing / glob matching / precedence / budget / determinism / fs fallback
```
Layout:
- `src/index.ts` — plugin entry (`name` / `Config` / `apply`): `fs/observed` touch tracking, `agent/pre-step` injection, `agent/disposed` cleanup, resume seeding from `session.snapshotEvents()`.
- `src/rules.ts` — pure logic: frontmatter and `# Path:` parsing, glob compilation/matching, precedence merging, budget rendering.
- `src/fs.ts` — versioned discovery/reads: harness `fs` service first, Node fallback.
- `test/rules.test.mjs`, `test/apply.test.mjs` — unit + apply-level tests (run against the compiled `lib/`).
- `examples/.dsh/rules/` — sample rules (copy into your project to get started).
- `fixtures/demo-project/` — a ready-made project for trying the plugin out.
## License
[MIT](LICENSE) — includes attribution to the original [dsh-rules](https://github.com/rj-jiangyichen/dsh-rules) this project ports.
Install
dsh plugin --profile web add github:TURIING/dsh-glob-rules
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-glob-rules from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.