@gmickel/gno 0.10.4 → 0.12.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/README.md +11 -0
- package/assets/skill/SKILL.md +12 -0
- package/assets/skill/mcp-reference.md +29 -188
- package/package.json +1 -1
- package/src/cli/commands/embed.ts +21 -2
- package/src/cli/commands/links.ts +896 -0
- package/src/cli/commands/ref-parser.ts +1 -1
- package/src/cli/commands/vec.ts +287 -0
- package/src/cli/options.ts +6 -0
- package/src/cli/program.ts +192 -0
- package/src/core/job-manager.ts +94 -1
- package/src/core/links.ts +400 -0
- package/src/embed/backlog.ts +144 -0
- package/src/embed/index.ts +11 -0
- package/src/ingestion/position.ts +119 -0
- package/src/ingestion/strip.ts +162 -0
- package/src/ingestion/sync.ts +58 -1
- package/src/mcp/tools/embed.ts +151 -0
- package/src/mcp/tools/index-cmd.ts +219 -0
- package/src/mcp/tools/index.ts +100 -0
- package/src/mcp/tools/job-status.ts +34 -4
- package/src/mcp/tools/links.ts +617 -0
- package/src/mcp/tools/list-jobs.ts +3 -2
- package/src/serve/embed-scheduler.ts +263 -0
- package/src/serve/public/app.tsx +2 -0
- package/src/serve/public/components/BacklinksPanel.tsx +321 -0
- package/src/serve/public/components/OutgoingLinksPanel.tsx +323 -0
- package/src/serve/public/components/RelatedNotesSidebar.tsx +482 -0
- package/src/serve/public/components/WikiLinkAutocomplete.tsx +554 -0
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/pages/DocView.tsx +344 -259
- package/src/serve/public/pages/DocumentEditor.tsx +101 -17
- package/src/serve/routes/api.ts +84 -1
- package/src/serve/routes/links.ts +471 -0
- package/src/serve/server.ts +74 -1
- package/src/store/migrations/004-doc-links.ts +64 -0
- package/src/store/migrations/index.ts +2 -1
- package/src/store/sqlite/adapter.ts +305 -0
- package/src/store/types.ts +109 -0
- package/src/store/vector/sqlite-vec.ts +62 -45
- package/src/store/vector/types.ts +3 -1
package/README.md
CHANGED
|
@@ -27,6 +27,16 @@ GNO is a local knowledge engine for privacy-conscious developers and AI agents.
|
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
+
## What's New in v0.12
|
|
31
|
+
|
|
32
|
+
- **Note Linking**: Wiki-style `[[links]]`, backlinks, and AI-powered related notes
|
|
33
|
+
- **Tag System**: Filter searches by frontmatter tags with `--tags-any`/`--tags-all`
|
|
34
|
+
- **Web UI**: Outgoing links panel, backlinks panel, related notes sidebar
|
|
35
|
+
- **CLI**: `gno links`, `gno backlinks`, `gno similar` commands
|
|
36
|
+
- **MCP**: New tools for AI agents to navigate your knowledge graph
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
30
40
|
## Quick Start
|
|
31
41
|
|
|
32
42
|
```bash
|
|
@@ -315,6 +325,7 @@ graph TD
|
|
|
315
325
|
| **MCP Server** | Works with Claude Desktop, Cursor, Zed, + 8 more |
|
|
316
326
|
| **Collections** | Organize sources with patterns, excludes, contexts |
|
|
317
327
|
| **Tag Filtering** | Frontmatter tags with hierarchical paths, filter via `--tags-any`/`--tags-all` |
|
|
328
|
+
| **Note Linking** | Wiki links, backlinks, related notes, cross-collection navigation |
|
|
318
329
|
| **Multilingual** | 30+ languages, auto-detection, cross-lingual search |
|
|
319
330
|
| **Incremental** | SHA-256 tracking, only changed files re-indexed |
|
|
320
331
|
| **Keyboard First** | ⌘N capture, ⌘K search, ⌘/ shortcuts, ⌘S save |
|
package/assets/skill/SKILL.md
CHANGED
|
@@ -83,6 +83,18 @@ gno search "your query" # BM25 keyword search
|
|
|
83
83
|
--no-pager Disable paging
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
+
## Important: Embedding After Changes
|
|
87
|
+
|
|
88
|
+
If you edit/create files that should be searchable via vector search:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
gno index # Full re-index (sync + embed)
|
|
92
|
+
# or
|
|
93
|
+
gno embed # Embed only (if already synced)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
MCP `gno.sync` and `gno.capture` do NOT auto-embed. Use CLI for embedding.
|
|
97
|
+
|
|
86
98
|
## Reference Documentation
|
|
87
99
|
|
|
88
100
|
| Topic | File |
|
|
@@ -1,8 +1,23 @@
|
|
|
1
|
-
# GNO MCP
|
|
1
|
+
# GNO MCP Installation
|
|
2
2
|
|
|
3
|
-
GNO provides an MCP (Model Context Protocol) server for AI integration.
|
|
3
|
+
GNO provides an MCP (Model Context Protocol) server for AI client integration.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> **Full reference**: See [gno.sh/docs/MCP](https://www.gno.sh/docs/MCP) for complete tool documentation.
|
|
6
|
+
|
|
7
|
+
## Quick Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Claude Desktop (default)
|
|
11
|
+
gno mcp install
|
|
12
|
+
|
|
13
|
+
# Claude Code
|
|
14
|
+
gno mcp install -t claude-code
|
|
15
|
+
|
|
16
|
+
# With write tools enabled
|
|
17
|
+
gno mcp install --enable-write
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Manual Setup
|
|
6
21
|
|
|
7
22
|
### Claude Desktop
|
|
8
23
|
|
|
@@ -19,202 +34,28 @@ Add to `claude_desktop_config.json`:
|
|
|
19
34
|
}
|
|
20
35
|
```
|
|
21
36
|
|
|
22
|
-
Config
|
|
37
|
+
Config locations:
|
|
23
38
|
|
|
24
39
|
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
25
40
|
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
26
41
|
- Linux: `~/.config/Claude/claude_desktop_config.json`
|
|
27
42
|
|
|
28
|
-
###
|
|
43
|
+
### Claude Code
|
|
29
44
|
|
|
30
45
|
```bash
|
|
31
|
-
gno mcp
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Runs JSON-RPC 2.0 over stdio.
|
|
35
|
-
|
|
36
|
-
## Tools
|
|
37
|
-
|
|
38
|
-
### gno.search
|
|
39
|
-
|
|
40
|
-
BM25 keyword search.
|
|
41
|
-
|
|
42
|
-
```json
|
|
43
|
-
{
|
|
44
|
-
"query": "search terms",
|
|
45
|
-
"collection": "optional-collection",
|
|
46
|
-
"limit": 5,
|
|
47
|
-
"minScore": 0.5,
|
|
48
|
-
"lang": "en",
|
|
49
|
-
"tagsAny": ["project", "work"],
|
|
50
|
-
"tagsAll": ["reviewed"]
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
| Parameter | Description |
|
|
55
|
-
| ------------ | ----------------------------------- |
|
|
56
|
-
| `query` | Search query (required) |
|
|
57
|
-
| `collection` | Filter by collection |
|
|
58
|
-
| `limit` | Max results (default: 5) |
|
|
59
|
-
| `minScore` | Minimum score 0-1 |
|
|
60
|
-
| `tagsAny` | Filter: has ANY of these tags (OR) |
|
|
61
|
-
| `tagsAll` | Filter: has ALL of these tags (AND) |
|
|
62
|
-
|
|
63
|
-
### gno.vsearch
|
|
64
|
-
|
|
65
|
-
Vector semantic search. Same parameters as `gno.search`.
|
|
66
|
-
|
|
67
|
-
### gno.query
|
|
68
|
-
|
|
69
|
-
Hybrid search (best quality).
|
|
70
|
-
|
|
71
|
-
```json
|
|
72
|
-
{
|
|
73
|
-
"query": "search terms",
|
|
74
|
-
"collection": "optional-collection",
|
|
75
|
-
"limit": 5
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
**Search modes** (via parameters):
|
|
80
|
-
|
|
81
|
-
| Mode | Parameters | Time |
|
|
82
|
-
| -------- | ---------------- | ----- |
|
|
83
|
-
| Fast | `fast: true` | ~0.7s |
|
|
84
|
-
| Default | (none) | ~2-3s |
|
|
85
|
-
| Thorough | `thorough: true` | ~5-8s |
|
|
86
|
-
|
|
87
|
-
Default skips expansion, with reranking. Use `thorough: true` for best recall.
|
|
88
|
-
|
|
89
|
-
**Agent retry strategy**: Use default mode first. If no relevant results:
|
|
90
|
-
|
|
91
|
-
1. Rephrase the query (free, often effective)
|
|
92
|
-
2. Then try `thorough: true` for better recall
|
|
93
|
-
|
|
94
|
-
### gno.get
|
|
95
|
-
|
|
96
|
-
Retrieve document by reference.
|
|
97
|
-
|
|
98
|
-
```json
|
|
99
|
-
{
|
|
100
|
-
"ref": "gno://collection/path or #docid",
|
|
101
|
-
"fromLine": 1,
|
|
102
|
-
"lineCount": 100,
|
|
103
|
-
"lineNumbers": true
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### gno.multi_get
|
|
108
|
-
|
|
109
|
-
Retrieve multiple documents.
|
|
110
|
-
|
|
111
|
-
```json
|
|
112
|
-
{
|
|
113
|
-
"refs": ["gno://work/doc1.md", "#a1b2c3d4"],
|
|
114
|
-
"maxBytes": 10240,
|
|
115
|
-
"lineNumbers": true
|
|
116
|
-
}
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Or by pattern:
|
|
120
|
-
|
|
121
|
-
```json
|
|
122
|
-
{
|
|
123
|
-
"pattern": "work/**/*.md",
|
|
124
|
-
"maxBytes": 10240
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### gno.status
|
|
129
|
-
|
|
130
|
-
Get index status.
|
|
131
|
-
|
|
132
|
-
```json
|
|
133
|
-
{}
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### gno.list_tags
|
|
137
|
-
|
|
138
|
-
List tags with document counts.
|
|
139
|
-
|
|
140
|
-
```json
|
|
141
|
-
{
|
|
142
|
-
"collection": "optional-collection",
|
|
143
|
-
"prefix": "project/"
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
| Parameter | Description |
|
|
148
|
-
| ------------ | --------------------------------------- |
|
|
149
|
-
| `collection` | Filter by collection |
|
|
150
|
-
| `prefix` | Filter by tag prefix (e.g., `project/`) |
|
|
151
|
-
|
|
152
|
-
### gno.tag
|
|
153
|
-
|
|
154
|
-
Add or remove tag from document.
|
|
155
|
-
|
|
156
|
-
```json
|
|
157
|
-
{
|
|
158
|
-
"ref": "gno://work/readme.md",
|
|
159
|
-
"tag": "project/api",
|
|
160
|
-
"action": "add"
|
|
161
|
-
}
|
|
46
|
+
gno mcp install -t claude-code -s user # User scope
|
|
47
|
+
gno mcp install -t claude-code -s project # Project scope
|
|
162
48
|
```
|
|
163
49
|
|
|
164
|
-
|
|
165
|
-
| --------- | ---------------------------------- |
|
|
166
|
-
| `ref` | Document URI or docid (required) |
|
|
167
|
-
| `tag` | Tag string (required) |
|
|
168
|
-
| `action` | `add` or `remove` (default: `add`) |
|
|
50
|
+
## Check Status
|
|
169
51
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
Documents accessible as MCP resources:
|
|
173
|
-
|
|
174
|
-
```
|
|
175
|
-
gno://{collection}/{path}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
Examples:
|
|
179
|
-
|
|
180
|
-
- `gno://work/contracts/nda.docx`
|
|
181
|
-
- `gno://notes/2025/01/meeting.md`
|
|
182
|
-
|
|
183
|
-
Returns Markdown content with line numbers.
|
|
184
|
-
|
|
185
|
-
## Response Format
|
|
186
|
-
|
|
187
|
-
All tools return:
|
|
188
|
-
|
|
189
|
-
```json
|
|
190
|
-
{
|
|
191
|
-
"content": [
|
|
192
|
-
{ "type": "text", "text": "Human-readable summary" }
|
|
193
|
-
],
|
|
194
|
-
"structuredContent": {
|
|
195
|
-
"results": [...],
|
|
196
|
-
"meta": { "query": "...", "mode": "hybrid" }
|
|
197
|
-
}
|
|
198
|
-
}
|
|
52
|
+
```bash
|
|
53
|
+
gno mcp status
|
|
199
54
|
```
|
|
200
55
|
|
|
201
|
-
##
|
|
56
|
+
## Uninstall
|
|
202
57
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
{
|
|
207
|
-
"isError": true,
|
|
208
|
-
"content": [
|
|
209
|
-
{ "type": "text", "text": "Error: Document not found" }
|
|
210
|
-
]
|
|
211
|
-
}
|
|
58
|
+
```bash
|
|
59
|
+
gno mcp uninstall
|
|
60
|
+
gno mcp uninstall -t claude-code
|
|
212
61
|
```
|
|
213
|
-
|
|
214
|
-
## Graceful Degradation
|
|
215
|
-
|
|
216
|
-
`gno.query` degrades gracefully:
|
|
217
|
-
|
|
218
|
-
- No vectors → BM25 only
|
|
219
|
-
- No expansion model → skips expansion
|
|
220
|
-
- No rerank model → skips reranking
|
package/package.json
CHANGED
|
@@ -161,13 +161,12 @@ async function processBatches(ctx: BatchContext): Promise<BatchResult> {
|
|
|
161
161
|
continue;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
// Store vectors
|
|
164
|
+
// Store vectors (embeddedAt set by DB)
|
|
165
165
|
const vectors: VectorRow[] = batch.map((b, idx) => ({
|
|
166
166
|
mirrorHash: b.mirrorHash,
|
|
167
167
|
seq: b.seq,
|
|
168
168
|
model: ctx.modelUri,
|
|
169
169
|
embedding: new Float32Array(embeddings[idx] as number[]),
|
|
170
|
-
embeddedAt: new Date().toISOString(),
|
|
171
170
|
}));
|
|
172
171
|
|
|
173
172
|
const storeResult = await ctx.vectorIndex.upsertVectors(vectors);
|
|
@@ -373,6 +372,26 @@ export async function embed(options: EmbedOptions = {}): Promise<EmbedResult> {
|
|
|
373
372
|
return { success: false, error: result.error };
|
|
374
373
|
}
|
|
375
374
|
|
|
375
|
+
// Sync vec index if any vec0 writes failed (matches embedBacklog behavior)
|
|
376
|
+
if (vectorIndex.vecDirty) {
|
|
377
|
+
const syncResult = await vectorIndex.syncVecIndex();
|
|
378
|
+
if (syncResult.ok) {
|
|
379
|
+
const { added, removed } = syncResult.value;
|
|
380
|
+
if (added > 0 || removed > 0) {
|
|
381
|
+
if (!options.json) {
|
|
382
|
+
process.stdout.write(
|
|
383
|
+
`\n[vec] Synced index: +${added} -${removed}\n`
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
vectorIndex.vecDirty = false;
|
|
388
|
+
} else if (!options.json) {
|
|
389
|
+
process.stdout.write(
|
|
390
|
+
`\n[vec] Sync failed: ${syncResult.error.message}\n`
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
376
395
|
return {
|
|
377
396
|
success: true,
|
|
378
397
|
embedded: result.embedded,
|