Claude Code Plugins

Community-maintained marketplace

Feedback

Manage prompts in your Obsidian vault. Use for saving, listing, and loading reusable prompts. Triggers on /obsidian commands, Obsidian vault operations, or prompt management requests.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name obsidian
description Manage prompts in your Obsidian vault. Use for saving, listing, and loading reusable prompts. Triggers on /obsidian commands, Obsidian vault operations, or prompt management requests.
allowed-tools Read, Write, Edit, Glob, Grep, Bash

Obsidian Prompt Manager

Manage reusable prompts in your Obsidian vault from Claude Code using native tools.

Configuration

Configuration is stored in the skill's config.json:

{
  "vaultPath": "/path/to/your/vault",
  "promptsFolder": "Claude-Prompts"
}

Config location: ~/.claude/skills/obsidian/config.json (personal) or .claude/skills/obsidian/config.json (project)


Commands

/obsidian setup <vault-path>

Configure your Obsidian vault path.

Steps to execute:

  1. Validate path exists:

    Use Bash: ls -la <vault-path>
    

    If path doesn't exist, inform user and stop.

  2. Create prompts folder:

    Use Bash: mkdir -p <vault-path>/Claude-Prompts
    
  3. Save configuration: Use Write tool to update config.json:

    {
      "vaultPath": "<vault-path>",
      "promptsFolder": "Claude-Prompts"
    }
    
  4. Confirm to user: "Vault configured: Prompts folder: /Claude-Prompts"


/obsidian save "<title>" [--tags tag1,tag2]

Save a prompt to your Obsidian vault.

