Obsidian Hello WorldSAFE
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
Overview
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
4f83675ca38aOBSERVED · 2026-10-09Host compatibility
What the documentation claims. We have not run a compatibility test.
| Host | Status | Notes |
|---|---|---|
| claude-code | mentioned | |
| cursor | mentioned |
What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
--- name: obsidian-hello-world description: 'Create a minimal working Obsidian plugin with commands, settings, modals, and ribbon icons. Use when building your first plugin feature, testing your setup, or learning basic Obsidian plugin patterns. Trigger with phrases like "obsidian hello world", "first obsidian plugin", "obsidian quick start", "simple obsidian plugin". ' allowed-tools: Read, Write, Edit, Bash(npm:*), Glob version: 1.13.0 license: MIT author: Jeremy Longshore <[email protected]> tags: - saas - obsidian - testing - getting-started compatibility: Designed for Claude Code --- # Obsidian Hello World ## Overview Build a minimal working Obsidian plugin demonstrating the five core building blocks: commands (palette + editor + checkCallback), settings tab with typed config, ribbon icons, modals, and status bar. Every snippet uses real Obsidian API. ## Prerequisites - Completed `obsidian-install-auth` setup (symlinked dev vault, `npm run dev` working) - Build pipeline producing `main.js` from `src/main.ts` ## Instructions ### Step 1: Define Typed Settings ```typescript // src/main.ts — top of file import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting, TFile } from 'obsidian'; interface MyPluginSettings { greeting: string; showRibbon: boolean; dateFormat: string; } const DEFAULT_SETTINGS: MyPluginSettings = { greeting: 'Hello, Obsidian!', showRibbon: true, dateFormat: 'YYYY-MM-DD', }; ``` ### Step 2: Create the Plugin Class with Commands ```typescript export default class MyPlugin extends Plugin { settings: MyPluginSettings; async onload() { await this.loadSettings(); // Ribbon icon — shows greeting as Notice if (this.settings.showRibbon) { this.addRibbonIcon('sparkles', 'My Plugin: Greet', () => { new Notice(this.settings.greeting); }); } // Command: show greeting (available everywhere) this.addCommand({ id: 'show-greeting', name: 'Show greeting', callback: () => new Notice(this.settings.greeting), }); // Command: insert greeting at cursor (editor-only — greyed out when no editor is active) this.addCommand({ id: 'insert-greeting', name: 'Insert greeting at cursor', editorCallback: (editor: Editor, view: MarkdownView) => { editor.replaceSelection(this.settings.greeting); }, }); // Command: word count with checkCallback (conditionally available) this.addCommand({ id: 'count-words', name: 'Count words in current note', checkCallback: (checking: boolean) => { const view = this.app.workspace.getActiveViewOfType(MarkdownView); if (view) { if (!checking) { const text = view.editor.getValue(); const count = text.split(/\s+/).filter(Boolean).length; new Notice(`Word count: ${count}`); } return true; // command is available } return false; // hide from palette when no editor }, }); // Command: open modal dialog this.addCommand({ id: 'show-greeting-modal', name: 'Show greeting modal', callback: () => new GreetingModal(this.app, this.settings.greeting).open(), }); // Command: insert today's date this.addCommand({ id: 'insert-date', name: 'Insert today\'s date', editorCallback: (editor: Editor) => { const today = new Date().toISOString().slice(0, 10); editor.replaceSelection(today); }, }); // Status bar — persistent widget at bottom const statusEl = this.addStatusBarItem(); statusEl.setText('Plugin loaded'); // Update status bar when active file changes this.registerEvent( this.app.workspace.on('active-leaf-change', () => { const view = this.app.workspace.getActiveViewOfType(MarkdownView); if (view) { const count = view.editor.getValue().split(/\s+/).filter(Boolean).length; statusEl.setText(`Words: ${count}`); } else { statusEl.setText('No editor'); } }) ); // Settings tab this.addSettingTab(new MySettingTab(this.app, this)); console.log(`[${this.manifest.id}] loaded`); } onunload() { console.log(`[${this.manifest.id}] unloaded`); } async loadSettings() { this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); } async saveSettings() { await this.saveData(this.settings); } } ``` ### Step 3: Create Settings Tab ```typescript class MySettingTab extends PluginSettingTab { plugin: MyPlugin; constructor(app: App, plugin: MyPlugin) { super(app, plugin); this.plugin = plugin; } display(): void { const { containerEl } = this; containerEl.empty(); new Setting(containerEl) .setName('Greeting message') .setDesc('Text shown by the greet command and ribbon icon.') .addText(text => text .setPlaceholder('Hello, Obsidian!') .setValue(this.plugin.settings.greeting) .onChange(async (value) => { this.plugin.settings.greeting = value; await this.plugin.saveSettings(); })); new Setting(containerEl) .setName('Show ribbon icon') .setDesc('Toggle the sparkles icon in the left ribbon. Reload plugin to apply.') .addToggle(toggle => toggle .setValue(this.plugin.settings.showRibbon) .onChange(async (value) => { this.plugin.settings.showRibbon = value; await this.plugin.saveSettings(); })); new Setting(containerEl) .setName('Date format') .setDesc('Format for the Insert Date command.') .addDropdown(dropdown => dropdown .addOption('YYYY-MM-DD', '2026-03-22') .addOption('MM/DD/YYYY', '03/22/2026') .addOption('DD.MM.YYYY', '22.03.2026') .setValue(this.plugin.settings.dateFormat) .onChange(async (value) => { this.plugi
Trust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (0)
No findings outside the package's declared scope.
Gates applied: no_behavioural_pass.
4f83675ca38afull audit observations/trust-audit/skill/jeremylongshore__obsidian-hello-world.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-09 | 4f83675ca38a | SAFE | B | 89 | first audit |
Questions
What does the Obsidian Hello World skill do?
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
Is Obsidian Hello World safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can Obsidian Hello World access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
Which assistants does Obsidian Hello World work with?
Its documentation mentions claude-code and cursor. That is what the text claims, not a compatibility test we ran.
How current is this page?
The grade is for one exact copy of the source (4f83675ca38a), read on 2026-10-09. The repository is watched, and a new audit runs when it changes — this is the first audit.