Skip to content
dsh.fish
Bundle

dsh-obsidian-export

DeepSeek Harness (DSH) plugin: export conversations to an Obsidian vault, plus read/search/list/tags/backlinks tools and automatic vault discovery.

Source
xiaomiba0904
stars
2 stars
License
MIT
Updated
Updated 16 hours ago

Readme

# dsh-obsidian-export

DeepSeek Harness (DSH) plugin that integrates with an **Obsidian vault**
(no Obsidian-app dependency — a vault is just a folder of Markdown files),
offering a model-facing toolset: **export** conversations, plus common vault
operations **read / search / list / tags / backlinks**.

## Tools

| tool | purpose |
|---|---|
| `obsidian_export` | export a DSH conversation to the vault as Markdown, with per-session **dedupe / create / skip / update / overwrite** semantics |
| `obsidian_read` | read a note; returns body + parsed frontmatter, first H1 title, `[[wikilink]]` targets, `#tags` |
| `obsidian_search` | search the vault — field `filename` (paths) or `content` (full-text) — and narrow by `tags` |
| `obsidian_list` | list Markdown notes and folders under a vault path (recursive, optional `subpath`) |
| `obsidian_tags` | aggregate distinct `#tags` used across the vault, with note counts |
| `obsidian_backlinks` | find notes that `[[link]]` a given target (for graph traversal) |

## `obsidian_export` — export + dedup

- Reads a session from the persistence seam (`ctx.sessionPersistence`) — current
  session by default, or `sessionId`, or imports an exported
  `session.jsonl` / `session.jsonl.zstd` via `path`.
- Renders a transcript (user / assistant / tool calls) + a `_dashboard.md`
  overview, and refreshes a vault `_index.md`.
- Tracks each session's **content hash** in `<vault>/.dsh-obsidian/manifest.json`,
  so it can tell whether the target exists and whether content changed.

### Export modes (判断"是否重复 / 更新 / 覆盖")

| mode | new session | content changed | content unchanged |
|---|---|---|---|
| `auto` (default) | `create` | `update` (rewrite in place) | `skip` |
| `update` | `create` | `update` | `skip` |
| `overwrite` | `create` | `overwrite` | `overwrite` (force) |
| `skip` | `create` | `skip` | `skip` |
| `dry-run` | `dry-run` | `dry-run` | `dry-run` (report only) |

Returns `{ ok, action, reason, changed, note, sessionId, hash, dir }`
— `action` ∈ `create | skip | update | overwrite | dry-run | error`.

## Source resolution order

1. `path` — import an exported `session.jsonl` / `.jsonl.zstd`.
2. `sessionId` — that persisted session (via `ctx.sessionPersistence.readRaw`/`inspect`).
3. otherwise — the **current** session (`exec.agent.session.id` / `DSH_SESSION_ID`).

## Files

- `src/engine.js` — pure, framework-free export + manifest/dedupe engine (Node ESM).
- `src/obsidian-tools.js` — the vault tools (read / search / list / tags / backlinks) over `ctx.fs`.
- `src/index.js` — the Cordis plugin: `defineTool` wiring for all six tools,
  `ctx.fs` / `ctx.sessionPersistence` use.
- `cordis.patch.yml` — bundle patch that mounts the plugin row.
- `package.json` — declares `"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }`.

## Install into a DSH profile

```sh
# from any directory; relative specs anchor to your invoking directory
dsh plugin --profile web add /absolute/path/to/dsh-obsidian-export
dsh plugin --profile web add ./dsh-obsidian-export      # or file:/link:
```

`dsh plugin` installs the package into the profile's `node_modules`, detects the
`dsh.bundle.patch` declaration, and appends it to `dsh.profile.bundles` in
`~/.dsh/profiles/<name>/package.json`.

> Bundle layers only mount at process boot, so a full restart of the profile is
> required to activate the tool:
> ```sh
> # stop the running instance, then
> dsh --profile web         # or dsh web
> ```
> Watch steps before restarting: confirm composition with
> `dsh --profile web --dump-config` (no restart needed).

The plugin needs its `@deepseek-ai/*` peer packages resolvable. When installed via
pnpm `file:`/`link:` from a directory, provide them in the plugin's own
`node_modules` (e.g. symlink to the DSH install's fallback dir) or rely on the
profile `node_modules` hoisting.

## Model usage

```
obsidian_export(vaultDir="/path/to/vault", mode="auto")                 # current session
obsidian_export(vaultDir="/path/to/vault", path="exported/session.jsonl")
obsidian_export(vaultDir="/path/to/vault", sessionId="session-<id>", mode="dry-run")

obsidian_read(vaultDir="/path/to/vault", path="Inbox/My Note.md")
obsidian_list(vaultDir="/path/to/vault", subpath="Inbox")
obsidian_search(vaultDir="/path/to/vault", query="rag")                 # filename match
obsidian_search(vaultDir="/path/to/vault", query="embedding", field="content")
obsidian_search(vaultDir="/path/to/vault", tags="pkms#research")
obsidian_tags(vaultDir="/path/to/vault")
obsidian_backlinks(vaultDir="/path/to/vault", target="Welcome")
```

Model flow for a common workflow: `obsidian_list` (see what's there) →
`obsidian_read` (load a note) → `obsidian_search` (find related notes by
content/tag) → `obsidian_backlinks` (follow the graph) → `obsidian_export`
(save a conversation). Combine an export with a `dry-run` first to preview
whether a target would be created, skipped, updated, or overwritten.

## License

MIT

Install

dsh plugin --profile web add github:xiaomiba0904/dsh-obsidian-export

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source