dsh-obsidian-bridge
Bidirectional knowledge bridge between DeepSeek Harness and Obsidian Vault — FTS5 search, draft writing, session linking
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 18, 2026
- Updated
- Aug 18, 2026
Introduction
dsh-obsidian-bridge
Bidirectional knowledge bridge between DeepSeek Harness (DSH) and Obsidian Vault.
What It Does
Gives DSH agents direct read/write access to your Obsidian Vault. The agent can search notes via SQLite FTS5 full-text search, read full content by path or wiki-link, write draft notes back to the vault, and create bidirectional links between DSH sessions and notes.
Unlike existing one-way export tools or MCP-based bridges, this plugin runs natively inside the DSH Cordis framework — no external server, no need for Obsidian to be running.
Status: v0.2.0 — Open Source Alpha
Verified Capabilities
| Capability | Status | Test |
|---|---|---|
| Read note by file path | Pass | test/spike.mjs |
| Read note by wiki-link name | Pass | test/spike.mjs |
| Read note with spaces in name | Pass | test/spike.mjs |
| SQLite FTS5 full-text search | Pass | test/phase2-spike.mjs |
| BM25 relevance ranking | Pass | test/phase2-spike.mjs |
| Chinese text search (CJK tokenization) | Pass | test/phase2-spike.mjs |
| Incremental sync (mtime-based) | Pass | test/phase2-spike.mjs |
| 500-note search performance | Pass (34ms) | test/spike.mjs |
| Path traversal protection | Pass | test/spike.mjs |
| Plugin loads in Cordis context | Pass | test/integration.mjs |
| Tool registration via defineTool | Pass | test/integration.mjs |
| Tool execute + render pipeline | Pass | test/integration.mjs |
| System prompt section injection | Pass | test/integration.mjs |
| Write draft note to vault | Pass | test/phase1-spike.mjs |
| Write draft with Unicode title | Pass | test/phase1-spike.mjs |
| Link session to vault note | Pass | test/phase1-spike.mjs |
| Link multiple notes to same session | Pass | test/phase1-spike.mjs |
| Keyword extraction (EN + CN) | Pass | test/phase1-spike.mjs |
| Auto-context hook (agent/pre-step) | Pass | test/phase1-integration.mjs |
| Auto-capture hook (tools/result) | Pass | test/phase1-integration.mjs |
| Auto-capture skips obsidian_* tools | Pass | test/phase1-integration.mjs |
| Zod config schema validation | Pass | test/phase2-spike.mjs |
| Plugin config via cordis.patch.yml | Pass | test/phase2-integration.mjs |
| Env var fallback compatibility | Pass | test/phase2-integration.mjs |
| Plugin disabled without vault path | Pass | test/phase2-integration.mjs |
| Hook disposer cleanup | Pass | test/phase2-integration.mjs |
| Plugin lifecycle cleanup (ctx.effect) | Pass | test/phase2-integration.mjs |
Test Results
Phase 0 Spike: 25 passed, 0 failed
Phase 0 Integration: 49 passed, 0 failed
Phase 1 Spike: 35 passed, 0 failed
Phase 1 Integration: 45 passed, 0 failed
Phase 2 Spike: 35 passed, 0 failed
Phase 2 Integration: 23 passed, 0 failed
Total: 212 passed, 0 failed
Architecture
DSH Agent (Node.js process)
└─ Cordis Framework
└─ dsh-obsidian-bridge plugin (apply(ctx, config))
├─ Config Schema (zod: vaultPath, autoContext, autoCapture, draftFolder, sessionId)
├─ System Prompt: "obsidian-vault-aware" (tools + workflow guide)
├─ Tool: obsidian_search (FTS5 BM25 search across vault notes)
├─ Tool: obsidian_read_note (read full note by path or wiki-link)
├─ Tool: obsidian_write_draft (write draft to dsh-drafts/ folder)
├─ Tool: obsidian_link_session (bidirectional session-note linking)
├─ Hook: agent/pre-step (auto-inject vault context, opt-in)
├─ Hook: tools/result (auto-capture tool results, opt-in)
├─ ctx.effect() cleanup (closes SQLite, disposes tools/hooks)
└─ VaultManager (file system access, caching, wiki-link resolution)
├─ NoteIndex (SQLite FTS5 full-text index)
│ ├─ Incremental sync (mtime-based, throttled)
│ ├─ BM25 relevance ranking
│ ├─ Chinese CJK tokenization
│ └─ .dsh/index.db (WAL mode, 16MB cache)
└─ Obsidian Vault (plain Markdown files on disk)
Single process. No external server. Direct file system access.
Installation
Prerequisites
- Node.js >= 22.19 (or >= 24)
- DSH installed:
npm install -g @deepseek-ai/dsh - An Obsidian Vault directory
Build
cd dsh-obsidian-bridge
npm install
npm run build
Install into DSH
Option A: From GitHub (recommended — no npm account needed)
# Install directly from GitHub
dsh plugin --profile web add github:Daseanle/dsh-obsidian-bridge
# Configure via cordis.patch.yml
dsh web
Option B: From npm (when published)
dsh plugin --profile web add dsh-obsidian-bridge
dsh web
Option C: From local clone
git clone https://github.com/Daseanle/dsh-obsidian-bridge.git
cd dsh-obsidian-bridge && npm install && npm run build
dsh plugin --profile web add file:./dsh-obsidian-bridge
dsh web
Configuration
Create or edit cordis.patch.yml in your DSH config directory:
- id: dsh-obsidian-bridge
config:
vaultPath: /path/to/your/vault
autoContext: false # auto-inject vault context before each model step
autoCapture: false # auto-capture non-Obsidian tool results as drafts
draftFolder: dsh-drafts # folder for draft notes
sessionId: "" # optional: link drafts to a specific session
Or use environment variables (legacy, used as fallback when config values are not provided):
export OBSIDIAN_VAULT_PATH="/path/to/your/vault"
export DSH_OBSIDIAN_AUTO_CONTEXT=true # optional
export DSH_OBSIDIAN_AUTO_CAPTURE=true # optional
export DSH_SESSION_ID="my-session" # optional
Verify
In the DSH agent, ask it to search your vault:
Search my Obsidian vault for notes about "architecture"
Project Structure
dsh-obsidian-bridge/
├── src/
│ ├── index.ts # Plugin entry: apply(ctx, config) with zod schema
│ ├── vault-manager.ts # Core: path resolution, note reading, search, write, link
│ ├── note-index.ts # SQLite FTS5 full-text index with incremental sync
│ ├── hooks.ts # Event hooks: auto-context, auto-capture (returns disposer)
│ └── tools/
│ ├── read-note.ts # obsidian_read_note tool definition
│ ├── search.ts # obsidian_search tool definition
│ ├── write-draft.ts # obsidian_write_draft tool definition
│ └── link-session.ts # obsidian_link_session tool definition
├── dist/ # Compiled JavaScript (tsc output)
├── test/
│ ├── vault/ # Test Obsidian Vault (4 sample notes)
│ ├── spike.mjs # Phase 0 core logic tests (25 tests)
│ ├── integration.mjs # Phase 0 plugin lifecycle tests (49 tests)
│ ├── phase1-spike.mjs # Phase 1 write/link tests (35 tests)
│ ├── phase1-integration.mjs # Phase 1 tools+hooks tests (45 tests)
│ ├── phase2-spike.mjs # Phase 2 FTS5+config tests (35 tests)
│ └── phase2-integration.mjs # Phase 2 config+cleanup tests (23 tests)
├── cordis.patch.yml # Example plugin configuration
├── package.json
├── tsconfig.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
└── .npmignore
Configuration
Config Schema (zod)
| Field | Type | Default | Description |
|---|---|---|---|
vaultPath | string | "" | Absolute path to your Obsidian Vault |
autoContext | boolean | false | Auto-inject vault context before each model step |
autoCapture | boolean | false | Auto-capture non-Obsidian tool results as drafts |
draftFolder | string | "dsh-drafts" | Folder name for draft notes |
sessionId | string | "" | Session ID for draft frontmatter and session linking |
Config is validated via zod Standard Schema V1. Values can be provided through cordis.patch.yml or environment variables (as fallback).
Environment Variables
| Variable | Fallback For | Default |
|---|---|---|
OBSIDIAN_VAULT_PATH | vaultPath | — |
DSH_OBSIDIAN_AUTO_CONTEXT | autoContext | false |
DSH_OBSIDIAN_AUTO_CAPTURE | autoCapture | false |
DSH_SESSION_ID | sessionId | "" |
SQLite FTS5 Index
The plugin creates a .dsh/index.db SQLite database inside your vault directory:
- FTS5 virtual table with
unicode61tokenizer - UNINDEXED columns for metadata (path, frontmatter, mtime, etc.)
- BM25 relevance ranking for search results
- Incremental sync: only re-reads notes whose
mtimechanged - Throttled sync: skips re-sync within 2s of last sync (unless invalidated)
- Chinese support: CJK characters are split for unicode61 tokenization
- WAL mode with 16MB cache for performance
Roadmap
| Phase | Scope | Status |
|---|---|---|
| Phase 0 — Spike | read_note + search, in-memory index, path traversal guard | Complete |
| Phase 1 — Self-use MVP | write_draft + link_session tools, hooks (auto-context, auto-capture) | Complete |
| Phase 2 — Open Source Alpha | SQLite FTS5, cordis.patch.yml config, npm publish, documentation | Complete |
License
MIT