obsidian-dev-skills 1.1.2 ā 1.1.4
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/obsidian-dev/references/agent-dos-donts.md +9 -11
- package/obsidian-dev/references/code-patterns.md +8 -192
- package/obsidian-dev/references/commands-settings.md +1 -4
- package/obsidian-dev/references/common-tasks.md +3 -3
- package/obsidian-ops/references/quick-reference.md +2 -2
- package/obsidian-ops/references/release-readiness.md +2 -2
- package/obsidian-ops/references/security-privacy.md +1 -1
- package/obsidian-ops/references/sync-procedure.md +9 -23
- package/obsidian-ref/references/file-conventions.md +1 -1
- package/obsidian-ref/references/ref-instructions.md +2 -2
- package/package.json +1 -1
- package/scripts/bulk-update.mjs +40 -0
- package/scripts/check-status.mjs +45 -0
|
@@ -12,29 +12,28 @@ Update frequency: Review periodically for AI agent-specific guidance
|
|
|
12
12
|
- **DO NOT** create a `.ref` subfolder inside the plugins/themes folder - clone the repo directly there
|
|
13
13
|
- Then create symlink in project's `.ref/` folder pointing to the global location
|
|
14
14
|
- For local projects, symlink directly in project's `.ref/` (don't clone to global)
|
|
15
|
-
- See [ref-instructions.md](ref-instructions.md) for details.
|
|
15
|
+
- See [ref-instructions.md](../../obsidian-ref/references/ref-instructions.md) for details.
|
|
16
16
|
- Add commands with stable IDs (don't rename once released).
|
|
17
17
|
- Provide defaults and validation in settings.
|
|
18
18
|
- Write idempotent code paths so reload/unload doesn't leak listeners or intervals.
|
|
19
19
|
- Use `this.register*` helpers for everything that needs cleanup.
|
|
20
|
-
- **Always run `pnpm build` after making changes** to catch build errors early. Only check for pnpm installation if the build fails. See [build-workflow.md](build-workflow.md) for details.
|
|
21
|
-
- **Summarize commands**: When user requests "Summarize" or "Summarize for release", follow the workflow in [summarize-commands.md](summarize-commands.md). Always read actual file changes, not just chat history.
|
|
22
|
-
- **Release preparation**: When user asks "is my plugin ready for release?" or similar, use [release-readiness.md](release-readiness.md) checklist. Run automated checks where possible, ask user interactively for items requiring their input (like platform testing).
|
|
20
|
+
- **Always run `pnpm build` after making changes** to catch build errors early. Only check for pnpm installation if the build fails. See [build-workflow.md](../../obsidian-ops/references/build-workflow.md) for details.
|
|
21
|
+
- **Summarize commands**: When user requests "Summarize" or "Summarize for release", follow the workflow in [summarize-commands.md](../../obsidian-ops/references/summarize-commands.md). Always read actual file changes, not just chat history.
|
|
22
|
+
- **Release preparation**: When user asks "is my plugin ready for release?" or similar, use [release-readiness.md](../../obsidian-ops/references/release-readiness.md) checklist. Run automated checks where possible, ask user interactively for items requiring their input (like platform testing).
|
|
23
23
|
|
|
24
24
|
## Don't
|
|
25
25
|
- Introduce network calls without an obvious user-facing reason and documentation.
|
|
26
26
|
- Ship features that require cloud services without clear disclosure and explicit opt-in.
|
|
27
27
|
- Store or transmit vault contents unless essential and consented.
|
|
28
|
-
- **File structure**: Never have `main.ts` in both root AND `src/` - this causes build confusion. For simple plugins, `main.ts` in root is acceptable. For plugins with multiple files, place `main.ts` in `src/` (recommended). See [file-conventions.md](file-conventions.md) and
|
|
28
|
+
- **File structure**: Never have `main.ts` in both root AND `src/` - this causes build confusion. For simple plugins, `main.ts` in root is acceptable. For plugins with multiple files, place `main.ts` in `src/` (recommended). See [file-conventions.md](../../obsidian-ref/references/file-conventions.md) for standard structure and common pitfalls.
|
|
29
29
|
- **Git operations**: Never automatically commit, push, or perform any git operations. All git operations must be left to the user.
|
|
30
|
-
- **Git updates**: When checking for updates to repos in `.ref`, you can use read-only commands like `git fetch` and `git log` to check what's new, but **never automatically pull** - always ask the user first. See [ref-instructions.md](ref-instructions.md) for how to check for updates.
|
|
30
|
+
- **Git updates**: When checking for updates to repos in `.ref`, you can use read-only commands like `git fetch` and `git log` to check what's new, but **never automatically pull** - always ask the user first. See [ref-instructions.md](../../obsidian-ref/references/ref-instructions.md) for how to check for updates.
|
|
31
31
|
|
|
32
32
|
## Fixing Linting Errors
|
|
33
33
|
|
|
34
34
|
**DO**:
|
|
35
35
|
- Read the error message carefully - note the exact line and column
|
|
36
36
|
- Understand what the error is actually complaining about
|
|
37
|
-
- Check the [linting-fixes-guide.md](linting-fixes-guide.md) for the specific error type
|
|
38
37
|
- Fix the root cause, not the symptom
|
|
39
38
|
- Test with `pnpm lint` after each fix
|
|
40
39
|
- Verify `pnpm build` still works
|
|
@@ -49,9 +48,8 @@ Update frequency: Review periodically for AI agent-specific guidance
|
|
|
49
48
|
|
|
50
49
|
**When Stuck**:
|
|
51
50
|
1. Read the error message - what line/column is it complaining about?
|
|
52
|
-
2.
|
|
53
|
-
3.
|
|
54
|
-
4.
|
|
55
|
-
5. If you've tried the same thing 3 times, stop and re-read the error message
|
|
51
|
+
2. Understand the type signature - what does the function expect?
|
|
52
|
+
3. Fix the actual type mismatch, not just suppress the warning
|
|
53
|
+
4. If you've tried the same thing 3 times, stop and re-read the error message
|
|
56
54
|
|
|
57
55
|
|
|
@@ -130,119 +130,16 @@ class MySettingTab extends PluginSettingTab {
|
|
|
130
130
|
this.addSettingTab(new MySettingTab(this.app, this));
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
-
## Settings with Groups
|
|
133
|
+
## Settings with Groups
|
|
134
134
|
|
|
135
135
|
**Source**: Based on `.ref/obsidian-api/obsidian.d.ts` (API is authoritative) - `SettingGroup` requires API 1.11.0+
|
|
136
136
|
|
|
137
|
-
**Use this when**: You want to
|
|
137
|
+
**Use this when**: You want to visually group related settings together.
|
|
138
138
|
|
|
139
|
-
**
|
|
140
|
-
- Continue using the compatibility utility (supports all versions)
|
|
141
|
-
- Force `minAppVersion: "1.11.0"` in `manifest.json` and use `SettingGroup` directly (simpler, but excludes older versions)
|
|
142
|
-
|
|
143
|
-
### Step 1: Create the Compatibility Utility
|
|
144
|
-
|
|
145
|
-
Create `src/utils/settings-compat.ts` (or wherever you keep utilities):
|
|
146
|
-
|
|
147
|
-
```ts
|
|
148
|
-
/**
|
|
149
|
-
* Compatibility utilities for settings
|
|
150
|
-
* Provides backward compatibility for SettingGroup (requires API 1.11.0+)
|
|
151
|
-
*/
|
|
152
|
-
import { Setting, requireApiVersion } from 'obsidian';
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Type definition for SettingGroup constructor
|
|
156
|
-
* Note: SettingGroup may exist at runtime in 1.11.0+ but may not be in TypeScript definitions
|
|
157
|
-
*
|
|
158
|
-
* IMPORTANT: This type signature is inferred from usage patterns. When .ref/obsidian-api/obsidian.d.ts
|
|
159
|
-
* is available, verify the actual signature there. The signature shown here matches the expected
|
|
160
|
-
* behavior based on Obsidian's API design patterns.
|
|
161
|
-
*/
|
|
162
|
-
type SettingGroupConstructor = new (containerEl: HTMLElement) => {
|
|
163
|
-
setHeading(heading: string): {
|
|
164
|
-
addSetting(cb: (setting: Setting) => void): void;
|
|
165
|
-
};
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Interface that works with both SettingGroup and fallback container
|
|
170
|
-
*/
|
|
171
|
-
export interface SettingsContainer {
|
|
172
|
-
addSetting(cb: (setting: Setting) => void): void;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Creates a settings container that uses SettingGroup if available (API 1.11.0+),
|
|
177
|
-
* otherwise falls back to creating a heading and using the container directly.
|
|
178
|
-
*
|
|
179
|
-
* Uses requireApiVersion('1.11.0') to check if SettingGroup is available.
|
|
180
|
-
* This is the official Obsidian API method for version checking.
|
|
181
|
-
*
|
|
182
|
-
* IMPORTANT: We use dynamic require() instead of direct import because SettingGroup
|
|
183
|
-
* may not be in TypeScript type definitions even if it exists at runtime in 1.11.0+.
|
|
184
|
-
* This avoids compile-time TypeScript errors while still working at runtime.
|
|
185
|
-
*
|
|
186
|
-
* @param containerEl - The container element for settings
|
|
187
|
-
* @param heading - The heading text for the settings group (optional)
|
|
188
|
-
* @param manifestId - The plugin's manifest ID for CSS scoping (required for fallback mode)
|
|
189
|
-
* @returns A container that can be used to add settings
|
|
190
|
-
*/
|
|
191
|
-
export function createSettingsGroup(
|
|
192
|
-
containerEl: HTMLElement,
|
|
193
|
-
heading?: string,
|
|
194
|
-
manifestId?: string
|
|
195
|
-
): SettingsContainer {
|
|
196
|
-
// Check if SettingGroup is available (API 1.11.0+)
|
|
197
|
-
// requireApiVersion is the official Obsidian API method for version checking
|
|
198
|
-
if (requireApiVersion('1.11.0')) {
|
|
199
|
-
// Use dynamic require() to access SettingGroup at runtime
|
|
200
|
-
// This avoids TypeScript errors when SettingGroup isn't in type definitions
|
|
201
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
202
|
-
const obsidian = require('obsidian');
|
|
203
|
-
const SettingGroup = obsidian.SettingGroup as SettingGroupConstructor;
|
|
204
|
-
|
|
205
|
-
// Use SettingGroup - it's guaranteed to exist if requireApiVersion returns true
|
|
206
|
-
const group = heading
|
|
207
|
-
? new SettingGroup(containerEl).setHeading(heading)
|
|
208
|
-
: new SettingGroup(containerEl);
|
|
209
|
-
return {
|
|
210
|
-
addSetting(cb: (setting: Setting) => void) {
|
|
211
|
-
group.addSetting(cb);
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
} else {
|
|
215
|
-
// Fallback path (either API < 1.11.0 or SettingGroup not found)
|
|
216
|
-
// Add scoping class to containerEl to scope CSS to only this plugin's settings
|
|
217
|
-
if (manifestId) {
|
|
218
|
-
containerEl.addClass(`${manifestId}-settings-compat`);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Fallback: Create a heading manually and use container directly
|
|
222
|
-
if (heading) {
|
|
223
|
-
const headingEl = containerEl.createDiv('setting-group-heading');
|
|
224
|
-
headingEl.createEl('h3', { text: heading });
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return {
|
|
228
|
-
addSetting(cb: (setting: Setting) => void) {
|
|
229
|
-
const setting = new Setting(containerEl);
|
|
230
|
-
cb(setting);
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
**Note**: The dynamic `require()` approach is necessary because `SettingGroup` may not be in TypeScript type definitions even if it exists at runtime in Obsidian 1.11.0+. This avoids compile-time TypeScript errors while maintaining runtime compatibility.
|
|
238
|
-
|
|
239
|
-
### Step 2: Use in Settings Tab
|
|
240
|
-
|
|
241
|
-
Update your settings tab to use the compatibility utility:
|
|
139
|
+
**Important**: You must set `minAppVersion: "1.11.0"` in your `manifest.json` to use `SettingGroup`.
|
|
242
140
|
|
|
243
141
|
```ts
|
|
244
|
-
import { App, PluginSettingTab, Setting } from "obsidian";
|
|
245
|
-
import { createSettingsGroup } from "./utils/settings-compat";
|
|
142
|
+
import { App, PluginSettingTab, Setting, SettingGroup } from "obsidian";
|
|
246
143
|
|
|
247
144
|
interface MyPluginSettings {
|
|
248
145
|
generalEnabled: boolean;
|
|
@@ -271,7 +168,7 @@ class MySettingTab extends PluginSettingTab {
|
|
|
271
168
|
containerEl.empty();
|
|
272
169
|
|
|
273
170
|
// General Settings Group
|
|
274
|
-
const generalGroup =
|
|
171
|
+
const generalGroup = new SettingGroup(containerEl).setHeading("General Settings");
|
|
275
172
|
|
|
276
173
|
generalGroup.addSetting((setting) => {
|
|
277
174
|
setting
|
|
@@ -304,7 +201,7 @@ class MySettingTab extends PluginSettingTab {
|
|
|
304
201
|
});
|
|
305
202
|
|
|
306
203
|
// Advanced Settings Group
|
|
307
|
-
const advancedGroup =
|
|
204
|
+
const advancedGroup = new SettingGroup(containerEl).setHeading("Advanced Settings");
|
|
308
205
|
|
|
309
206
|
advancedGroup.addSetting((setting) => {
|
|
310
207
|
setting
|
|
@@ -343,69 +240,9 @@ class MySettingTab extends PluginSettingTab {
|
|
|
343
240
|
this.addSettingTab(new MySettingTab(this.app, this));
|
|
344
241
|
```
|
|
345
242
|
|
|
346
|
-
### Step 3: Add CSS Styling (Required for Older Obsidian Builds)
|
|
347
|
-
|
|
348
|
-
**Important**: When using the compatibility utility for older Obsidian builds (< 1.11.0), you must add CSS to prevent double divider lines. The fallback creates a heading with class `setting-group-heading`, and without proper CSS, you'll see a double divider (one from the heading's border-bottom and one from the first setting-item's border-top).
|
|
349
|
-
|
|
350
|
-
**CRITICAL**: The CSS **MUST** be scoped to your plugin's settings container using a manifest-ID-based class to avoid affecting other plugins' settings. Global CSS selectors will impact all settings in Obsidian, not just your plugin's settings.
|
|
351
|
-
|
|
352
|
-
Add this CSS to your `styles.css` file, replacing `{manifest-id}` with your plugin's manifest ID:
|
|
353
|
-
|
|
354
|
-
```css
|
|
355
|
-
/* Group settings compatibility styling for older Obsidian builds (< 1.11.0) */
|
|
356
|
-
/* Scoped to only this plugin's settings container to avoid affecting other plugins */
|
|
357
|
-
.{manifest-id}-settings-compat .setting-group-heading h3 {
|
|
358
|
-
margin: 0 0 0.75rem;
|
|
359
|
-
padding-bottom: 0.5rem;
|
|
360
|
-
padding-top: 0.5rem;
|
|
361
|
-
font-size: 1rem;
|
|
362
|
-
font-weight: 600;
|
|
363
|
-
border-bottom: none !important;
|
|
364
|
-
}
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
**Example**: If your manifest ID is `sample-plugin`, use `.sample-plugin-settings-compat` as the scoping class.
|
|
368
|
-
|
|
369
|
-
**How it works**:
|
|
370
|
-
- The CSS uses the `:has()` selector to detect if a `.setting-item` immediately follows the heading
|
|
371
|
-
- If settings exist below the heading, no border-bottom is applied (avoiding double divider)
|
|
372
|
-
- If no settings follow, border-bottom is applied for visual separation
|
|
373
|
-
- The scoping class (`{manifest-id}-settings-compat`) ensures CSS only affects headings within this plugin's settings container
|
|
374
|
-
- This only affects older builds (< 1.11.0) where the compatibility fallback is used
|
|
375
|
-
- On Obsidian 1.11.0+, `SettingGroup` handles styling automatically, so this CSS has no effect
|
|
376
|
-
|
|
377
|
-
**Note**: The `:has()` selector is well-supported in modern Obsidian (Chromium-based). If you need to support very old browsers, see the alternative TypeScript-based approach in the Common Pitfalls section below.
|
|
378
|
-
|
|
379
|
-
### How It Works
|
|
380
|
-
|
|
381
|
-
- **On Obsidian 1.11.0+**: Uses `SettingGroup` with proper styling and grouping
|
|
382
|
-
- **On older versions**: Creates a manual heading (`<h3>`) and uses regular `Setting` objects
|
|
383
|
-
- **Same API**: Your code using `addSetting()` works identically in both cases
|
|
384
|
-
|
|
385
243
|
### Common Pitfalls
|
|
386
244
|
|
|
387
|
-
#### Pitfall 1:
|
|
388
|
-
|
|
389
|
-
**Problem**: You may see this TypeScript error:
|
|
390
|
-
```ts
|
|
391
|
-
Module '"obsidian"' has no exported member 'SettingGroup'
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
**Cause**: `SettingGroup` may exist at runtime in Obsidian 1.11.0+ but may not be in the TypeScript type definitions, causing compile-time errors.
|
|
395
|
-
|
|
396
|
-
**Solution**: Use dynamic `require()` instead of direct import, as shown in the compatibility utility above. Do not import `SettingGroup` directly:
|
|
397
|
-
|
|
398
|
-
```ts
|
|
399
|
-
// ā WRONG - Causes TypeScript errors
|
|
400
|
-
import { SettingGroup } from 'obsidian';
|
|
401
|
-
|
|
402
|
-
// ā
CORRECT - Use dynamic require()
|
|
403
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
404
|
-
const obsidian = require('obsidian');
|
|
405
|
-
const SettingGroup = obsidian.SettingGroup as SettingGroupConstructor;
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
#### Pitfall 2: Missing Closing Parentheses
|
|
245
|
+
#### Pitfall 1: Missing Closing Parentheses
|
|
409
246
|
|
|
410
247
|
**Problem**: Arrow functions with method chaining need proper closing parentheses and semicolons.
|
|
411
248
|
|
|
@@ -431,7 +268,7 @@ generalGroup.addSetting((setting) =>
|
|
|
431
268
|
); // Closing parenthesis and semicolon required
|
|
432
269
|
```
|
|
433
270
|
|
|
434
|
-
#### Pitfall
|
|
271
|
+
#### Pitfall 2: Storing Setting References
|
|
435
272
|
|
|
436
273
|
**Problem**: If you need to reference a `Setting` object later (e.g., for visibility toggling), you must use block syntax `{ }` instead of expression syntax.
|
|
437
274
|
|
|
@@ -460,27 +297,6 @@ generalGroup.addSetting((setting) => {
|
|
|
460
297
|
mySetting.settingEl.style.display = this.plugin.settings.enabled ? "" : "none";
|
|
461
298
|
```
|
|
462
299
|
|
|
463
|
-
### Alternative: Force Minimum Version
|
|
464
|
-
|
|
465
|
-
If you don't need to support versions before 1.11.0, you can skip the compatibility utility:
|
|
466
|
-
|
|
467
|
-
1. Set `minAppVersion: "1.11.0"` in your `manifest.json`
|
|
468
|
-
2. Use `SettingGroup` directly:
|
|
469
|
-
|
|
470
|
-
```ts
|
|
471
|
-
import { Setting, SettingGroup } from "obsidian";
|
|
472
|
-
|
|
473
|
-
// In settings tab:
|
|
474
|
-
const group = new SettingGroup(containerEl).setHeading("My Settings");
|
|
475
|
-
group.addSetting((setting) => {
|
|
476
|
-
// ... configure setting
|
|
477
|
-
});
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
**Note**: Even with `minAppVersion: "1.11.0"`, you may still encounter TypeScript errors if `SettingGroup` isn't in the type definitions. In that case, you can still use the compatibility utility approach (it will always use `SettingGroup` when `requireApiVersion('1.11.0')` returns true), or use dynamic `require()` as shown in the compatibility utility.
|
|
481
|
-
|
|
482
|
-
This approach is simpler but excludes users on older Obsidian versions. The compatibility utility still works and is recommended for maximum flexibility.
|
|
483
|
-
|
|
484
300
|
## Modal with Form Input
|
|
485
301
|
|
|
486
302
|
**Source**: Based on `.ref/obsidian-plugin-docs/docs/guides/modals.md`
|
|
@@ -16,9 +16,6 @@ Applicability: Plugin
|
|
|
16
16
|
|
|
17
17
|
## Version Considerations
|
|
18
18
|
|
|
19
|
-
When using newer API features (e.g., `SettingGroup` since API 1.11.0),
|
|
20
|
-
- **For new plugins**: You can set `minAppVersion: "1.11.0"` in `manifest.json` and use the feature directly
|
|
21
|
-
- **For existing plugins**: Use version checking with `requireApiVersion()` to support both newer and older Obsidian versions
|
|
22
|
-
- See [code-patterns.md](code-patterns.md) for backward compatibility patterns, including a complete example for `SettingGroup`
|
|
19
|
+
When using newer API features (e.g., `SettingGroup` since API 1.11.0), you must set `minAppVersion: "1.11.0"` in your `manifest.json`.
|
|
23
20
|
|
|
24
21
|
|
|
@@ -12,7 +12,7 @@ Update frequency: Check Obsidian Sample Plugin repo for updates
|
|
|
12
12
|
- **common-tasks.md**: Quick snippets and basic patterns for common operations
|
|
13
13
|
- **code-patterns.md**: Complete, production-ready examples with full context and error handling
|
|
14
14
|
|
|
15
|
-
> **Note**: If user asks "what does the Obsidian API say about X?" or similar, check `.ref/obsidian-api/obsidian.d.ts` first. See [ref-instructions.md](ref-instructions.md) for when to check `.ref` setup.
|
|
15
|
+
> **Note**: If user asks "what does the Obsidian API say about X?" or similar, check `.ref/obsidian-api/obsidian.d.ts` first. See [ref-instructions.md](../../obsidian-ref/references/ref-instructions.md) for when to check `.ref` setup.
|
|
16
16
|
|
|
17
17
|
## Organize code across multiple files
|
|
18
18
|
|
|
@@ -137,7 +137,7 @@ this.addSettingTab(new MySettingTab(this.app, this));
|
|
|
137
137
|
- `addSearch(cb: (component: SearchComponent) => any)` - Add a search input at the beginning of the group (useful for filtering)
|
|
138
138
|
- `addExtraButton(cb: (component: ExtraButtonComponent) => any)` - Add an extra button to the group
|
|
139
139
|
|
|
140
|
-
**
|
|
140
|
+
**Important**: You must set `minAppVersion: "1.11.0"` in your `manifest.json` to use these methods.
|
|
141
141
|
|
|
142
142
|
## Secret Storage
|
|
143
143
|
|
|
@@ -221,7 +221,7 @@ const value = this.app.secretStorage.getSecret("my-api-key");
|
|
|
221
221
|
|
|
222
222
|
**Important**: Secret IDs must be lowercase alphanumeric with optional dashes (e.g., `my-plugin-api-key`). Invalid IDs will throw an error.
|
|
223
223
|
|
|
224
|
-
See [security-privacy.md](security-privacy.md) for security best practices and [code-patterns.md](code-patterns.md) for comprehensive examples with error handling.
|
|
224
|
+
See [security-privacy.md](../../obsidian-ops/references/security-privacy.md) for security best practices and [code-patterns.md](code-patterns.md) for comprehensive examples with error handling.
|
|
225
225
|
|
|
226
226
|
## Modal Patterns
|
|
227
227
|
|
|
@@ -34,7 +34,7 @@ One-page cheat sheet for common Obsidian theme development tasks.
|
|
|
34
34
|
- `add ref ../my-local-plugin` ā Creates symlink to local project
|
|
35
35
|
- `check API [feature]` ā Searches obsidian.d.ts for feature (for theme CSS variables, etc.)
|
|
36
36
|
|
|
37
|
-
**Note**: These commands are interpreted by AI agents and execute the corresponding workflows automatically.
|
|
37
|
+
**Note**: These commands are interpreted by AI agents and execute the corresponding workflows automatically.
|
|
38
38
|
|
|
39
39
|
## Build Commands
|
|
40
40
|
|
|
@@ -165,5 +165,5 @@ package.json
|
|
|
165
165
|
Gruntfile.js # Build configuration (if using Grunt)
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
-
See [file-conventions.md](file-conventions.md) for details.
|
|
168
|
+
See [file-conventions.md](../../obsidian-ref/references/file-conventions.md) for details.
|
|
169
169
|
|
|
@@ -202,9 +202,9 @@ When user asks "is my theme ready for release?" or similar:
|
|
|
202
202
|
|
|
203
203
|
- [versioning-releases.md](versioning-releases.md) - Release process and versioning
|
|
204
204
|
- [security-privacy.md](security-privacy.md) - Security and privacy guidelines
|
|
205
|
-
- [manifest.md](manifest.md) - Manifest requirements and validation
|
|
205
|
+
- [manifest.md](../../obsidian-ref/references/manifest.md) - Manifest requirements and validation
|
|
206
206
|
- [testing.md](testing.md) - Testing procedures and platform testing
|
|
207
|
-
- [ux-copy.md](ux-copy.md) - UI text conventions (for theme names and descriptions)
|
|
207
|
+
- [ux-copy.md](../../obsidian-ref/references/ux-copy.md) - UI text conventions (for theme names and descriptions)
|
|
208
208
|
- [build-workflow.md](build-workflow.md) - Build commands (if using build tools)
|
|
209
209
|
- [performance.md](performance.md) - Performance optimization best practices
|
|
210
210
|
|
|
@@ -54,7 +54,7 @@ Themes are CSS-only and have minimal security surface area, but still follow pri
|
|
|
54
54
|
## Related Documentation
|
|
55
55
|
|
|
56
56
|
- [release-readiness.md](release-readiness.md) - Comprehensive release checklist including policy adherence
|
|
57
|
-
- [manifest.md](manifest.md) - Manifest requirements (includes security-related fields)
|
|
57
|
+
- [manifest.md](../../obsidian-ref/references/manifest.md) - Manifest requirements (includes security-related fields)
|
|
58
58
|
- [Developer Policies](https://docs.obsidian.md/Developer+policies) - Official Obsidian Developer Policies
|
|
59
59
|
- [Theme Guidelines](https://docs.obsidian.md/Themes/Releasing/Theme+guidelines) - Official Theme Guidelines
|
|
60
60
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
Source: Project-specific procedure
|
|
3
|
-
Last synced:
|
|
3
|
+
Last synced: 2026-02-08
|
|
4
4
|
Update frequency: Update as sync process evolves
|
|
5
5
|
Applicability: Both
|
|
6
6
|
-->
|
|
7
7
|
|
|
8
8
|
# Sync Procedure: Keeping .agents Up to Date
|
|
9
9
|
|
|
10
|
-
**Sync Tracking**:
|
|
10
|
+
**Sync Tracking**: Keep track of sync dates manually in the documentation file headers to ensure traceability.
|
|
11
11
|
|
|
12
12
|
This document outlines the standard procedure for keeping the `.agents` directory content synchronized with the latest updates from the 6 core Obsidian repositories:
|
|
13
13
|
- [Obsidian API](https://github.com/obsidianmd/obsidian-api) - Official API documentation and type definitions
|
|
@@ -19,7 +19,7 @@ This document outlines the standard procedure for keeping the `.agents` director
|
|
|
19
19
|
|
|
20
20
|
## Prerequisites
|
|
21
21
|
|
|
22
|
-
1. **Set up reference repositories** (see [ref-instructions.md](ref-instructions.md)):
|
|
22
|
+
1. **Set up reference repositories** (see [ref-instructions.md](../../obsidian-ref/references/ref-instructions.md)):
|
|
23
23
|
- The 6 core Obsidian projects should be available in `.ref/` (either as symlinks to a central location or as local clones):
|
|
24
24
|
- `obsidian-api/` - API documentation
|
|
25
25
|
- `obsidian-sample-plugin/` - Sample plugin template
|
|
@@ -284,7 +284,7 @@ For each file that needs updating:
|
|
|
284
284
|
|
|
285
285
|
**Important**: Always use the actual current date from `Get-Date -Format "yyyy-MM-dd"`, never use placeholder dates.
|
|
286
286
|
|
|
287
|
-
4. **Note**: Individual file headers
|
|
287
|
+
4. **Note**: Individual file headers have "Last synced" dates. When syncing, update these dates to reflect the actual sync time.
|
|
288
288
|
|
|
289
289
|
### Step 6: Verify and Test
|
|
290
290
|
|
|
@@ -309,7 +309,7 @@ For each file that needs updating:
|
|
|
309
309
|
- [ ] Review developer docs for policy/guideline updates
|
|
310
310
|
- [ ] Review plugin docs for best practices
|
|
311
311
|
- [ ] Update relevant `.agent/skills/**/*.md` files
|
|
312
|
-
- [ ] **Update
|
|
312
|
+
- [ ] **Update sync dates** in file headers
|
|
313
313
|
- [ ] Review and commit changes
|
|
314
314
|
|
|
315
315
|
## Troubleshooting
|
|
@@ -354,39 +354,25 @@ ls -la .ref/obsidian-api
|
|
|
354
354
|
- **When starting new features**: Verify current best practices
|
|
355
355
|
- **Before releases**: Ensure guidelines are current
|
|
356
356
|
|
|
357
|
-
## Automation Ideas (Future)
|
|
358
357
|
|
|
359
|
-
Consider creating a script to:
|
|
360
|
-
- Automatically check for updates in reference repos
|
|
361
|
-
- Compare `AGENTS.md` from sample plugin with current `.agents` structure
|
|
362
|
-
- Generate a diff report of what changed
|
|
363
|
-
- Remind to update "Last synced" dates
|
|
364
358
|
|
|
365
359
|
## Updating Sync Status
|
|
366
360
|
|
|
367
|
-
After completing a sync, update
|
|
368
|
-
|
|
369
|
-
**Easy way** (recommended): Use the helper script:
|
|
370
|
-
```bash
|
|
371
|
-
node scripts/update-sync-status.mjs "Description of what was synced"
|
|
372
|
-
```
|
|
361
|
+
After completing a sync, update the "Last synced" dates in the documentation file headers.
|
|
373
362
|
|
|
374
363
|
**Manual way**: Edit the file directly:
|
|
375
364
|
```powershell
|
|
376
365
|
# Get actual current date (CRITICAL: never use placeholder!)
|
|
377
366
|
$syncDate = Get-Date -Format "yyyy-MM-dd"
|
|
378
367
|
|
|
379
|
-
# Update sync
|
|
380
|
-
# - "lastFullSync": "$syncDate"
|
|
381
|
-
# - "lastSyncSource": "Description of what was synced"
|
|
382
|
-
# - Update relevant dates in "sourceRepos" section for repos that were checked/synced
|
|
368
|
+
# Update the file header with the actual sync date
|
|
383
369
|
```
|
|
384
370
|
|
|
385
|
-
**Critical**: Always use the actual date from `Get-Date -Format "yyyy-MM-dd"`. Never use placeholder dates like "YYYY-MM-DD" or hardcoded dates.
|
|
371
|
+
**Critical**: Always use the actual date from `Get-Date -Format "yyyy-MM-dd"`. Never use placeholder dates like "YYYY-MM-DD" or hardcoded dates.
|
|
386
372
|
|
|
387
373
|
## Notes
|
|
388
374
|
|
|
389
375
|
- Not all changes need to be synced immediately - focus on breaking changes and new best practices
|
|
390
376
|
- Some content may be project-specific and shouldn't be overwritten
|
|
391
377
|
- Always review changes before committing to ensure they make sense for your project
|
|
392
|
-
- **Always update sync
|
|
378
|
+
- **Always update sync dates** to reflect when the information was last verified
|
|
@@ -44,7 +44,7 @@ package.json
|
|
|
44
44
|
|
|
45
45
|
- Source files in `src/scss/` are compiled to `theme.css`
|
|
46
46
|
- Build tools (Grunt, npm scripts, etc.) handle compilation
|
|
47
|
-
- Run build command after making changes (see [build-workflow.md](build-workflow.md))
|
|
47
|
+
- Run build command after making changes (see [build-workflow.md](../../obsidian-ops/references/build-workflow.md))
|
|
48
48
|
- **Example**: The `obsidian-oxygen` theme uses this pattern with Grunt
|
|
49
49
|
|
|
50
50
|
## Wrong Structure (Common Mistakes)
|
|
@@ -102,7 +102,7 @@ If you cannot find `.ref` initially, try:
|
|
|
102
102
|
3. **Report findings**:
|
|
103
103
|
- If updates are available, show what changed (use `git log` or `git diff`)
|
|
104
104
|
- Ask if the user wants to pull the updates
|
|
105
|
-
- **Never automatically pull** - always ask first (see [agent-dos-donts.md](agent-dos-donts.md))
|
|
105
|
+
- **Never automatically pull** - always ask first (see [agent-dos-donts.md](../../obsidian-dev/references/agent-dos-donts.md))
|
|
106
106
|
|
|
107
107
|
4. **If repo not found**:
|
|
108
108
|
- List what's available in `.ref/plugins/` or `.ref/themes/`
|
|
@@ -264,7 +264,7 @@ ln -s ../../.ref/obsidian-dev/plugins/plugin-name .ref/plugins/plugin-name
|
|
|
264
264
|
ln -s ../../.ref/obsidian-dev/themes/theme-name .ref/themes/theme-name
|
|
265
265
|
```
|
|
266
266
|
|
|
267
|
-
**Note**: See [sync-procedure.md](sync-procedure.md) for the standard procedure to keep `.agents` content synchronized with updates from these repositories.
|
|
267
|
+
**Note**: See [sync-procedure.md](../../obsidian-ops/references/sync-procedure.md) for the standard procedure to keep `.agents` content synchronized with updates from these repositories.
|
|
268
268
|
|
|
269
269
|
## Adding Additional References
|
|
270
270
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
const initScript = path.join(__dirname, 'init.mjs');
|
|
8
|
+
|
|
9
|
+
const projects = [
|
|
10
|
+
"C:\\Users\\david\\Development\\obsidian-alias-filename-history",
|
|
11
|
+
"C:\\Users\\david\\Development\\obsidian-astro-composer",
|
|
12
|
+
"C:\\Users\\david\\Development\\obsidian-astro-modular-settings",
|
|
13
|
+
"C:\\Users\\david\\Development\\obsidian-bases-cms",
|
|
14
|
+
"C:\\Users\\david\\Development\\obsidian-custom-slides",
|
|
15
|
+
"C:\\Users\\david\\Development\\obsidian-disable-tabs",
|
|
16
|
+
"C:\\Users\\david\\Development\\obsidian-explorer-focus",
|
|
17
|
+
"C:\\Users\\david\\Development\\obsidian-home-base",
|
|
18
|
+
"C:\\Users\\david\\Development\\obsidian-image-manager",
|
|
19
|
+
"C:\\Users\\david\\Development\\obsidian-oxygen-settings",
|
|
20
|
+
"C:\\Users\\david\\Development\\obsidian-periodic-links",
|
|
21
|
+
"C:\\Users\\david\\Development\\obsidian-property-over-file-name",
|
|
22
|
+
"C:\\Users\\david\\Development\\obsidian-seo",
|
|
23
|
+
"C:\\Users\\david\\Development\\obsidian-ui-tweaker",
|
|
24
|
+
"C:\\Users\\david\\Development\\obsidian-vault-cms",
|
|
25
|
+
"C:\\Users\\david\\Development\\obsidian-zenmode"
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
for (const project of projects) {
|
|
29
|
+
console.log(`\nš Updating skills for: ${path.basename(project)}`);
|
|
30
|
+
try {
|
|
31
|
+
execSync(`node "${initScript}"`, {
|
|
32
|
+
cwd: project,
|
|
33
|
+
stdio: 'inherit',
|
|
34
|
+
env: { ...process.env, INIT_CWD: project }
|
|
35
|
+
});
|
|
36
|
+
console.log(`ā
Success: ${path.basename(project)}`);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error(`ā Failed: ${path.basename(project)} - ${error.message}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const projects = [
|
|
5
|
+
"C:\\Users\\david\\Development\\obsidian-alias-filename-history",
|
|
6
|
+
"C:\\Users\\david\\Development\\obsidian-astro-composer",
|
|
7
|
+
"C:\\Users\\david\\Development\\obsidian-astro-modular-settings",
|
|
8
|
+
"C:\\Users\\david\\Development\\obsidian-bases-cms",
|
|
9
|
+
"C:\\Users\\david\\Development\\obsidian-custom-slides",
|
|
10
|
+
"C:\\Users\\david\\Development\\obsidian-disable-tabs",
|
|
11
|
+
"C:\\Users\\david\\Development\\obsidian-explorer-focus",
|
|
12
|
+
"C:\\Users\\david\\Development\\obsidian-home-base",
|
|
13
|
+
"C:\\Users\\david\\Development\\obsidian-image-manager",
|
|
14
|
+
"C:\\Users\\david\\Development\\obsidian-oxygen-settings",
|
|
15
|
+
"C:\\Users\\david\\Development\\obsidian-periodic-links",
|
|
16
|
+
"C:\\Users\\david\\Development\\obsidian-property-over-file-name",
|
|
17
|
+
"C:\\Users\\david\\Development\\obsidian-seo",
|
|
18
|
+
"C:\\Users\\david\\Development\\obsidian-ui-tweaker",
|
|
19
|
+
"C:\\Users\\david\\Development\\obsidian-vault-cms",
|
|
20
|
+
"C:\\Users\\david\\Development\\obsidian-zenmode"
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
console.log('| Project | Status | Last Sync | Source |');
|
|
24
|
+
console.log('| --- | --- | --- | --- |');
|
|
25
|
+
|
|
26
|
+
for (const project of projects) {
|
|
27
|
+
const name = path.basename(project);
|
|
28
|
+
let agentDir = path.join(project, '.agent');
|
|
29
|
+
if (!fs.existsSync(agentDir) && fs.existsSync(path.join(project, '.agents'))) {
|
|
30
|
+
agentDir = path.join(project, '.agents');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const syncStatusPath = path.join(agentDir, 'sync-status.json');
|
|
34
|
+
|
|
35
|
+
if (fs.existsSync(syncStatusPath)) {
|
|
36
|
+
try {
|
|
37
|
+
const status = JSON.parse(fs.readFileSync(syncStatusPath, 'utf8'));
|
|
38
|
+
console.log(`| ${name} | ā
Found | ${status.lastFullSync || 'Unknown'} | ${status.lastSyncSource || 'Unknown'} |`);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.log(`| ${name} | ā ļø Parse Error | - | - |`);
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
console.log(`| ${name} | ā Missing | - | - |`);
|
|
44
|
+
}
|
|
45
|
+
}
|