Steps to execute:

  1. Read config: Use Read tool on config.json to get vaultPath. If vaultPath is empty, ask user to run /obsidian setup first.

  2. Get prompt content: Ask user: "What content should I save for this prompt?"

  3. Create markdown file: Use Write tool to create <vaultPath>/Claude-Prompts/<title>.md:

    ---
    title: "<title>"
    date: <YYYY-MM-DD>
    tags:
      - claude-prompt
      - <additional tags if provided>
    ---
    
    # <title>
    
    <prompt content>
    
  4. Confirm to user: "Saved: /Claude-Prompts/.md"</p> </li> </ol> <hr> <h3><code>/obsidian list [--search <keyword>]</code></h3> <p>List all saved prompts from your vault.</p> <p><strong>Steps to execute:</strong></p> <ol> <li><p><strong>Read config:</strong> Use Read tool on config.json to get vaultPath. If vaultPath is empty, ask user to run <code>/obsidian setup</code> first.</p> </li> <li><p><strong>Find prompts:</strong> Use Glob tool: <code><vaultPath>/Claude-Prompts/**/*.md</code></p> </li> <li><p><strong>If --search provided:</strong> Use Grep tool to filter files containing the keyword.</p> </li> <li><p><strong>For each file found:</strong> Use Read tool to extract:</p> <ul> <li>Title (from frontmatter or filename)</li> <li>Preview (first line of content after frontmatter)</li> </ul> </li> <li><p><strong>Display formatted list:</strong></p> <pre><code>Found X prompt(s): <Title 1> Path: <relative-path> Preview: <first 60 chars>... <Title 2> ... </code></pre> </li> </ol> <hr> <h3><code>/obsidian use "<prompt-name>"</code></h3> <p>Load and execute a saved prompt.</p> <p><strong>Steps to execute:</strong></p> <ol> <li><p><strong>Read config:</strong> Use Read tool on config.json to get vaultPath. If vaultPath is empty, ask user to run <code>/obsidian setup</code> first.</p> </li> <li><p><strong>Find the prompt:</strong> Use Glob tool: <code><vaultPath>/Claude-Prompts/**/*.md</code> Match filename or title (case-insensitive) to <prompt-name>.</p> </li> <li><p><strong>If not found:</strong> List available prompts and ask user to choose.</p> </li> <li><p><strong>Read prompt file:</strong> Use Read tool to get file contents.</p> </li> <li><p><strong>Extract content:</strong> Remove YAML frontmatter (everything between <code>---</code> markers). Remove the title header line (starts with <code># </code>).</p> </li> <li><p><strong>Execute the prompt:</strong> Treat the extracted content as if the user typed it. Respond to it as a new instruction.</p> </li> </ol> <hr> <h2>Examples</h2> <h3>Setup Example</h3> <pre><code>User: /obsidian setup ~/Documents/MyVault Claude: Let me configure your Obsidian vault... [Uses Bash to verify path exists] [Uses Bash to create Claude-Prompts folder] [Uses Write to save config.json] Vault configured: /Users/you/Documents/MyVault Prompts folder: /Users/you/Documents/MyVault/Claude-Prompts </code></pre> <h3>Save Example</h3> <pre><code>User: /obsidian save "Code Review Checklist" --tags review,quality Claude: What content should I save for this prompt? User: Review this code for: 1) bugs 2) performance 3) security Claude: [Uses Write to create the markdown file] Saved: /Users/you/Documents/MyVault/Claude-Prompts/Code Review Checklist.md </code></pre> <h3>List Example</h3> <pre><code>User: /obsidian list Claude: [Uses Glob to find .md files] [Uses Read to extract titles and previews] Found 3 prompt(s): Code Review Checklist Path: Code Review Checklist.md Preview: Review this code for: 1) bugs 2) performance... Debug Helper Path: Debug Helper.md Preview: Help me debug this issue by... </code></pre> <h3>Use Example</h3> <pre><code>User: /obsidian use "Code Review Checklist" Claude: [Uses Glob to find the file] [Uses Read to get contents] [Extracts content, removing frontmatter] Now executing prompt: "Review this code for: 1) bugs 2) performance 3) security" [Claude then responds as if user typed that prompt] </code></pre> </div> </article> </section> </div> </main> <vercel-analytics data-props="{}" data-params="{"slug":"@leweii/obsidian-prompt-manager/obsidian"}" data-pathname="/skills/@leweii/obsidian-prompt-manager/obsidian"></vercel-analytics> <script type="module">var f="@vercel/analytics",l="1.5.0",w=()=>{window.va||(window.va=function(...r){(window.vaq=window.vaq||[]).push(r)})};function d(){return typeof window<"u"}function u(){try{const e="production"}catch{}return"production"}function v(e="auto"){if(e==="auto"){window.vam=u();return}window.vam=e}function m(){return(d()?window.vam:u())||"production"}function c(){return m()==="development"}function b(e,r){if(!e||!r)return e;let n=e;try{const t=Object.entries(r);for(const[a,i]of t)if(!Array.isArray(i)){const o=s(i);o.test(n)&&(n=n.replace(o,`/[${a}]`))}for(const[a,i]of t)if(Array.isArray(i)){const o=s(i.join("/"));o.test(n)&&(n=n.replace(o,`/[...${a}]`))}return n}catch{return e}}function s(e){return new RegExp(`/${h(e)}(?=[/?#]|$)`)}function h(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function y(e){return e.scriptSrc?e.scriptSrc:c()?"https://va.vercel-scripts.com/v1/script.debug.js":e.basePath?`${e.basePath}/insights/script.js`:"/_vercel/insights/script.js"}function g(e={debug:!0}){var r;if(!d())return;v(e.mode),w(),e.beforeSend&&((r=window.va)==null||r.call(window,"beforeSend",e.beforeSend));const n=y(e);if(document.head.querySelector(`script[src*="${n}"]`))return;const t=document.createElement("script");t.src=n,t.defer=!0,t.dataset.sdkn=f+(e.framework?`/${e.framework}`:""),t.dataset.sdkv=l,e.disableAutoTrack&&(t.dataset.disableAutoTrack="1"),e.endpoint?t.dataset.endpoint=e.endpoint:e.basePath&&(t.dataset.endpoint=`${e.basePath}/insights`),e.dsn&&(t.dataset.dsn=e.dsn),t.onerror=()=>{const a=c()?"Please check if any ad blockers are enabled and try again.":"Be sure to enable Web Analytics for your project and deploy again. See https://vercel.com/docs/analytics/quickstart for more information.";console.log(`[Vercel Web Analytics] Failed to load script from ${n}. ${a}`)},c()&&e.debug===!1&&(t.dataset.debug="false"),document.head.appendChild(t)}function p({route:e,path:r}){var n;(n=window.va)==null||n.call(window,"pageview",{route:e,path:r})}function k(){try{return}catch{}}customElements.define("vercel-analytics",class extends HTMLElement{constructor(){super();try{const r=JSON.parse(this.dataset.props??"{}"),n=JSON.parse(this.dataset.params??"{}");g({...r,disableAutoTrack:!0,framework:"astro",basePath:k(),beforeSend:window.webAnalyticsBeforeSend});const t=this.dataset.pathname;p({route:b(t??"",n),path:t})}catch(r){throw new Error(`Failed to parse WebAnalytics properties: ${r}`)}}});</script> </body></html>