pkm-mcp-server 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +11 -0
- package/.claude-plugin/plugin.json +15 -0
- package/.mcp.json +10 -0
- package/CHANGELOG.md +37 -18
- package/README.md +103 -72
- package/cli.js +10 -2
- package/commands/setup.md +50 -0
- package/hooks/README.md +4 -4
- package/hooks/capture-handler.sh +1 -1
- package/hooks/hooks.json +35 -0
- package/hooks/stop-sweep.js +6 -2
- package/index.js +1 -1
- package/init.js +5 -5
- package/package.json +14 -8
- package/skills/.gitkeep +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "obsidian-pkm-marketplace",
|
|
3
|
+
"description": "Obsidian PKM Plugin for Claude Code",
|
|
4
|
+
"plugins": [
|
|
5
|
+
{
|
|
6
|
+
"name": "obsidian-pkm",
|
|
7
|
+
"description": "Bidirectional knowledge flow between Claude Code and Obsidian — tools, skills, and hooks for PKM",
|
|
8
|
+
"source": "."
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "obsidian-pkm",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Bidirectional knowledge flow between Claude Code and Obsidian — tools, skills, and hooks for PKM",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Adrian Verhoosel"
|
|
7
|
+
},
|
|
8
|
+
"repository": "https://github.com/AdrianV101/obsidian-pkm-plugin",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"keywords": ["obsidian", "pkm", "knowledge-management", "mcp", "claude-code"],
|
|
11
|
+
"mcpServers": "./.mcp.json",
|
|
12
|
+
"hooks": "./hooks/hooks.json",
|
|
13
|
+
"commands": ["./commands"],
|
|
14
|
+
"skills": ["./skills"]
|
|
15
|
+
}
|
package/.mcp.json
ADDED
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [2.0.0] - 2026-03-24
|
|
10
|
+
|
|
11
|
+
### Breaking Changes
|
|
12
|
+
- **Package renamed**: `pkm-mcp-server` → `obsidian-pkm`
|
|
13
|
+
- **CLI binary renamed**: `pkm-mcp-server` → `obsidian-pkm`
|
|
14
|
+
- **GitHub repo renamed**: `Obsidian-MCP` → `obsidian-pkm-plugin`
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- Claude Code plugin structure (`.claude-plugin/plugin.json`)
|
|
18
|
+
- Declarative hook registration (`hooks/hooks.json`) — no more manual hook copying
|
|
19
|
+
- `/obsidian-pkm:setup` slash command for guided configuration
|
|
20
|
+
- Self-hosted marketplace for `claude plugin install` support
|
|
21
|
+
- `.mcp.json` for plugin-managed MCP server
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- Version jump from 1.6.x to 2.0.0 reflects the structural migration to a full plugin
|
|
25
|
+
- Init wizard simplified for npm fallback path
|
|
26
|
+
|
|
9
27
|
## [1.6.0] - 2026-03-23
|
|
10
28
|
|
|
11
29
|
### Security
|
|
@@ -193,21 +211,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
193
211
|
- Atomic file creation in `vault_write` (`wx` flag) prevents race conditions
|
|
194
212
|
- Error messages sanitized to prevent leaking absolute vault paths
|
|
195
213
|
|
|
196
|
-
[Unreleased]: https://github.com/AdrianV101/
|
|
197
|
-
[
|
|
198
|
-
[1.
|
|
199
|
-
[1.5.
|
|
200
|
-
[1.5.
|
|
201
|
-
[1.5.
|
|
202
|
-
[1.
|
|
203
|
-
[1.4.
|
|
204
|
-
[1.4.
|
|
205
|
-
[1.
|
|
206
|
-
[1.3.
|
|
207
|
-
[1.3.
|
|
208
|
-
[1.3.
|
|
209
|
-
[1.
|
|
210
|
-
[1.2.
|
|
211
|
-
[1.
|
|
212
|
-
[1.1.
|
|
213
|
-
[1.
|
|
214
|
+
[Unreleased]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v2.0.0...HEAD
|
|
215
|
+
[2.0.0]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.6.0...v2.0.0
|
|
216
|
+
[1.6.0]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.5.3...v1.6.0
|
|
217
|
+
[1.5.3]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.5.2...v1.5.3
|
|
218
|
+
[1.5.2]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.5.1...v1.5.2
|
|
219
|
+
[1.5.1]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.5.0...v1.5.1
|
|
220
|
+
[1.5.0]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.4.2...v1.5.0
|
|
221
|
+
[1.4.2]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.4.1...v1.4.2
|
|
222
|
+
[1.4.1]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.4.0...v1.4.1
|
|
223
|
+
[1.4.0]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.3.3...v1.4.0
|
|
224
|
+
[1.3.3]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.3.2...v1.3.3
|
|
225
|
+
[1.3.2]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.3.1...v1.3.2
|
|
226
|
+
[1.3.1]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.3.0...v1.3.1
|
|
227
|
+
[1.3.0]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.2.1...v1.3.0
|
|
228
|
+
[1.2.1]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.2.0...v1.2.1
|
|
229
|
+
[1.2.0]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.1.1...v1.2.0
|
|
230
|
+
[1.1.1]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.1.0...v1.1.1
|
|
231
|
+
[1.1.0]: https://github.com/AdrianV101/obsidian-pkm-plugin/compare/v1.0.0...v1.1.0
|
|
232
|
+
[1.0.0]: https://github.com/AdrianV101/obsidian-pkm-plugin/releases/tag/v1.0.0
|
package/README.md
CHANGED
|
@@ -1,75 +1,76 @@
|
|
|
1
|
-
# Obsidian PKM
|
|
1
|
+
# Obsidian PKM Plugin
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/obsidian-pkm)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
|
-
[](https://github.com/AdrianV101/obsidian-pkm-plugin/actions/workflows/ci.yml)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
A Claude Code plugin that turns your Obsidian vault into persistent, structured memory for AI coding assistants. Provides 19 MCP tools for note creation, semantic search, graph traversal, metadata queries, session memory, and passive knowledge capture — plus hooks and skills for seamless workflow integration. Published on npm as [`obsidian-pkm`](https://www.npmjs.com/package/obsidian-pkm).
|
|
9
9
|
|
|
10
10
|
## Why
|
|
11
11
|
|
|
12
|
-
Claude Code
|
|
12
|
+
Claude Code has built-in memory, but it's flat text files scoped to individual projects — no structure, no search beyond exact matches, no connections between notes, and no way to query across projects. As knowledge grows, it doesn't scale. This server replaces that with a proper PKM layer: structured notes with enforced metadata, semantic search, a navigable knowledge graph, and cross-project access through a single Obsidian vault.
|
|
13
13
|
|
|
14
|
-
- **
|
|
15
|
-
- **Structured knowledge**
|
|
16
|
-
- **Semantic
|
|
17
|
-
- **Graph
|
|
14
|
+
- **Structured session memory** — Every tool call is logged with timestamps and session IDs, so Claude can recall exactly what was read, written, and searched in previous conversations — not just what was saved to a text file.
|
|
15
|
+
- **Structured knowledge creation** — ADRs, research notes, devlogs, and tasks are created from enforced templates with validated frontmatter — not freeform text dumps. Your vault stays consistent and queryable.
|
|
16
|
+
- **Semantic discovery** — "Find my notes about caching strategies" works even if you never used the word "caching." Conceptual search surfaces relevant knowledge that keyword search misses.
|
|
17
|
+
- **Graph-aware connections** — Claude explores your knowledge graph by following wikilinks, discovering related notes by proximity rather than just content. Link suggestions help weave new notes into your existing web of knowledge.
|
|
18
|
+
- **Passive capture** — Decisions, tasks, and research findings are captured in the background without interrupting your coding flow. A session-end sweep catches anything that slipped through.
|
|
18
19
|
|
|
19
|
-
Without this,
|
|
20
|
+
Without this, knowledge stays fragmented across per-project memory files and chat logs. With it, your AI assistant maintains a unified knowledge base that compounds over time.
|
|
20
21
|
|
|
21
22
|
https://github.com/user-attachments/assets/58ad9c9b-d987-4728-89e7-33de20b73a38
|
|
22
23
|
|
|
23
24
|
## Features
|
|
24
25
|
|
|
26
|
+
### Knowledge Creation & Editing
|
|
27
|
+
|
|
25
28
|
| Tool | Description |
|
|
26
29
|
|------|-------------|
|
|
27
|
-
| `
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
32
|
-
| `vault_search` | Full-text search across markdown files |
|
|
33
|
-
| `vault_semantic_search` | Semantic similarity search via OpenAI embeddings |
|
|
34
|
-
| `vault_suggest_links` | Suggest relevant notes to link based on content similarity |
|
|
35
|
-
| `vault_list` | List files and folders |
|
|
36
|
-
| `vault_recent` | Recently modified files |
|
|
37
|
-
| `vault_links` | Wikilink analysis (incoming/outgoing) |
|
|
38
|
-
| `vault_neighborhood` | Graph exploration via BFS wikilink traversal |
|
|
39
|
-
| `vault_query` | Query notes by YAML frontmatter (type, status, tags/tags_any, dates, custom fields, sorting) |
|
|
40
|
-
| `vault_tags` | Discover tags with counts; folder scoping, glob filters, inline tag parsing |
|
|
41
|
-
| `vault_activity` | Session activity log for cross-conversation memory |
|
|
42
|
-
| `vault_trash` | Soft-delete to `.trash/` (Obsidian convention), warns about broken incoming links |
|
|
43
|
-
| `vault_move` | Move/rename files with automatic wikilink updating across vault |
|
|
44
|
-
| `vault_update_frontmatter` | Atomic YAML frontmatter updates (set, create, remove fields; validates enum fields by note type) |
|
|
45
|
-
| `vault_capture` | Signal a PKM-worthy capture (decision, task, research, bug); returns immediately, background hook creates the note |
|
|
30
|
+
| `vault_write` | Create notes from templates with enforced frontmatter (ADRs, research, devlogs, tasks, etc.) |
|
|
31
|
+
| `vault_append` | Add content to notes, with positional insert (after/before heading, end of section) |
|
|
32
|
+
| `vault_edit` | Surgical string replacement for precise edits |
|
|
33
|
+
| `vault_update_frontmatter` | Atomic YAML frontmatter updates (set, create, remove fields; validates enums by note type) |
|
|
34
|
+
| `vault_capture` | Signal a PKM-worthy capture (decision, task, research, bug); background hook creates the note |
|
|
46
35
|
|
|
47
|
-
###
|
|
36
|
+
### Discovery & Search
|
|
48
37
|
|
|
49
|
-
|
|
38
|
+
| Tool | Description |
|
|
39
|
+
|------|-------------|
|
|
40
|
+
| `vault_search` | Full-text keyword search across markdown files |
|
|
41
|
+
| `vault_semantic_search` | Conceptual similarity search via OpenAI embeddings — finds related notes even with different wording |
|
|
42
|
+
| `vault_query` | Query by YAML frontmatter (type, status, tags, dates, custom fields) with sorting |
|
|
43
|
+
| `vault_tags` | Discover all tags with per-note counts; folder scoping, glob filters, inline tag parsing |
|
|
44
|
+
| `vault_suggest_links` | Suggest relevant notes to link based on content similarity |
|
|
50
45
|
|
|
51
|
-
|
|
52
|
-
vault_read({ path: "devlog" })
|
|
53
|
-
// Resolves to: 01-Projects/Obsidian-MCP/development/devlog.md
|
|
46
|
+
### Graph & Connections
|
|
54
47
|
|
|
55
|
-
|
|
56
|
-
|
|
48
|
+
| Tool | Description |
|
|
49
|
+
|------|-------------|
|
|
50
|
+
| `vault_links` | Wikilink analysis (incoming and outgoing links for a note) |
|
|
51
|
+
| `vault_neighborhood` | Graph exploration via BFS wikilink traversal — discover related notes by proximity |
|
|
57
52
|
|
|
58
|
-
|
|
59
|
-
// Works on vault_peek, vault_links, vault_neighborhood, vault_suggest_links too
|
|
60
|
-
```
|
|
53
|
+
### Reading & Navigation
|
|
61
54
|
|
|
62
|
-
|
|
55
|
+
| Tool | Description |
|
|
56
|
+
|------|-------------|
|
|
57
|
+
| `vault_read` | Read note contents (pagination by heading, tail, chunk, line range; auto-redirects large files) |
|
|
58
|
+
| `vault_peek` | Inspect file metadata and structure without reading full content |
|
|
59
|
+
| `vault_list` | List files and folders |
|
|
60
|
+
| `vault_recent` | Recently modified files |
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
vault_search({ query: "API design", folder: "Obsidian-MCP" })
|
|
66
|
-
// Resolves folder to: 01-Projects/Obsidian-MCP
|
|
62
|
+
### Organization & Maintenance
|
|
67
63
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
| Tool | Description |
|
|
65
|
+
|------|-------------|
|
|
66
|
+
| `vault_move` | Move/rename files with automatic wikilink updating across the vault |
|
|
67
|
+
| `vault_trash` | Soft-delete to `.trash/` (Obsidian convention), warns about broken incoming links |
|
|
71
68
|
|
|
72
|
-
|
|
69
|
+
### Session Memory
|
|
70
|
+
|
|
71
|
+
| Tool | Description |
|
|
72
|
+
|------|-------------|
|
|
73
|
+
| `vault_activity` | Cross-conversation memory — logs every tool call with timestamps and session IDs |
|
|
73
74
|
|
|
74
75
|
## Prerequisites
|
|
75
76
|
|
|
@@ -84,14 +85,32 @@ Ambiguous matches return an error listing candidates. Exact paths always work un
|
|
|
84
85
|
|
|
85
86
|
### 1. Install and Set Up
|
|
86
87
|
|
|
87
|
-
**
|
|
88
|
+
**Via Claude Code plugin marketplace** (recommended):
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
claude plugin marketplace add AdrianV101/obsidian-pkm-plugin
|
|
92
|
+
claude plugin install obsidian-pkm
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Then run the setup skill in Claude Code:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
/obsidian-pkm:setup
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The setup skill walks you through vault path, templates, folder structure, semantic search, and Claude Code registration.
|
|
102
|
+
|
|
103
|
+
**Via npm** (fallback):
|
|
88
104
|
|
|
89
105
|
```bash
|
|
90
|
-
npm install -g pkm
|
|
91
|
-
pkm
|
|
106
|
+
npm install -g obsidian-pkm
|
|
107
|
+
obsidian-pkm init
|
|
92
108
|
```
|
|
93
109
|
|
|
94
|
-
The setup wizard walks you through
|
|
110
|
+
The setup wizard walks you through vault path, templates, folder structure, semantic search, and Claude Code registration. Nothing is written until you confirm each step, and you can press Ctrl+C at any time to cancel.
|
|
111
|
+
|
|
112
|
+
<details>
|
|
113
|
+
<summary>Wizard step details</summary>
|
|
95
114
|
|
|
96
115
|
**Step 1 — Vault path.** Point to an existing Obsidian vault or create a new one. The wizard resolves `~`, `$HOME`, and relative paths automatically. Safety checks prevent using system directories (`/`, `/home`, etc.) as a vault. For existing non-empty directories you can use it as-is, create a subfolder inside it, or wipe it (with triple confirmation). You'll be offered an optional backup before any changes — this creates a timestamped copy next to the vault (e.g. `PKM-backup-2026-03-21T14-30-00/`).
|
|
97
116
|
|
|
@@ -116,29 +135,31 @@ Existing templates are never overwritten.
|
|
|
116
135
|
|
|
117
136
|
Each `_index.md` has `type: moc` frontmatter. Existing folders and index files are skipped.
|
|
118
137
|
|
|
119
|
-
**Step 4 — OpenAI API key (optional).** Enables `vault_semantic_search` and `vault_suggest_links`. The key is stored only in your Claude Code configuration (`~/.claude.json`) and is used solely for generating text embeddings. You can add this later — see [Enable Semantic Search](#
|
|
138
|
+
**Step 4 — OpenAI API key (optional).** Enables `vault_semantic_search` and `vault_suggest_links`. The key is stored only in your Claude Code configuration (`~/.claude.json`) and is used solely for generating text embeddings. You can add this later — see [Enable Semantic Search](#4-enable-semantic-search-optional).
|
|
120
139
|
|
|
121
140
|
**Step 5 — Claude Code registration.** Registers the MCP server via `claude mcp add -s user`. If `obsidian-pkm` is already registered, you'll be asked whether to overwrite. The exact command is shown for confirmation before running. If the `claude` CLI is not found on PATH, the wizard prints the manual registration command instead.
|
|
122
141
|
|
|
142
|
+
</details>
|
|
143
|
+
|
|
123
144
|
Restart Claude Code after setup. The server provides all tools except semantic search out of the box.
|
|
124
145
|
|
|
125
146
|
**From source:**
|
|
126
147
|
|
|
127
148
|
```bash
|
|
128
|
-
git clone https://github.com/AdrianV101/
|
|
129
|
-
cd
|
|
149
|
+
git clone https://github.com/AdrianV101/obsidian-pkm-plugin.git
|
|
150
|
+
cd obsidian-pkm-plugin
|
|
130
151
|
npm install
|
|
131
152
|
node cli.js init
|
|
132
153
|
```
|
|
133
154
|
|
|
134
|
-
You can also run the wizard without a global install: `npx pkm
|
|
155
|
+
You can also run the wizard without a global install: `npx obsidian-pkm init`.
|
|
135
156
|
|
|
136
157
|
### 2. Manual Registration (alternative)
|
|
137
158
|
|
|
138
159
|
If you prefer to skip the wizard, register directly with the Claude CLI:
|
|
139
160
|
|
|
140
161
|
```bash
|
|
141
|
-
claude mcp add -s user -e VAULT_PATH=/absolute/path/to/your/vault -- obsidian-pkm npx -y pkm
|
|
162
|
+
claude mcp add -s user -e VAULT_PATH=/absolute/path/to/your/vault -- obsidian-pkm npx -y obsidian-pkm@latest
|
|
142
163
|
```
|
|
143
164
|
|
|
144
165
|
For a source install:
|
|
@@ -149,7 +170,15 @@ claude mcp add -s user -e VAULT_PATH=/absolute/path/to/your/vault -- obsidian-pk
|
|
|
149
170
|
|
|
150
171
|
Verify with `claude mcp list` — you should see `obsidian-pkm: ... - Connected`.
|
|
151
172
|
|
|
152
|
-
### 3.
|
|
173
|
+
### 3. Verify It Works
|
|
174
|
+
|
|
175
|
+
Open Claude Code and try:
|
|
176
|
+
|
|
177
|
+
> List the folders in my vault
|
|
178
|
+
|
|
179
|
+
Claude should call `vault_list` and show your vault's directory structure. If it works, the server is connected and ready.
|
|
180
|
+
|
|
181
|
+
### 4. Enable Semantic Search (optional)
|
|
153
182
|
|
|
154
183
|
If you didn't set this up during `init`, add your OpenAI API key by re-registering:
|
|
155
184
|
|
|
@@ -158,12 +187,12 @@ claude mcp remove obsidian-pkm
|
|
|
158
187
|
claude mcp add -s user \
|
|
159
188
|
-e VAULT_PATH=/absolute/path/to/your/vault \
|
|
160
189
|
-e OPENAI_API_KEY=sk-... \
|
|
161
|
-
-- obsidian-pkm npx -y pkm
|
|
190
|
+
-- obsidian-pkm npx -y obsidian-pkm@latest
|
|
162
191
|
```
|
|
163
192
|
|
|
164
193
|
This enables `vault_semantic_search` and `vault_suggest_links`. Uses `text-embedding-3-large` with a SQLite + sqlite-vec index stored at `.obsidian/semantic-index.db`. The index rebuilds automatically — delete the DB file to force a full re-embed.
|
|
165
194
|
|
|
166
|
-
###
|
|
195
|
+
### 5. Enable PKM Hooks (optional)
|
|
167
196
|
|
|
168
197
|
The hook system adds automatic context loading at session start and passive knowledge capture during coding. Requires the [Claude CLI](https://docs.anthropic.com/en/docs/claude-cli) installed and authenticated.
|
|
169
198
|
|
|
@@ -178,7 +207,7 @@ Add to your `~/.claude/settings.json` (alongside the `mcpServers` block):
|
|
|
178
207
|
"hooks": [
|
|
179
208
|
{
|
|
180
209
|
"type": "command",
|
|
181
|
-
"command": "VAULT_PATH=\"/path/to/your/vault\" node /path/to/
|
|
210
|
+
"command": "VAULT_PATH=\"/path/to/your/vault\" node /path/to/obsidian-pkm-plugin/hooks/session-start.js",
|
|
182
211
|
"timeout": 15,
|
|
183
212
|
"statusMessage": "Loading PKM project context..."
|
|
184
213
|
}
|
|
@@ -190,7 +219,7 @@ Add to your `~/.claude/settings.json` (alongside the `mcpServers` block):
|
|
|
190
219
|
"hooks": [
|
|
191
220
|
{
|
|
192
221
|
"type": "command",
|
|
193
|
-
"command": "VAULT_PATH=\"/path/to/your/vault\" node /path/to/
|
|
222
|
+
"command": "VAULT_PATH=\"/path/to/your/vault\" node /path/to/obsidian-pkm-plugin/hooks/stop-sweep.js",
|
|
194
223
|
"async": true,
|
|
195
224
|
"timeout": 10
|
|
196
225
|
}
|
|
@@ -203,7 +232,7 @@ Add to your `~/.claude/settings.json` (alongside the `mcpServers` block):
|
|
|
203
232
|
"hooks": [
|
|
204
233
|
{
|
|
205
234
|
"type": "command",
|
|
206
|
-
"command": "VAULT_PATH=\"/path/to/your/vault\" /path/to/
|
|
235
|
+
"command": "VAULT_PATH=\"/path/to/your/vault\" /path/to/obsidian-pkm-plugin/hooks/capture-handler.sh",
|
|
207
236
|
"async": true,
|
|
208
237
|
"timeout": 10
|
|
209
238
|
}
|
|
@@ -214,7 +243,7 @@ Add to your `~/.claude/settings.json` (alongside the `mcpServers` block):
|
|
|
214
243
|
}
|
|
215
244
|
```
|
|
216
245
|
|
|
217
|
-
Replace `/path/to/your/vault` with your Obsidian vault path and `/path/to/
|
|
246
|
+
Replace `/path/to/your/vault` with your Obsidian vault path and `/path/to/obsidian-pkm-plugin` with the path to this repo (or the global npm install location).
|
|
218
247
|
|
|
219
248
|
| Hook | Event | What it does |
|
|
220
249
|
|------|-------|--------------|
|
|
@@ -246,7 +275,7 @@ Vault/
|
|
|
246
275
|
|
|
247
276
|
### Templates
|
|
248
277
|
|
|
249
|
-
`vault_write` loads all `.md` files from `05-Templates/` at startup and enforces frontmatter on every note created. The setup wizard (`pkm
|
|
278
|
+
`vault_write` loads all `.md` files from `05-Templates/` at startup and enforces frontmatter on every note created. The setup wizard (`obsidian-pkm init`) installs these automatically — or you can copy the files from `templates/` manually.
|
|
250
279
|
|
|
251
280
|
13 included templates: `adr`, `daily-note`, `devlog`, `fleeting-note`, `literature-note`, `meeting-notes`, `moc`, `note`, `permanent-note`, `project-index`, `research-note`, `task`, `troubleshooting-log`. Add your own templates to `05-Templates/` and they become available to `vault_write` automatically.
|
|
252
281
|
|
|
@@ -288,15 +317,17 @@ All paths passed to tools are relative to vault root. The server includes path s
|
|
|
288
317
|
|
|
289
318
|
## How It Works
|
|
290
319
|
|
|
291
|
-
**
|
|
320
|
+
**Knowledge creation** is template-based. `vault_write` loads templates from `05-Templates/`, substitutes Templater-compatible variables (`<% tp.date.now("YYYY-MM-DD") %>`, `<% tp.file.title %>`), and validates required frontmatter fields (`type`, `created`, `tags`). This ensures every note in your vault has consistent metadata — making it queryable, sortable, and discoverable from day one. Task notes enforce enum validation on `status` and `priority`; other types accept `project`, `deciders`, `due`, and `source`.
|
|
321
|
+
|
|
322
|
+
**Knowledge discovery** works at two levels. Keyword search (`vault_search`) finds exact terms. Semantic search embeds notes using OpenAI and finds conceptually related content — so "managing overwhelm" surfaces notes about "cognitive load" even if those exact words never appear together. The semantic index watches for file changes in real-time and syncs across machines via Obsidian Sync.
|
|
292
323
|
|
|
293
|
-
**
|
|
324
|
+
**Knowledge connections** are maintained through Obsidian's `[[wikilink]]` graph. `vault_neighborhood` traverses links via BFS to discover related notes by proximity, while `vault_suggest_links` recommends connections you haven't made yet. `vault_move` rewrites wikilinks across the vault when you reorganize, and `vault_trash` warns about links that would break.
|
|
294
325
|
|
|
295
|
-
**
|
|
326
|
+
**Session memory** records every tool call with timestamps and session IDs, so Claude can recall what was read, written, or searched in previous conversations. This turns ephemeral chat sessions into a continuous thread of work.
|
|
296
327
|
|
|
297
|
-
**
|
|
328
|
+
**Passive capture** uses `vault_capture` to signal that something is worth persisting (a decision, task, research finding, or bug). The tool returns immediately — a PostToolUse hook spawns a background agent that creates the structured vault note. Combined with the Stop hook (which sweeps each session for un-captured knowledge), this keeps your vault up to date without interrupting the coding flow.
|
|
298
329
|
|
|
299
|
-
**
|
|
330
|
+
**Fuzzy path resolution** lets read-only tools accept short names instead of full vault paths. `vault_read({ path: "devlog" })` resolves to `01-Projects/MyApp/development/devlog.md` automatically (`.md` extension optional). Folder-scoped tools like `vault_search` and `vault_query` accept partial folder names — `folder: "MyApp"` resolves to `01-Projects/MyApp`. Ambiguous matches return an error listing candidates. Write/destructive tools always require exact paths.
|
|
300
331
|
|
|
301
332
|
## Troubleshooting
|
|
302
333
|
|
|
@@ -304,13 +335,13 @@ All paths passed to tools are relative to vault root. The server includes path s
|
|
|
304
335
|
You need C++ build tools. See [Prerequisites](#prerequisites) for your platform. On Linux, `sudo apt install build-essential python3` usually fixes it.
|
|
305
336
|
|
|
306
337
|
**Server starts but all tool calls fail with ENOENT**
|
|
307
|
-
Your `VAULT_PATH` is wrong or missing. The server validates this at startup and exits with a clear error. Re-register with the correct path: `claude mcp remove obsidian-pkm && claude mcp add -s user -e VAULT_PATH=/correct/path -- obsidian-pkm npx -y pkm
|
|
338
|
+
Your `VAULT_PATH` is wrong or missing. The server validates this at startup and exits with a clear error. Re-register with the correct path: `claude mcp remove obsidian-pkm && claude mcp add -s user -e VAULT_PATH=/correct/path -- obsidian-pkm npx -y obsidian-pkm@latest`
|
|
308
339
|
|
|
309
340
|
**`vault_write` says "no templates available"**
|
|
310
|
-
Run `pkm
|
|
341
|
+
Run `obsidian-pkm init` to install templates, or copy the `templates/` files from this repo into your vault's `05-Templates/` directory. The server loads templates from there at startup.
|
|
311
342
|
|
|
312
343
|
**Semantic search not appearing in tool list**
|
|
313
|
-
Set `OPENAI_API_KEY` in your MCP server registration. See [Enable Semantic Search](#
|
|
344
|
+
Set `OPENAI_API_KEY` in your MCP server registration. See [Enable Semantic Search](#4-enable-semantic-search-optional). Without it, `vault_semantic_search` and `vault_suggest_links` are hidden entirely.
|
|
314
345
|
|
|
315
346
|
**Server not showing up in Claude Code after install**
|
|
316
347
|
Run `claude mcp list` to check. If `obsidian-pkm` is missing, register it with `claude mcp add` (see [Manual Registration](#2-manual-registration-alternative)). Note: editing `~/.claude/settings.json` directly does **not** register MCP servers — use the CLI.
|
package/cli.js
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
import { createRequire } from "module";
|
|
4
4
|
|
|
5
|
+
console.warn("");
|
|
6
|
+
console.warn(" pkm-mcp-server has been renamed to obsidian-pkm.");
|
|
7
|
+
console.warn(" Install the new version:");
|
|
8
|
+
console.warn(" Marketplace: claude plugin marketplace add AdrianV101/obsidian-pkm-plugin");
|
|
9
|
+
console.warn(" npm: npm install -g obsidian-pkm");
|
|
10
|
+
console.warn(" Then uninstall the old package: npm uninstall -g pkm-mcp-server");
|
|
11
|
+
console.warn("");
|
|
12
|
+
|
|
5
13
|
const subcommand = process.argv[2];
|
|
6
14
|
|
|
7
15
|
try {
|
|
@@ -11,13 +19,13 @@ try {
|
|
|
11
19
|
} else if (subcommand === "--version" || subcommand === "-v") {
|
|
12
20
|
const require = createRequire(import.meta.url);
|
|
13
21
|
const { version } = require("./package.json");
|
|
14
|
-
console.log(`pkm
|
|
22
|
+
console.log(`obsidian-pkm v${version}`);
|
|
15
23
|
} else if (!subcommand) {
|
|
16
24
|
const { startServer } = await import("./index.js");
|
|
17
25
|
await startServer();
|
|
18
26
|
} else {
|
|
19
27
|
console.error(`Unknown command: ${subcommand}`);
|
|
20
|
-
console.error("Usage: pkm
|
|
28
|
+
console.error("Usage: obsidian-pkm [init]");
|
|
21
29
|
process.exit(1);
|
|
22
30
|
}
|
|
23
31
|
} catch (e) {
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: setup
|
|
3
|
+
description: Configure Obsidian PKM plugin — set vault path, API keys, and verify setup
|
|
4
|
+
allowed-tools: [Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Obsidian PKM Setup
|
|
8
|
+
|
|
9
|
+
You are configuring the Obsidian PKM plugin. Walk the user through these steps:
|
|
10
|
+
|
|
11
|
+
## Step 1: Vault Path
|
|
12
|
+
|
|
13
|
+
Ask the user for their Obsidian vault path. Validate that:
|
|
14
|
+
- The path exists and is a directory
|
|
15
|
+
- It contains at least one `.md` file
|
|
16
|
+
- Suggest `~/Documents/PKM` as a default
|
|
17
|
+
|
|
18
|
+
If the path is valid, instruct the user to add `export VAULT_PATH="/absolute/path/to/vault"` to their shell profile (`~/.zshrc` or `~/.bashrc`) if not already set. Verify with `echo $VAULT_PATH`.
|
|
19
|
+
|
|
20
|
+
## Step 2: OpenAI API Key (Optional)
|
|
21
|
+
|
|
22
|
+
Ask if they want semantic search features (vault_semantic_search, vault_suggest_links). If yes:
|
|
23
|
+
- Ask for their OpenAI API key
|
|
24
|
+
- Instruct them to add `export OPENAI_API_KEY="sk-..."` to their shell profile
|
|
25
|
+
- Explain this enables 2 additional tools but is completely optional
|
|
26
|
+
|
|
27
|
+
## Step 3: Verify Setup
|
|
28
|
+
|
|
29
|
+
Run these checks:
|
|
30
|
+
1. `echo $VAULT_PATH` — confirm it's set
|
|
31
|
+
2. Count `.md` files in the vault: `find "$VAULT_PATH" -name "*.md" | wc -l`
|
|
32
|
+
3. Check if templates exist: `ls "$VAULT_PATH/05-Templates/"` — if missing, offer to run `obsidian-pkm init` to scaffold the vault structure
|
|
33
|
+
|
|
34
|
+
## Step 4: Migration Check
|
|
35
|
+
|
|
36
|
+
Check if the old `pkm-mcp-server` is installed:
|
|
37
|
+
1. Run `npm list -g pkm-mcp-server --depth=0 2>/dev/null`
|
|
38
|
+
2. Check for stale hooks: `ls ~/.claude/hooks/pkm/ 2>/dev/null`
|
|
39
|
+
|
|
40
|
+
If found:
|
|
41
|
+
- Suggest: `npm uninstall -g pkm-mcp-server`
|
|
42
|
+
- Suggest removing `~/.claude/hooks/pkm/` directory (hooks are now managed by the plugin)
|
|
43
|
+
- Check `~/.claude/settings.json` for old hook entries and offer to clean them up
|
|
44
|
+
|
|
45
|
+
## Step 5: Done
|
|
46
|
+
|
|
47
|
+
Confirm setup is complete. Tell the user:
|
|
48
|
+
- "Your Obsidian PKM plugin is configured. Try asking me to list your vault folders to verify."
|
|
49
|
+
- If OPENAI_API_KEY was set: "Semantic search will build its index in the background on first use."
|
|
50
|
+
- **Important**: "If you just added environment variables to your shell profile, you'll need to restart your Claude Code session (or run `source ~/.zshrc`) for the MCP server and hooks to pick them up."
|
package/hooks/README.md
CHANGED
|
@@ -39,7 +39,7 @@ Add the following to your `~/.claude/settings.json`:
|
|
|
39
39
|
"hooks": [
|
|
40
40
|
{
|
|
41
41
|
"type": "command",
|
|
42
|
-
"command": "VAULT_PATH=\"/path/to/your/vault\" node /path/to/
|
|
42
|
+
"command": "VAULT_PATH=\"/path/to/your/vault\" node /path/to/obsidian-pkm-plugin/hooks/session-start.js",
|
|
43
43
|
"timeout": 15,
|
|
44
44
|
"statusMessage": "Loading PKM project context..."
|
|
45
45
|
}
|
|
@@ -51,7 +51,7 @@ Add the following to your `~/.claude/settings.json`:
|
|
|
51
51
|
"hooks": [
|
|
52
52
|
{
|
|
53
53
|
"type": "command",
|
|
54
|
-
"command": "VAULT_PATH=\"/path/to/your/vault\" node /path/to/
|
|
54
|
+
"command": "VAULT_PATH=\"/path/to/your/vault\" node /path/to/obsidian-pkm-plugin/hooks/stop-sweep.js",
|
|
55
55
|
"async": true,
|
|
56
56
|
"timeout": 10
|
|
57
57
|
}
|
|
@@ -64,7 +64,7 @@ Add the following to your `~/.claude/settings.json`:
|
|
|
64
64
|
"hooks": [
|
|
65
65
|
{
|
|
66
66
|
"type": "command",
|
|
67
|
-
"command": "VAULT_PATH=\"/path/to/your/vault\" /path/to/
|
|
67
|
+
"command": "VAULT_PATH=\"/path/to/your/vault\" /path/to/obsidian-pkm-plugin/hooks/capture-handler.sh",
|
|
68
68
|
"async": true,
|
|
69
69
|
"timeout": 10
|
|
70
70
|
}
|
|
@@ -75,7 +75,7 @@ Add the following to your `~/.claude/settings.json`:
|
|
|
75
75
|
}
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
Replace `/path/to/your/vault` with the absolute path to your Obsidian vault (e.g., `~/Documents/PKM`), and `/path/to/
|
|
78
|
+
Replace `/path/to/your/vault` with the absolute path to your Obsidian vault (e.g., `~/Documents/PKM`), and `/path/to/obsidian-pkm-plugin` with the absolute path to this repository.
|
|
79
79
|
|
|
80
80
|
## Architecture Notes
|
|
81
81
|
|
package/hooks/capture-handler.sh
CHANGED
|
@@ -50,7 +50,7 @@ MCP_CONFIG=$(node -e "
|
|
|
50
50
|
if (process.env.OPENAI_API_KEY) env.OPENAI_API_KEY = process.env.OPENAI_API_KEY;
|
|
51
51
|
const server = useLocal
|
|
52
52
|
? { command: 'node', args: [localIndex], env }
|
|
53
|
-
: { command: 'npx', args: ['-y', 'pkm
|
|
53
|
+
: { command: 'npx', args: ['-y', 'obsidian-pkm@latest'], env };
|
|
54
54
|
console.log(JSON.stringify({ mcpServers: { 'obsidian-pkm': server } }));
|
|
55
55
|
" "$SCRIPT_DIR" "${VAULT_PATH:-$HOME/Documents/PKM}")
|
|
56
56
|
|
package/hooks/hooks.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"SessionStart": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "startup|clear|compact",
|
|
6
|
+
"hooks": [{
|
|
7
|
+
"type": "command",
|
|
8
|
+
"command": "VAULT_PATH=${VAULT_PATH} node ${CLAUDE_PLUGIN_ROOT}/hooks/session-start.js",
|
|
9
|
+
"timeout": 15
|
|
10
|
+
}]
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"PostToolUse": [
|
|
14
|
+
{
|
|
15
|
+
"matcher": "mcp__obsidian-pkm__vault_capture",
|
|
16
|
+
"hooks": [{
|
|
17
|
+
"type": "command",
|
|
18
|
+
"command": "VAULT_PATH=${VAULT_PATH} bash ${CLAUDE_PLUGIN_ROOT}/hooks/capture-handler.sh",
|
|
19
|
+
"timeout": 30,
|
|
20
|
+
"async": true
|
|
21
|
+
}]
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"Stop": [
|
|
25
|
+
{
|
|
26
|
+
"hooks": [{
|
|
27
|
+
"type": "command",
|
|
28
|
+
"command": "VAULT_PATH=${VAULT_PATH} node ${CLAUDE_PLUGIN_ROOT}/hooks/stop-sweep.js",
|
|
29
|
+
"timeout": 15,
|
|
30
|
+
"async": true
|
|
31
|
+
}]
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}
|
package/hooks/stop-sweep.js
CHANGED
|
@@ -61,7 +61,11 @@ async function main() {
|
|
|
61
61
|
|
|
62
62
|
// Resolve project — no project, no captures
|
|
63
63
|
const { projectPath, error } = await resolveProject(cwd, VAULT_PATH);
|
|
64
|
-
if (error
|
|
64
|
+
if (error) {
|
|
65
|
+
logError(`project resolution failed: ${error}`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (!projectPath) return;
|
|
65
69
|
|
|
66
70
|
// Build MCP config — auto-detect repo (../index.js exists) vs installed (use npx)
|
|
67
71
|
const localIndex = join(__dirname, "..", "index.js");
|
|
@@ -74,7 +78,7 @@ async function main() {
|
|
|
74
78
|
mcpServers: {
|
|
75
79
|
"obsidian-pkm": useLocal
|
|
76
80
|
? { command: "node", args: [localIndex], env: mcpEnv }
|
|
77
|
-
: { command: "npx", args: ["-y", "pkm
|
|
81
|
+
: { command: "npx", args: ["-y", "obsidian-pkm@latest"], env: mcpEnv },
|
|
78
82
|
},
|
|
79
83
|
});
|
|
80
84
|
|
package/index.js
CHANGED
package/init.js
CHANGED
|
@@ -192,7 +192,7 @@ export async function dirSize(dirPath) {
|
|
|
192
192
|
export function detectInstallType(filePath) {
|
|
193
193
|
const thisFile = filePath || fileURLToPath(import.meta.url);
|
|
194
194
|
if (thisFile.includes("node_modules")) {
|
|
195
|
-
return { command: "npx", args: ["-y", "pkm
|
|
195
|
+
return { command: "npx", args: ["-y", "obsidian-pkm@latest"] };
|
|
196
196
|
}
|
|
197
197
|
const cliPath = path.join(path.dirname(thisFile), "cli.js");
|
|
198
198
|
return { command: "node", args: [cliPath] };
|
|
@@ -394,7 +394,7 @@ export async function runInit() {
|
|
|
394
394
|
try {
|
|
395
395
|
// ── Step 1: Welcome ──
|
|
396
396
|
console.log(`
|
|
397
|
-
pkm
|
|
397
|
+
obsidian-pkm setup wizard
|
|
398
398
|
|
|
399
399
|
This will walk you through setting up your Obsidian vault for use with the
|
|
400
400
|
PKM MCP server. You'll be asked about 6 things:
|
|
@@ -508,7 +508,7 @@ Nothing is written until you confirm each step. Press Ctrl+C at any time to canc
|
|
|
508
508
|
|
|
509
509
|
let skipRegistration = false;
|
|
510
510
|
if (hasExisting) {
|
|
511
|
-
const overwrite = await confirmPrompt({ message: "Claude Code is already configured for pkm
|
|
511
|
+
const overwrite = await confirmPrompt({ message: "Claude Code is already configured for obsidian-pkm. Overwrite?", default: false });
|
|
512
512
|
if (!overwrite) {
|
|
513
513
|
console.log(" Registration skipped.\n");
|
|
514
514
|
skipRegistration = true;
|
|
@@ -548,7 +548,7 @@ Nothing is written until you confirm each step. Press Ctrl+C at any time to canc
|
|
|
548
548
|
steps.push("MCP server: skipped (registration failed)");
|
|
549
549
|
}
|
|
550
550
|
} else {
|
|
551
|
-
console.log(" Registration: skipped (you can run `pkm
|
|
551
|
+
console.log(" Registration: skipped (you can run `obsidian-pkm init` again later)");
|
|
552
552
|
steps.push("MCP server: skipped");
|
|
553
553
|
}
|
|
554
554
|
} else {
|
|
@@ -678,7 +678,7 @@ To verify, restart Claude Code and try:
|
|
|
678
678
|
"List the folders in my vault"
|
|
679
679
|
|
|
680
680
|
Claude should call vault_list and show your vault's directory structure.
|
|
681
|
-
If that doesn't work, check: https://github.com/AdrianV101/
|
|
681
|
+
If that doesn't work, check: https://github.com/AdrianV101/obsidian-pkm-plugin#troubleshooting
|
|
682
682
|
`);
|
|
683
683
|
} catch (e) {
|
|
684
684
|
if (e.name === "ExitPromptError") {
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pkm-mcp-server",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.7.0",
|
|
4
|
+
"description": "Claude Code plugin for Obsidian vault integration — 19 MCP tools, hooks, and skills for PKM",
|
|
5
5
|
"main": "cli.js",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./cli.js"
|
|
8
8
|
},
|
|
9
9
|
"bin": {
|
|
10
|
-
"pkm
|
|
10
|
+
"obsidian-pkm": "cli.js"
|
|
11
11
|
},
|
|
12
12
|
"type": "module",
|
|
13
13
|
"engines": {
|
|
@@ -19,7 +19,11 @@
|
|
|
19
19
|
"CHANGELOG.md",
|
|
20
20
|
"hooks/",
|
|
21
21
|
"templates/",
|
|
22
|
-
"sample-project/"
|
|
22
|
+
"sample-project/",
|
|
23
|
+
".claude-plugin/",
|
|
24
|
+
"commands/",
|
|
25
|
+
"skills/",
|
|
26
|
+
".mcp.json"
|
|
23
27
|
],
|
|
24
28
|
"scripts": {
|
|
25
29
|
"start": "node cli.js",
|
|
@@ -29,7 +33,7 @@
|
|
|
29
33
|
},
|
|
30
34
|
"repository": {
|
|
31
35
|
"type": "git",
|
|
32
|
-
"url": "git+https://github.com/AdrianV101/
|
|
36
|
+
"url": "git+https://github.com/AdrianV101/obsidian-pkm-plugin.git"
|
|
33
37
|
},
|
|
34
38
|
"author": "Adrian Verhoosel",
|
|
35
39
|
"license": "MIT",
|
|
@@ -45,11 +49,13 @@
|
|
|
45
49
|
"markdown",
|
|
46
50
|
"notes",
|
|
47
51
|
"semantic-search",
|
|
48
|
-
"wikilinks"
|
|
52
|
+
"wikilinks",
|
|
53
|
+
"plugin",
|
|
54
|
+
"hooks"
|
|
49
55
|
],
|
|
50
|
-
"homepage": "https://github.com/AdrianV101/
|
|
56
|
+
"homepage": "https://github.com/AdrianV101/obsidian-pkm-plugin#readme",
|
|
51
57
|
"bugs": {
|
|
52
|
-
"url": "https://github.com/AdrianV101/
|
|
58
|
+
"url": "https://github.com/AdrianV101/obsidian-pkm-plugin/issues"
|
|
53
59
|
},
|
|
54
60
|
"dependencies": {
|
|
55
61
|
"@inquirer/prompts": "^8.3.2",
|
package/skills/.gitkeep
ADDED
|
File without changes
|