@qiqiangvae/dsh-obsidian 0.1.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.
Files changed (45) hide show
  1. package/ATTRIBUTION.md +36 -0
  2. package/LICENSE +21 -0
  3. package/README.md +102 -0
  4. package/cordis.patch.yml +23 -0
  5. package/index.js +5 -0
  6. package/lib/index.d.ts +64 -0
  7. package/lib/index.d.ts.map +1 -0
  8. package/lib/index.js +351 -0
  9. package/lib/index.js.map +1 -0
  10. package/lib/lint.d.ts +25 -0
  11. package/lib/lint.d.ts.map +1 -0
  12. package/lib/lint.js +145 -0
  13. package/lib/lint.js.map +1 -0
  14. package/lib/scaffold.d.ts +26 -0
  15. package/lib/scaffold.d.ts.map +1 -0
  16. package/lib/scaffold.js +67 -0
  17. package/lib/scaffold.js.map +1 -0
  18. package/lib/search.d.ts +41 -0
  19. package/lib/search.d.ts.map +1 -0
  20. package/lib/search.js +127 -0
  21. package/lib/search.js.map +1 -0
  22. package/lib/skills.d.ts +18 -0
  23. package/lib/skills.d.ts.map +1 -0
  24. package/lib/skills.js +83 -0
  25. package/lib/skills.js.map +1 -0
  26. package/lib/types.d.ts +55 -0
  27. package/lib/types.d.ts.map +1 -0
  28. package/lib/types.js +6 -0
  29. package/lib/types.js.map +1 -0
  30. package/lib/vault.d.ts +69 -0
  31. package/lib/vault.d.ts.map +1 -0
  32. package/lib/vault.js +315 -0
  33. package/lib/vault.js.map +1 -0
  34. package/package.json +66 -0
  35. package/skills/defuddle/SKILL.md +35 -0
  36. package/skills/json-canvas/SKILL.md +61 -0
  37. package/skills/obsidian-bases/SKILL.md +51 -0
  38. package/skills/obsidian-cli/SKILL.md +41 -0
  39. package/skills/obsidian-markdown/SKILL.md +59 -0
  40. package/skills/save/SKILL.md +33 -0
  41. package/skills/think/SKILL.md +27 -0
  42. package/skills/wiki/SKILL.md +45 -0
  43. package/skills/wiki-ingest/SKILL.md +40 -0
  44. package/skills/wiki-lint/SKILL.md +36 -0
  45. package/skills/wiki-query/SKILL.md +34 -0
package/lib/types.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * types.ts — minimal type declarations for the DSH cordis API we use.
3
+ * When dsh bumps the public API, update these; the loader reports mismatches.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
package/lib/vault.d.ts ADDED
@@ -0,0 +1,69 @@
1
+ /**
2
+ * vault.ts — vault file operations, type routing, frontmatter bookkeeping.
3
+ *
4
+ * Re-implementation of the LLM Wiki pattern's mechanical core (paths,
5
+ * frontmatter, master index, log, source delta tracking). Adapted from
6
+ * dsh-plugin-wiki-tools; now written directly against node:fs in modern
7
+ * TypeScript so it survives cordis API churn.
8
+ */
9
+ import type { PluginConfig } from './types.js';
10
+ export type { PluginConfig } from './types.js';
11
+ export interface VaultLayout {
12
+ wikiDir: string;
13
+ rawDir: string;
14
+ metaDir: string;
15
+ indexFile: string;
16
+ logFile: string;
17
+ hotFile: string;
18
+ typeFolders: Record<string, string>;
19
+ }
20
+ export declare function resolveLayout(vaultPath: string, config: PluginConfig): VaultLayout;
21
+ export declare function isMachineryPage(name: string): boolean;
22
+ export declare function isPortableFilename(name: string): boolean;
23
+ /** Reject any path that resolves outside vaultPath. */
24
+ export declare function assertInsideVault(vaultPath: string, target: string): void;
25
+ export interface Frontmatter {
26
+ title?: string;
27
+ type?: string;
28
+ tags?: string[];
29
+ created?: string;
30
+ updated?: string;
31
+ source?: string;
32
+ source_hash?: string;
33
+ [k: string]: unknown;
34
+ }
35
+ export declare function parseFrontmatter(md: string): {
36
+ fm: Frontmatter;
37
+ body: string;
38
+ };
39
+ export declare function serializeFrontmatter(fm: Frontmatter): string;
40
+ export declare function completeFrontmatter(existing: Frontmatter, patch: Partial<Frontmatter>, now?: string): Frontmatter;
41
+ export declare function upsertIndexEntry(indexFile: string, type: string, sectionHeading: string, title: string, style?: ':' | '—'): void;
42
+ export declare function appendLog(logFile: string, line: string): void;
43
+ export interface WritePageArgs {
44
+ title: string;
45
+ type: string;
46
+ content: string;
47
+ tags?: string[];
48
+ source_path?: string;
49
+ force?: boolean;
50
+ }
51
+ export interface WritePageResult {
52
+ path: string;
53
+ unresolvedLinks: string[];
54
+ sourceHash?: string;
55
+ skipped?: boolean;
56
+ }
57
+ export declare function safeFilename(title: string): string;
58
+ export declare function routePageFolder(vaultPath: string, layout: VaultLayout, type: string): string;
59
+ export declare function collectUnresolvedLinks(body: string, knownTitles: Set<string>): string[];
60
+ export declare function listAllTitles(wikiDir: string): Set<string>;
61
+ export declare function sha256(s: string | Buffer): string;
62
+ export declare function writePage(vaultPath: string, config: PluginConfig, args: WritePageArgs): WritePageResult;
63
+ export declare function renamePage(vaultPath: string, config: PluginConfig, oldTitle: string, newTitle: string): {
64
+ from: string;
65
+ to: string;
66
+ };
67
+ export declare function deletePage(vaultPath: string, config: PluginConfig, title: string): void;
68
+ export declare function walkMd(root: string): Generator<string>;
69
+ //# sourceMappingURL=vault.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"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"}
package/lib/vault.js ADDED
@@ -0,0 +1,315 @@
1
+ /**
2
+ * vault.ts — vault file operations, type routing, frontmatter bookkeeping.
3
+ *
4
+ * Re-implementation of the LLM Wiki pattern's mechanical core (paths,
5
+ * frontmatter, master index, log, source delta tracking). Adapted from
6
+ * dsh-plugin-wiki-tools; now written directly against node:fs in modern
7
+ * TypeScript so it survives cordis API churn.
8
+ */
9
+ import { existsSync, readFileSync, writeFileSync, readdirSync, statSync, mkdirSync, renameSync, unlinkSync, } from 'node:fs';
10
+ import { join, dirname, basename, extname, resolve, sep } from 'node:path';
11
+ import { createHash } from 'node:crypto';
12
+ // ──────────────────────────────────────────────────────────────────────────────
13
+ // Defaults — overridable via config.typeFolders
14
+ // ──────────────────────────────────────────────────────────────────────────────
15
+ const DEFAULT_TYPE_FOLDERS = {
16
+ domain: 'wiki/areas',
17
+ area: 'wiki/areas',
18
+ project: 'wiki/projects',
19
+ resource: 'wiki/resources',
20
+ source: 'wiki/sources',
21
+ archive: 'wiki/archive',
22
+ index: 'wiki',
23
+ log: 'wiki',
24
+ hot: 'wiki',
25
+ };
26
+ export function resolveLayout(vaultPath, config) {
27
+ const typeFolders = { ...DEFAULT_TYPE_FOLDERS, ...(config.typeFolders ?? {}) };
28
+ return {
29
+ wikiDir: join(vaultPath, 'wiki'),
30
+ rawDir: join(vaultPath, '.raw'),
31
+ metaDir: join(vaultPath, 'wiki', 'meta'),
32
+ indexFile: join(vaultPath, 'wiki', 'index.md'),
33
+ logFile: join(vaultPath, 'wiki', 'log.md'),
34
+ hotFile: join(vaultPath, 'wiki', 'hot.md'),
35
+ typeFolders,
36
+ };
37
+ }
38
+ // ──────────────────────────────────────────────────────────────────────────────
39
+ // Path safety — jail everything inside the configured vaultPath
40
+ // ──────────────────────────────────────────────────────────────────────────────
41
+ const RESERVED_DEVICE_NAMES = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])$/i;
42
+ const PORTABLE_BAD_CHARS = /[:<>"|?*\\]/;
43
+ const PORTABLE_BAD_TAIL = /[ .]+$/;
44
+ export function isMachineryPage(name) {
45
+ // case-insensitive: "Lint Report", "lint report", "LINT REPORT" all count
46
+ return /^lint report\b/i.test(name);
47
+ }
48
+ export function isPortableFilename(name) {
49
+ if (!name)
50
+ return false;
51
+ if (RESERVED_DEVICE_NAMES.test(name))
52
+ return false;
53
+ if (PORTABLE_BAD_CHARS.test(name))
54
+ return false;
55
+ if (PORTABLE_BAD_TAIL.test(name))
56
+ return false;
57
+ return true;
58
+ }
59
+ /** Reject any path that resolves outside vaultPath. */
60
+ export function assertInsideVault(vaultPath, target) {
61
+ const abs = resolve(target);
62
+ const root = resolve(vaultPath);
63
+ if (abs !== root && !abs.startsWith(root + sep)) {
64
+ throw new Error(`path escapes vault: ${target}`);
65
+ }
66
+ }
67
+ const FM_RE = /^---\n([\s\S]*?)\n---\n?/;
68
+ export function parseFrontmatter(md) {
69
+ const m = FM_RE.exec(md);
70
+ if (!m)
71
+ return { fm: {}, body: md };
72
+ const fm = {};
73
+ for (const line of m[1].split('\n')) {
74
+ const idx = line.indexOf(':');
75
+ if (idx < 0)
76
+ continue;
77
+ const key = line.slice(0, idx).trim();
78
+ let val = line.slice(idx + 1).trim();
79
+ if (typeof val === 'string' && val.startsWith('[') && val.endsWith(']')) {
80
+ // YAML-style inline list: [a, b, c] — split, strip quotes
81
+ val = val.slice(1, -1).split(',').map((s) => s.trim().replace(/^["']|["']$/g, '')).filter(Boolean);
82
+ }
83
+ else if (typeof val === 'string') {
84
+ val = val.replace(/^["']|["']$/g, '');
85
+ }
86
+ fm[key] = val;
87
+ }
88
+ return { fm, body: md.slice(m[0].length) };
89
+ }
90
+ export function serializeFrontmatter(fm) {
91
+ const lines = ['---'];
92
+ for (const [k, v] of Object.entries(fm)) {
93
+ if (v === undefined)
94
+ continue;
95
+ if (Array.isArray(v)) {
96
+ lines.push(`${k}: ${JSON.stringify(v)}`);
97
+ }
98
+ else if (typeof v === 'string' && (v.includes(':') || v.startsWith('['))) {
99
+ lines.push(`${k}: "${v.replace(/"/g, '\\"')}"`);
100
+ }
101
+ else {
102
+ lines.push(`${k}: ${v}`);
103
+ }
104
+ }
105
+ lines.push('---', '');
106
+ return lines.join('\n');
107
+ }
108
+ export function completeFrontmatter(existing, patch, now = new Date().toISOString().slice(0, 10)) {
109
+ const merged = { ...existing, ...patch };
110
+ if (!merged.created)
111
+ merged.created = existing.created ?? now;
112
+ merged.updated = now;
113
+ return merged;
114
+ }
115
+ // ──────────────────────────────────────────────────────────────────────────────
116
+ // Index / log / hot bookkeeping
117
+ // ──────────────────────────────────────────────────────────────────────────────
118
+ export function upsertIndexEntry(indexFile, type, sectionHeading, title, style = ':') {
119
+ if (!existsSync(indexFile)) {
120
+ writeFileSync(indexFile, `# Index\n\n`);
121
+ }
122
+ const md = readFileSync(indexFile, 'utf8');
123
+ const sectionRe = new RegExp(`(^## ${escapeRe(sectionHeading)}\\n)([\\s\\S]*?)(?=^## |\\Z)`, 'm');
124
+ const m = sectionRe.exec(md);
125
+ const sep = style === '—' ? ' — ' : ': ';
126
+ const entry = `- [[${title}]]${sep}${type}\n`;
127
+ let next;
128
+ if (m) {
129
+ const body = m[2];
130
+ if (body.includes(`[[${title}]]`))
131
+ return; // already present
132
+ next = md.replace(m[0], m[1] + body + entry + m[3]);
133
+ }
134
+ else {
135
+ next = md + `\n## ${sectionHeading}\n\n` + entry;
136
+ }
137
+ writeFileSync(indexFile, next);
138
+ }
139
+ export function appendLog(logFile, line) {
140
+ if (!existsSync(dirname(logFile))) {
141
+ mkdirSync(dirname(logFile), { recursive: true });
142
+ }
143
+ const today = new Date().toISOString().slice(0, 10);
144
+ let md = existsSync(logFile) ? readFileSync(logFile, 'utf8') : `# Log\n\n`;
145
+ if (!md.startsWith(`## ${today}`)) {
146
+ md = `## ${today}\n\n` + md.replace(/^# Log\n\n/, '');
147
+ }
148
+ md = `- ${new Date().toISOString()} — ${line}\n` + md;
149
+ writeFileSync(logFile, md);
150
+ }
151
+ export function safeFilename(title) {
152
+ return title.replace(/[\\/]/g, '-').replace(/[<>:"?*|]/g, '').trim() || 'untitled';
153
+ }
154
+ // typeFolders values are RELATIVE TO vaultPath (they already include the
155
+ // leading `wiki/` segment), e.g. `resource` → `wiki/resources`. Route against
156
+ // vaultPath directly — never against wikiDir, which would double the `wiki/`.
157
+ export function routePageFolder(vaultPath, layout, type) {
158
+ const folder = layout.typeFolders[type] ?? layout.typeFolders['resource'];
159
+ return join(vaultPath, folder);
160
+ }
161
+ export function collectUnresolvedLinks(body, knownTitles) {
162
+ const linkRe = /\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g;
163
+ const out = [];
164
+ const seen = new Set();
165
+ for (const m of body.matchAll(linkRe)) {
166
+ const t = m[1].trim();
167
+ if (knownTitles.has(t) || seen.has(t))
168
+ continue;
169
+ seen.add(t);
170
+ out.push(t);
171
+ }
172
+ return out;
173
+ }
174
+ export function listAllTitles(wikiDir) {
175
+ const titles = new Set();
176
+ if (!existsSync(wikiDir))
177
+ return titles;
178
+ for (const f of walkMd(wikiDir)) {
179
+ const base = basename(f, extname(f));
180
+ if (!isMachineryPage(base))
181
+ titles.add(base);
182
+ }
183
+ return titles;
184
+ }
185
+ export function sha256(s) {
186
+ return createHash('sha256').update(s).digest('hex');
187
+ }
188
+ export function writePage(vaultPath, config, args) {
189
+ const layout = resolveLayout(vaultPath, config);
190
+ const filename = safeFilename(args.title);
191
+ if (isMachineryPage(filename)) {
192
+ throw new Error(`refusing to write machinery page: ${filename}`);
193
+ }
194
+ if (!isPortableFilename(filename)) {
195
+ throw new Error(`non-portable filename: ${filename}`);
196
+ }
197
+ const folder = routePageFolder(vaultPath, layout, args.type);
198
+ assertInsideVault(vaultPath, folder);
199
+ if (!existsSync(folder))
200
+ mkdirSync(folder, { recursive: true });
201
+ const targetPath = join(folder, `${filename}.md`);
202
+ // filename-uniqueness guard
203
+ if (existsSync(targetPath) && args.title !== basename(targetPath, '.md')) {
204
+ throw new Error(`filename collision: ${targetPath}`);
205
+ }
206
+ // source hash + skip-on-unchanged
207
+ let sourceHash;
208
+ if (args.source_path) {
209
+ if (!existsSync(args.source_path)) {
210
+ throw new Error(`source not found: ${args.source_path}`);
211
+ }
212
+ sourceHash = sha256(readFileSync(args.source_path));
213
+ }
214
+ // parse existing page (if any) to preserve `created` and unknown fields
215
+ const existing = existsSync(targetPath)
216
+ ? parseFrontmatter(readFileSync(targetPath, 'utf8'))
217
+ : { fm: {}, body: '' };
218
+ if (existing.fm.source_hash && sourceHash && existing.fm.source_hash === sourceHash && !args.force) {
219
+ return { path: targetPath, unresolvedLinks: [], sourceHash, skipped: true };
220
+ }
221
+ const fm = completeFrontmatter(existing.fm, {
222
+ title: args.title,
223
+ type: args.type,
224
+ tags: args.tags,
225
+ source: args.source_path,
226
+ source_hash: sourceHash,
227
+ });
228
+ const final = serializeFrontmatter(fm) + args.content;
229
+ writeFileSync(targetPath, final, 'utf8');
230
+ // index & log
231
+ const sectionHeading = layout.typeFolders[args.type]?.replace(/^wiki\//, '') ?? args.type;
232
+ upsertIndexEntry(layout.indexFile, args.type, sectionHeading, args.title);
233
+ appendLog(layout.logFile, `${args.type} [[${args.title}]]${args.source_path ? ` (source ${args.source_path})` : ''}`);
234
+ // forward-link report
235
+ const titles = listAllTitles(layout.wikiDir);
236
+ titles.add(args.title);
237
+ const unresolvedLinks = collectUnresolvedLinks(args.content, titles);
238
+ return { path: targetPath, unresolvedLinks, sourceHash };
239
+ }
240
+ // ──────────────────────────────────────────────────────────────────────────────
241
+ // Page rename with machinery protection
242
+ // ──────────────────────────────────────────────────────────────────────────────
243
+ export function renamePage(vaultPath, config, oldTitle, newTitle) {
244
+ const layout = resolveLayout(vaultPath, config);
245
+ const oldName = safeFilename(oldTitle);
246
+ const newName = safeFilename(newTitle);
247
+ if (isMachineryPage(oldName) || isMachineryPage(newName)) {
248
+ throw new Error('refusing to rename machinery page');
249
+ }
250
+ if (!isPortableFilename(newName)) {
251
+ throw new Error(`non-portable filename: ${newName}`);
252
+ }
253
+ // Locate the existing page across every effective type folder.
254
+ let from;
255
+ for (const type of Object.keys(layout.typeFolders)) {
256
+ const dir = routePageFolder(vaultPath, layout, type);
257
+ const candidate = join(dir, `${oldName}.md`);
258
+ if (existsSync(candidate)) {
259
+ from = candidate;
260
+ break;
261
+ }
262
+ }
263
+ if (!from)
264
+ throw new Error(`not found: ${oldTitle}`);
265
+ const toDir = dirname(from);
266
+ const to = join(toDir, `${newName}.md`);
267
+ if (existsSync(to))
268
+ throw new Error(`target exists: ${to}`);
269
+ renameSync(from, to);
270
+ return { from, to };
271
+ }
272
+ export function deletePage(vaultPath, config, title) {
273
+ const layout = resolveLayout(vaultPath, config);
274
+ const name = safeFilename(title);
275
+ if (isMachineryPage(name))
276
+ throw new Error('refusing to delete machinery page');
277
+ // search in all effective typeFolders
278
+ for (const type of Object.keys(layout.typeFolders)) {
279
+ const p = join(routePageFolder(vaultPath, layout, type), `${name}.md`);
280
+ if (existsSync(p)) {
281
+ unlinkSync(p);
282
+ return;
283
+ }
284
+ }
285
+ throw new Error(`not found: ${title}`);
286
+ }
287
+ // ──────────────────────────────────────────────────────────────────────────────
288
+ // Walk helpers
289
+ // ──────────────────────────────────────────────────────────────────────────────
290
+ export function* walkMd(root) {
291
+ if (!existsSync(root))
292
+ return;
293
+ for (const entry of readdirSync(root)) {
294
+ const p = join(root, entry);
295
+ let st;
296
+ try {
297
+ st = statSync(p);
298
+ }
299
+ catch {
300
+ continue;
301
+ }
302
+ if (st.isDirectory()) {
303
+ if (entry === 'meta' || entry.startsWith('.'))
304
+ continue;
305
+ yield* walkMd(p);
306
+ }
307
+ else if (st.isFile() && p.endsWith('.md')) {
308
+ yield p;
309
+ }
310
+ }
311
+ }
312
+ function escapeRe(s) {
313
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
314
+ }
315
+ //# sourceMappingURL=vault.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault.js","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@qiqiangvae/dsh-obsidian",
3
+ "version": "0.1.0",
4
+ "description": "Self-organizing AI second brain for Obsidian, as a single DeepSeek Harness plugin. Merged fork of dsh-plugin-wiki-skills + dsh-plugin-wiki-tools, targeting parity with claude-obsidian.",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "types": "index.d.ts",
8
+ "exports": {
9
+ ".": "./index.js",
10
+ "./lib/vault.js": "./lib/vault.js",
11
+ "./lib/search.js": "./lib/search.js",
12
+ "./lib/lint.js": "./lib/lint.js",
13
+ "./lib/scaffold.js": "./lib/scaffold.js",
14
+ "./lib/skills.js": "./lib/skills.js",
15
+ "./lib/types.js": "./lib/types.js",
16
+ "./cordis.patch.yml": "./cordis.patch.yml",
17
+ "./package.json": "./package.json"
18
+ },
19
+ "files": [
20
+ "index.js",
21
+ "lib/",
22
+ "cordis.patch.yml",
23
+ "skills/",
24
+ "README.md",
25
+ "LICENSE",
26
+ "ATTRIBUTION.md"
27
+ ],
28
+ "keywords": [
29
+ "dsh-plugin",
30
+ "deepseek-harness",
31
+ "obsidian",
32
+ "knowledge-base",
33
+ "second-brain",
34
+ "llm-wiki"
35
+ ],
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/qiqiangvae/dsh-obsidian.git"
39
+ },
40
+ "license": "MIT",
41
+ "engines": {
42
+ "node": ">=22.19.0"
43
+ },
44
+ "peerDependencies": {
45
+ "@deepseek-ai/cordis": "*",
46
+ "@deepseek-ai/dsh-tools": "*",
47
+ "@deepseek-ai/schemastery": "*"
48
+ },
49
+ "scripts": {
50
+ "test": "node --test test/basic.test.mjs test/apply.smoke.test.mjs",
51
+ "build": "tsc -p tsconfig.json",
52
+ "prepublishOnly": "npm run build"
53
+ },
54
+ "devDependencies": {
55
+ "typescript": "^5.5.0",
56
+ "@types/node": "^20.0.0",
57
+ "@deepseek-ai/cordis": "^4.0.1",
58
+ "@deepseek-ai/dsh-tools": "^0.0.1-rc.1",
59
+ "@deepseek-ai/schemastery": "^3.18.1"
60
+ },
61
+ "dsh": {
62
+ "bundle": {
63
+ "patch": "./cordis.patch.yml"
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: defuddle
3
+ description: Extract clean markdown from a web page (article, blog post, doc page) by stripping nav, ads, cookie banners, and chrome. Use before ingesting a URL into the vault, to save tokens and keep the source readable.
4
+ ---
5
+
6
+ # defuddle
7
+
8
+ Clean a web page down to its article body.
9
+
10
+ ## When to use
11
+
12
+ - Before any URL ingestion via `wiki-ingest`, prefer running the URL through
13
+ defuddle-style extraction.
14
+ - The actual extraction is done by the [Defuddle](https://github.com/kepano/defuddle)
15
+ CLI / npm package. The skill's job is to *instruct* the agent to call it.
16
+
17
+ ## Workflow
18
+
19
+ 1. Fetch the URL. If the response is already markdown, skip defuddle.
20
+ 2. Otherwise, run `npx defuddle <url>` (or the equivalent in your runtime).
21
+ 3. Hand the cleaned markdown to `wiki-ingest` to write a `resource` page.
22
+
23
+ ## What defuddle removes
24
+
25
+ - Nav, header, footer
26
+ - Cookie / GDPR banners
27
+ - Sidebars, related-article blocks
28
+ - Most ads and trackers
29
+
30
+ ## What it preserves
31
+
32
+ - Article title (h1)
33
+ - Author and date metadata
34
+ - Headings, paragraphs, lists, code blocks
35
+ - Images (with src intact)
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: json-canvas
3
+ description: Create and edit JSON Canvas (.canvas) files: nodes (text, file, link, group), edges, and layout. Use to produce visual mind-maps, knowledge graphs, or workflow diagrams from vault content.
4
+ ---
5
+
6
+ # json-canvas
7
+
8
+ JSON Canvas is an open spec (https://jsoncanvas.org). Obsidian Canvas reads
9
+ these files. Other readers: Kinopio, Jiyuu.
10
+
11
+ ## Schema (1.0)
12
+
13
+ ```json
14
+ {
15
+ "nodes": [
16
+ {
17
+ "id": "uuid-or-string",
18
+ "type": "text",
19
+ "x": 0, "y": 0, "width": 250, "height": 100,
20
+ "label": "Optional",
21
+ "text": "# Heading\nMarkdown body"
22
+ },
23
+ {
24
+ "id": "uuid-or-string",
25
+ "type": "file",
26
+ "x": 300, "y": 0, "width": 250, "height": 100,
27
+ "file": "Notes/My Note.md"
28
+ },
29
+ {
30
+ "id": "uuid-or-string",
31
+ "type": "link",
32
+ "x": 600, "y": 0, "width": 250, "height": 100,
33
+ "url": "https://example.com"
34
+ },
35
+ {
36
+ "id": "uuid-or-string",
37
+ "type": "group",
38
+ "x": 0, "y": 150, "width": 500, "height": 200,
39
+ "label": "Cluster",
40
+ "color": "1"
41
+ }
42
+ ],
43
+ "edges": [
44
+ {
45
+ "id": "edge-1",
46
+ "fromNode": "uuid-1",
47
+ "fromSide": "right",
48
+ "toNode": "uuid-2",
49
+ "toSide": "left",
50
+ "label": "links to"
51
+ }
52
+ ]
53
+ }
54
+ ```
55
+
56
+ ## Tips
57
+
58
+ - Generate `id`s as stable strings; downstream tools dedupe on them.
59
+ - Coordinates: pixel units; Obsidian's default zoom fits 100×100.
60
+ - For "graph from vault wikilinks", walk pages, build nodes per title,
61
+ and add an edge for each `[[link]]` occurrence.
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: obsidian-bases
3
+ description: Create and edit Obsidian Bases (.base) with views, filters, formulas, and summaries. Use when the user asks for a tabular view, a project dashboard, or a filtered list of pages by property.
4
+ ---
5
+
6
+ # obsidian-bases
7
+
8
+ Obsidian Bases are `.base` YAML files in the vault root (or anywhere).
9
+
10
+ ## Minimal example
11
+
12
+ ```yaml
13
+ title: Projects
14
+ filter:
15
+ and:
16
+ - type == "project"
17
+ views:
18
+ - type: table
19
+ name: Active
20
+ filter:
21
+ and:
22
+ - status == "active"
23
+ order:
24
+ - file.name
25
+ - due
26
+ - status
27
+ - type: cards
28
+ name: By status
29
+ groupBy: status
30
+ ```
31
+
32
+ ## Common formula patterns
33
+
34
+ ```yaml
35
+ formulas:
36
+ days_to_due: (date(prop("due")) - today()) / 86400000
37
+ is_overdue: (date(prop("due")) < today()) && (prop("status") != "done")
38
+ ```
39
+
40
+ ## Common gotchas
41
+
42
+ - Property names with spaces must be quoted: `prop("Project Status")`.
43
+ - `today()` is midnight UTC; for day-level comparisons use
44
+ `date(prop("due")) < today()` rather than raw string compare.
45
+ - `groupBy` on a missing property silently groups everything into `null`.
46
+
47
+ ## When to use
48
+
49
+ - A "Project dashboard" → `groupBy: status, orderBy: due`
50
+ - A "Reading list" → `filter: type == "resource" && status == "to-read"`
51
+ - A "By author" view → `groupBy: author`