Curated Claude Code catalog
Updated 07.05.2026 · 19:39 CET
01 / Skill
AgriciDaniel

claude-obsidian

Quality
9.0

This Claude Code skill transforms your Obsidian vault into an autonomous knowledge engine that creates, organizes, maintains, and evolves notes. It ingests sources, extracts entities, updates cross-references, and files everything into a structured wiki. It's ideal for building a persistent, compounding knowledge base that answers questions by synthesizing information from your entire vault, citing specific pages.

USP

Unlike most Obsidian AI plugins that are just chat interfaces, claude-obsidian is a knowledge engine that autonomously creates, organizes, and maintains your notes. It features multi-agent support, persistent session memory, and comprehens…

Use cases

  • 01Building a personal second brain
  • 02Autonomous research and knowledge synthesis
  • 03Maintaining a structured codebase wiki
  • 04Organizing project documentation

Detected files (8)

  • skills/wiki-fold/SKILL.mdskill
    Show content (8909 bytes)
    ---
    name: wiki-fold
    description: "Rollup of wiki log entries into meta-pages. Reads the last 2^k entries from wiki/log.md, writes a structurally-idempotent fold page to wiki/folds/ that links back to children. Extractive summarization (no invention). Dry-run by default, stdout-only; commit mode writes and accepts that the PostToolUse hook auto-commits. Triggers on: fold the log, run a fold, run wiki-fold, log rollup, roll up log entries."
    ---
    
    # wiki-fold: Extractive Log Rollup
    
    Implements a bounded subset of Mechanism 1 from [[DragonScale Memory]]: flat fold over raw `wiki/log.md` entries. Fold-of-folds (hierarchical level-stacking) is **out of scope for this skill**; see "Scope boundary" below.
    
    A fold is **additive**: child log entries and their referenced pages are never modified, moved, or deleted. A fold is **extractive**: every outcome and theme in the output must be traceable to a specific child log entry. No invented facts, no synthesis beyond what the child entries support.
    
    ---
    
    ## Scope boundary (explicit)
    
    This skill does **not** implement:
    - Fold-of-folds / hierarchical level stacking (DragonScale spec calls for it; deferred to a future skill).
    - Automatic triggering (folds are always human-invoked in Phase 1).
    - Semantic-tiling dedup (Mechanism 3; separate skill).
    
    It **does** implement:
    - Flat fold over raw log.md entries at a chosen batch exponent `k`.
    - Structural idempotency via a deterministic fold ID.
    - Extractive summarization with count-checking.
    
    When referring to level in frontmatter, use `batch_exponent: k` (not `level: k`), because this skill does not produce hierarchical levels.
    
    ---
    
    ## Modes
    
    | Mode | Writes? | Invocation |
    |---|---|---|
    | **dry-run (default)** | **No Write tool calls.** Emit fold content via Bash `cat`/`heredoc` to stdout only. | `fold the log, dry-run k=3` |
    | **commit** | Uses Write/Edit tools. Each Write fires the repo PostToolUse hook which auto-commits wiki changes. Accept this. Compose full content first, then sequence writes. | `fold the log, commit k=3` (only after a clean dry-run) |
    
    **Why stdout-only in dry-run**: the repo's `hooks/hooks.json` PostToolUse hook fires on any `Write|Edit` and runs `git add wiki/ .raw/`. Writing to `/tmp` does not stage /tmp, but it still triggers the hook, which will commit *any pending wiki changes* under a generic message. Dry-run must leave zero residue. Bash stdout does not fire the hook.
    
    ---
    
    ## Deterministic fold ID
    
    Every fold has an ID derived from its inputs:
    
    ```
    fold-k{K}-from-{EARLIEST-DATE}-to-{LATEST-DATE}-n{COUNT}
    ```
    
    Example: `fold-k3-from-2026-04-10-to-2026-04-23-n8`.
    
    The filename in commit mode is `wiki/folds/{FOLD-ID}.md`. No date-of-creation in the filename. No timestamp in the title.
    
    **Duplicate detection (required)**: before emitting any output, check if `wiki/folds/{FOLD-ID}.md` already exists. If so, report "Fold already exists at wiki/folds/{FOLD-ID}.md. Use --force to overwrite, or pick a different range." and stop. This is the no-op idempotency guarantee; byte-identical content is NOT guaranteed (LLM prose varies) but the filename and scope are.
    
    ---
    
    ## Parameters
    
    - `k` (default 4): batch exponent. Batch size = `2^k`. Typical values: k=3 (8), k=4 (16), k=5 (32).
    - `range` (optional): explicit entry range `entries 1-16`. Overrides k.
    - `--force`: overwrite an existing fold with the same ID. Default no.
    - `--commit`: write to wiki/. Without it, dry-run stdout-only.
    
    If fewer than `2^k` log entries exist, report the shortfall and stop. Do not silently fold a partial batch.
    
    ---
    
    ## Procedure
    
    ### 1. Parse log entries
    
    ```
    grep -n "^## \[" wiki/log.md | head -{2^k}
    ```
    
    Record for each entry: line number, date, operation, title, and the following bullet lines until the next `## [` or end-of-section.
    
    ### 2. Extract child page identifiers
    
    From each entry's bullet list, extract:
    - `Location: wiki/path/to/page.md` (the primary page)
    - `[[Wikilinks]]` inline
    - `Pages created:` and `Pages updated:` lists
    
    Build a structured children list:
    ```yaml
    children:
      - date: "2026-04-23"
        op: "save"
        title: "DragonScale Memory v0.2 — post-adversarial-review"
        page: "[[DragonScale Memory]]"
      - ...
    ```
    
    One record per log entry. Do not dedupe by page: if two entries both point to `[[DragonScale Memory]]`, both records appear, distinguishable by date and title.
    
    ### 3. Read referenced pages (bounded)
    
    Read only the pages that are not already captured fully in the log entry's bullets. Budget: 0-10 page reads. Hard ceiling: 15. If an entry's referenced page is missing, record `page_missing: true` and proceed.
    
    ### 4. Extractive summarization with count checks
    
    Write the fold body per `references/fold-template.md`. **Rules**:
    
    - **Extractive only.** Every outcome bullet and theme bullet must cite a specific child entry (e.g., `(from 2026-04-14 session)`) or a quoted line from that entry. Do not introduce events, counts, or interpretations not present in a child entry.
    - **Log entry is the primary source.** If the log entry's bullets and the referenced meta-page disagree on a fact (e.g., a count), prefer the log-entry bullets and flag the mismatch as "source mismatch: log says X, meta says Y."
    - **Count checks.** If you write "N concept pages" or "M repos updated," grep the source entries for the number and verify. Numeric mismatches are dry-run blockers.
    - **No merging across entries without naming them.** A theme that spans multiple entries must name each contributing entry inline.
    - **Uncertainty is a feature.** If an entry is ambiguous, say "ambiguous in source: [[Entry]]" rather than picking one interpretation.
    
    ### 5. Self-check before emitting
    
    Before printing output, verify:
    - Every child in `children:` frontmatter appears exactly once in the Child Entries table.
    - Every entry in the table appears in the `children:` frontmatter.
    - Every numeric claim in Key Outcomes is grep-verifiable against a child entry.
    - The fold ID is deterministic and the file does not already exist (or `--force` is set).
    
    If any check fails, abort and report the specific failure.
    
    ### 6. Emit
    
    **Dry-run**: use Bash `cat <<'EOF' ... EOF` to stdout. Do not use Write. Print the fold ID and a one-line summary of what the commit step would do.
    
    **Commit** (only after user says "commit the fold"):
    1. `Write` the fold page to `wiki/folds/{FOLD-ID}.md`. (PostToolUse hook will auto-commit this.)
    2. `Edit` `wiki/index.md` to add the fold link under a `## Folds` section (create section if missing). (Hook auto-commits.)
    3. `Edit` `wiki/log.md` to prepend one entry:
       ```
       ## [YYYY-MM-DD] fold | batch-exponent-k{K} rollup of N entries
       - Location: wiki/folds/{FOLD-ID}.md
       - Range: {EARLIEST-DATE} to {LATEST-DATE}
       - Children: N log entries
       ```
       (Hook auto-commits.)
    
    Three auto-commits result. The user sees three separate `wiki: auto-commit` entries in git log. This is expected; do not attempt to suppress the hook.
    
    ---
    
    ## Output schema
    
    See `references/fold-template.md` for the canonical frontmatter and body layout.
    
    ---
    
    ## Invariants
    
    1. **Structural idempotency**: same range + same k → same fold ID → duplicate detection prevents double-writes. LLM prose may vary across runs; the *location and scope* are fixed.
    2. **Additive**: children are never modified.
    3. **Bounded reads**: 0-15 child-page reads per fold.
    4. **Extractive**: zero invented facts. Count checks enforced.
    5. **No chaining**: wiki-fold does not invoke wiki-lint, wiki-ingest, autoresearch, or save.
    
    ---
    
    ## What NOT to do
    
    - Do not use Write/Edit during dry-run. Bash stdout only.
    - Do not include the current date in the fold filename or title. Use the child entry range.
    - Do not silently dedupe children by page title. One record per log entry.
    - Do not write "emergent themes" that span entries without naming which entries contribute.
    - Do not claim byte-identical idempotency. Structural idempotency is the actual guarantee.
    - Do not suppress or bypass the PostToolUse auto-commit hook.
    - Do not update `wiki/hot.md`. Ownership stays with save/ingest skills.
    
    ---
    
    ## Reversal
    
    Committed fold reversal (three commits, land in this order):
    1. Remove the log.md fold entry.
    2. Remove the index.md entry.
    3. Delete the fold page file.
    
    Or: `git revert` the three auto-commits. Child pages are untouched in either path.
    
    ---
    
    ## Example dry-run sequence
    
    User: "fold the log, dry-run k=3"
    
    1. Parse `wiki/log.md` top 8 entries.
    2. Build structured children list (8 records).
    3. Read 0-10 referenced pages as needed.
    4. Produce fold ID: `fold-k3-from-2026-04-10-to-2026-04-23-n8`.
    5. Check `wiki/folds/fold-k3-from-2026-04-10-to-2026-04-23-n8.md` does not exist.
    6. Write fold body following the template.
    7. Run self-check (frontmatter/table consistency, count verification).
    8. Emit via `cat <<'EOF' ... EOF` to stdout.
    9. Report: "Dry-run complete. Fold ID: {FOLD-ID}. To commit: 'commit the fold'."
    
  • skills/obsidian-bases/SKILL.mdskill
    Show content (5911 bytes)
    ---
    name: obsidian-bases
    description: "Create and edit Obsidian Bases (.base files): Obsidian's native database layer for dynamic tables, card views, list views, filters, formulas, and summaries over vault notes. Triggers on: create a base, add a base file, obsidian bases, base view, filter notes, formula, database view, dynamic table, task tracker base, reading list base."
    allowed-tools: Read Write
    ---
    
    # obsidian-bases: Obsidian's Database Layer
    
    Obsidian Bases (launched 2025) turns vault notes into queryable, dynamic views. Tables, cards, lists, maps. Defined in `.base` files. No plugin required; it is a core Obsidian feature.
    
    **Authoritative reference**: If the kepano/obsidian-skills plugin is installed, prefer its canonical obsidian-bases skill. Otherwise, use the reference below. Official docs: https://help.obsidian.md/bases/syntax
    
    ---
    
    ## File Format
    
    `.base` files contain valid YAML. The root keys are `filters`, `formulas`, `properties`, `summaries`, and `views`.
    
    ```yaml
    # Global filters: apply to ALL views
    filters:
      and:
        - file.hasTag("wiki")
        - 'status != "archived"'
    
    # Computed properties
    formulas:
      age_days: '(now() - file.ctime).days.round(0)'
      status_icon: 'if(status == "mature", "✅", "🔄")'
    
    # Display name overrides for properties panel
    properties:
      status:
        displayName: "Status"
      formula.age_days:
        displayName: "Age (days)"
    
    # One or more views
    views:
      - type: table
        name: "All Pages"
        order:
          - file.name
          - type
          - status
          - updated
          - formula.age_days
    ```
    
    ---
    
    ## Filters
    
    Filters select which notes appear. Applied globally or per-view.
    
    ```yaml
    # Single string filter
    filters: 'status == "current"'
    
    # AND: all must be true
    filters:
      and:
        - 'status != "archived"'
        - file.hasTag("wiki")
    
    # OR: any can be true
    filters:
      or:
        - file.hasTag("concept")
        - file.hasTag("entity")
    
    # NOT: exclude matches
    filters:
      not:
        - file.inFolder("wiki/meta")
    
    # Nested
    filters:
      and:
        - file.inFolder("wiki/")
        - or:
            - 'type == "concept"'
            - 'type == "entity"'
    ```
    
    ### Filter operators
    
    `==` `!=` `>` `<` `>=` `<=`
    
    ### Useful filter functions
    
    | Function | Example |
    |----------|---------|
    | `file.hasTag("x")` | Notes with tag `x` |
    | `file.inFolder("path/")` | Notes in folder |
    | `file.hasLink("Note")` | Notes linking to Note |
    
    ---
    
    ## Properties
    
    Three types:
    - **Note properties**: from frontmatter: `status`, `type`, `updated`
    - **File properties**: metadata: `file.name`, `file.mtime`, `file.size`, `file.ctime`, `file.tags`, `file.folder`
    - **Formula properties**: computed: `formula.age_days`
    
    ---
    
    ## Formulas
    
    Defined in `formulas:`. Referenced as `formula.name` in `order:` and `properties:`.
    
    ```yaml
    formulas:
      # Days since created
      age_days: '(now() - file.ctime).days.round(0)'
    
      # Days until a date property
      days_until: 'if(due_date, (date(due_date) - today()).days, "")'
    
      # Conditional label
      status_icon: 'if(status == "mature", "✅", if(status == "developing", "🔄", "🌱"))'
    
      # Word count estimate
      word_est: '(file.size / 5).round(0)'
    ```
    
    **Key rule**: Subtracting two dates returns a `Duration`. Not a number. Always access `.days` first:
    ```yaml
    # CORRECT
    age: '(now() - file.ctime).days'
    
    # WRONG: crashes
    age: '(now() - file.ctime).round(0)'
    ```
    
    **Always guard nullable properties with `if()`**:
    ```yaml
    # CORRECT
    days_left: 'if(due_date, (date(due_date) - today()).days, "")'
    ```
    
    ---
    
    ## View Types
    
    ### Table
    ```yaml
    views:
      - type: table
        name: "Wiki Index"
        limit: 100
        order:
          - file.name
          - type
          - status
          - updated
        groupBy:
          property: type
          direction: ASC
    ```
    
    ### Cards
    ```yaml
    views:
      - type: cards
        name: "Gallery"
        order:
          - file.name
          - tags
          - status
    ```
    
    ### List
    ```yaml
    views:
      - type: list
        name: "Quick List"
        order:
          - file.name
          - status
    ```
    
    ---
    
    ## Wiki Vault Templates
    
    ### Wiki content dashboard (all non-meta pages)
    
    ```yaml
    filters:
      and:
        - file.inFolder("wiki/")
        - not:
            - file.inFolder("wiki/meta")
    
    formulas:
      age: '(now() - file.ctime).days.round(0)'
    
    properties:
      formula.age:
        displayName: "Age (days)"
    
    views:
      - type: table
        name: "All Wiki Pages"
        order:
          - file.name
          - type
          - status
          - updated
          - formula.age
        groupBy:
          property: type
          direction: ASC
    ```
    
    ### Entity index (people, orgs, repos)
    
    ```yaml
    filters:
      and:
        - file.inFolder("wiki/entities/")
        - 'file.ext == "md"'
    
    views:
      - type: table
        name: "Entities"
        order:
          - file.name
          - entity_type
          - status
          - updated
        groupBy:
          property: entity_type
          direction: ASC
    ```
    
    ### Recent ingests
    
    ```yaml
    filters:
      and:
        - file.inFolder("wiki/sources/")
    
    views:
      - type: table
        name: "Sources"
        order:
          - file.name
          - source_type
          - created
          - status
        groupBy:
          property: source_type
          direction: ASC
    ```
    
    ---
    
    ## Embedding in Notes
    
    ```markdown
    ![[MyBase.base]]
    
    ![[MyBase.base#View Name]]
    ```
    
    ---
    
    ## Where to Save
    
    Store `.base` files in `wiki/meta/` for vault dashboards:
    - `wiki/meta/dashboard.base`: main content view
    - `wiki/meta/entities.base`: entity tracker
    - `wiki/meta/sources.base`: ingestion log
    
    ---
    
    ## YAML Quoting Rules
    
    - Formulas with double quotes → wrap in single quotes: `'if(done, "Yes", "No")'`
    - Strings with colons or special chars → wrap in double quotes: `"Status: Active"`
    - Unquoted strings with `:` break YAML parsing
    
    ---
    
    ## What Not to Do
    
    - Do not use `from:` or `where:`: those are Dataview syntax, not Obsidian Bases
    - Do not use `sort:` at the root level: sorting is per-view via `order:` and `groupBy:`
    - Do not put `.base` files outside the vault: they only render inside Obsidian
    - Do not reference `formula.X` in `order:` without defining `X` in `formulas:`
    
  • skills/obsidian-markdown/SKILL.mdskill
    Show content (5742 bytes)
    ---
    name: obsidian-markdown
    description: "Write correct Obsidian Flavored Markdown: wikilinks, embeds, callouts, properties, tags, highlights, math, and canvas syntax. Reference this when creating or editing any wiki page. Triggers on: write obsidian note, obsidian syntax, wikilink, callout, embed, obsidian markdown, wikilink format, callout syntax, embed syntax, obsidian formatting, how to write obsidian markdown."
    allowed-tools: Read Write Edit
    ---
    
    # obsidian-markdown: Obsidian Flavored Markdown
    
    Reference this skill when writing any wiki page. Obsidian extends standard Markdown with wikilinks, embeds, callouts, and properties. Getting syntax wrong causes broken links, invisible callouts, or malformed frontmatter.
    
    **Cross-reference**: If the kepano/obsidian-skills plugin is installed, prefer its canonical obsidian-markdown skill for authoritative Obsidian syntax reference. Otherwise, use the reference below. See also [github.com/kepano/obsidian-skills](https://github.com/kepano/obsidian-skills).
    
    ---
    
    ## Wikilinks
    
    Internal links use double brackets. The filename without extension.
    
    | Syntax | What it does |
    |---|---|
    | `[[Note Name]]` | Basic link |
    | `[[Note Name\|Display Text]]` | Aliased link (shows "Display Text") |
    | `[[Note Name#Heading]]` | Link to a specific heading |
    | `[[Note Name#^block-id]]` | Link to a specific block |
    
    Rules:
    - Case-sensitive on some systems. Match the exact filename.
    - No path needed: Obsidian resolves by filename uniqueness.
    - If two files have the same name, use `[[Folder/Note Name]]` to disambiguate.
    
    ---
    
    ## Embeds
    
    Embeds use `!` before the wikilink. They display the content inline.
    
    | Syntax | What it does |
    |---|---|
    | `![[Note Name]]` | Embed a full note |
    | `![[Note Name#Heading]]` | Embed a section |
    | `![[image.png]]` | Embed an image |
    | `![[image.png\|300]]` | Embed image with width 300px |
    | `![[document.pdf]]` | Embed a PDF (Obsidian renders natively) |
    | `![[audio.mp3]]` | Embed audio |
    
    ---
    
    ## Callouts
    
    Callouts are blockquotes with a type keyword. They render as styled alert boxes.
    
    ```markdown
    > [!note]
    > Default informational callout.
    
    > [!note] Custom Title
    > Callout with a custom title.
    
    > [!note]- Collapsible (closed by default)
    > Click to expand.
    
    > [!note]+ Collapsible (open by default)
    > Click to collapse.
    ```
    
    ### All callout types
    
    | Type | Aliases | Use for |
    |------|---------|---------|
    | `note` |: | General notes |
    | `abstract` | `summary`, `tldr` | Summaries |
    | `info` |: | Information |
    | `todo` |: | Action items |
    | `tip` | `hint`, `important` | Tips and highlights |
    | `success` | `check`, `done` | Positive outcomes |
    | `question` | `help`, `faq` | Open questions |
    | `warning` | `caution`, `attention` | Warnings |
    | `failure` | `fail`, `missing` | Errors or failures |
    | `danger` | `error` | Critical issues |
    | `bug` |: | Known bugs |
    | `example` |: | Examples |
    | `quote` | `cite` | Quotations |
    | `contradiction` |: | Conflicting information (wiki convention) |
    
    ---
    
    ## Properties (Frontmatter)
    
    Obsidian renders YAML frontmatter as a Properties panel. Rules:
    
    ```yaml
    ---
    type: concept                    # plain string
    title: "Note Title"              # quoted if it contains special chars
    created: 2026-04-08              # date as YYYY-MM-DD (not ISO datetime)
    updated: 2026-04-08
    tags:
      - tag-one                      # list items use - format
      - tag-two
    status: developing
    related:
      - "[[Other Note]]"             # wikilinks must be quoted in YAML
    sources:
      - "[[source-page]]"
    ---
    ```
    
    Rules:
    - Flat YAML only. Never nest objects.
    - Dates as `YYYY-MM-DD`, not `2026-04-08T00:00:00`.
    - Lists as `- item`, not inline `[a, b, c]`.
    - Wikilinks in YAML must be quoted: `"[[Page]]"`.
    - `tags` field: Obsidian reads this as the tag list, searchable in vault.
    
    ---
    
    ## Tags
    
    Two valid forms:
    
    ```markdown
    #tag-name             : inline tag anywhere in the body
    #parent/child-tag     : nested tag (shows hierarchy in tag pane)
    ```
    
    In frontmatter:
    ```yaml
    tags:
      - research
      - ai/obsidian
    ```
    
    Do not use `#` inside frontmatter tag lists. Just the tag name.
    
    ---
    
    ## Text Formatting
    
    Standard Markdown plus Obsidian extensions:
    
    | Syntax | Result |
    |---|---|
    | `**bold**` | Bold |
    | `*italic*` | Italic |
    | `~~strikethrough~~` | Strikethrough |
    | `==highlight==` | Highlighted text (yellow in Obsidian) |
    | `` `inline code` `` | Inline code |
    
    ---
    
    ## Math
    
    Obsidian uses MathJax/KaTeX:
    
    Inline math:
    ```markdown
    $E = mc^2$
    ```
    
    Block math:
    ```markdown
    $$
    \int_0^\infty e^{-x} dx = 1
    $$
    ```
    
    ---
    
    ## Code Blocks
    
    Standard fenced code blocks. Obsidian highlights all common languages:
    
    ````markdown
    ```python
    def hello():
        return "world"
    ```
    ````
    
    ---
    
    ## Tables
    
    Standard Markdown tables:
    
    ```markdown
    | Column A | Column B | Column C |
    |----------|----------|----------|
    | Value    | Value    | Value    |
    | Value    | Value    | Value    |
    ```
    
    Obsidian renders tables natively. No plugin needed.
    
    ---
    
    ## Mermaid Diagrams
    
    Obsidian renders Mermaid natively:
    
    ````markdown
    ```mermaid
    graph TD
        A[Start] --> B{Decision}
        B -->|Yes| C[End]
        B -->|No| D[Loop]
        D --> A
    ```
    ````
    
    Supported: `graph`, `sequenceDiagram`, `gantt`, `classDiagram`, `pie`, `flowchart`.
    
    ---
    
    ## Footnotes
    
    ```markdown
    This sentence has a footnote.[^1]
    
    [^1]: The footnote text goes here.
    ```
    
    ---
    
    ## What NOT to Do
    
    - Do not use `[link text](path/to/note.md)` for internal links: use `[[Note Name]]` instead.
    - Do not use HTML inside callouts: stick to Markdown.
    - Do not use `##` inside a callout body: headings don't render inside callouts.
    - Do not write `tags: [a, b, c]` inline in frontmatter: Obsidian prefers the list format.
    - Do not write ISO datetimes in frontmatter (`2026-04-08T00:00:00Z`): use `2026-04-08`.
    
  • skills/save/SKILL.mdskill
    Show content (3861 bytes)
    ---
    name: save
    description: >
      Save the current conversation, answer, or insight into the Obsidian wiki vault as a
      structured note. Analyzes the chat, determines the right note type, creates frontmatter,
      files it in the correct wiki folder, and updates index, log, and hot cache.
      Triggers on: "save this", "save that answer", "/save", "file this",
      "save to wiki", "save this session", "file this conversation", "keep this",
      "save this analysis", "add this to the wiki".
    allowed-tools: Read Write Edit Glob Grep
    ---
    
    # save: File Conversations Into the Wiki
    
    Good answers and insights shouldn't disappear into chat history. This skill takes what was just discussed and files it as a permanent wiki page.
    
    The wiki compounds. Save often.
    
    ---
    
    ## Note Type Decision
    
    Determine the best type from the conversation content:
    
    | Type | Folder | Use when |
    |------|--------|---------|
    | synthesis | wiki/questions/ | Multi-step analysis, comparison, or answer to a specific question |
    | concept | wiki/concepts/ | Explaining or defining an idea, pattern, or framework |
    | source | wiki/sources/ | Summary of external material discussed in the session |
    | decision | wiki/meta/ | Architectural, project, or strategic decision that was made |
    | session | wiki/meta/ | Full session summary: captures everything discussed |
    
    If the user specifies a type, use that. If not, pick the best fit based on the content. When in doubt, use `synthesis`.
    
    ---
    
    ## Save Workflow
    
    1. **Scan** the current conversation. Identify the most valuable content to preserve.
    2. **Ask** (if not already named): "What should I call this note?" Keep the name short and descriptive.
    3. **Determine** note type using the table above.
    4. **Extract** all relevant content from the conversation. Rewrite it in declarative present tense (not "the user asked" but the actual content itself).
    5. **Create** the note in the correct folder with full frontmatter.
    6. **Collect links**: identify any wiki pages mentioned in the conversation. Add them to `related` in frontmatter.
    7. **Update** `wiki/index.md`. Add the new entry at the top of the relevant section.
    8. **Append** to `wiki/log.md`. New entry at the TOP:
       ```
       ## [YYYY-MM-DD] save | Note Title
       - Type: [note type]
       - Location: wiki/[folder]/Note Title.md
       - From: conversation on [brief topic description]
       ```
    9. **Update** `wiki/hot.md` to reflect the new addition.
    10. **Confirm**: "Saved as [[Note Title]] in wiki/[folder]/."
    
    ---
    
    ## Frontmatter Template
    
    ```yaml
    ---
    type: <synthesis|concept|source|decision|session>
    title: "Note Title"
    created: YYYY-MM-DD
    updated: YYYY-MM-DD
    tags:
      - <relevant-tag>
    status: developing
    related:
      - "[[Any Wiki Page Mentioned]]"
    sources:
      - "[[.raw/source-if-applicable.md]]"
    ---
    ```
    
    For `question` type, add:
    ```yaml
    question: "The original query as asked."
    answer_quality: solid
    ```
    
    For `decision` type, add:
    ```yaml
    decision_date: YYYY-MM-DD
    status: active
    ```
    
    ---
    
    ## Writing Style
    
    - Declarative, present tense. Write the knowledge, not the conversation.
    - Not: "The user asked about X and Claude explained..."
    - Yes: "X works by doing Y. The key insight is Z."
    - Include all relevant context. Future sessions should be able to read this page cold.
    - Link every mentioned concept, entity, or wiki page with wikilinks.
    - Cite sources where applicable: `(Source: [[Page]])`.
    
    ---
    
    ## What to Save vs. Skip
    
    Save:
    - Non-obvious insights or synthesis
    - Decisions with rationale
    - Analyses that took significant effort
    - Comparisons that are likely to be referenced again
    - Research findings
    
    Skip:
    - Mechanical Q&A (lookup questions with obvious answers)
    - Setup steps already documented elsewhere
    - Temporary debugging sessions with no lasting insight
    - Anything already in the wiki
    
    If it's already in the wiki, update the existing page instead of creating a duplicate.
    
  • skills/autoresearch/SKILL.mdskill
    Show content (7383 bytes)
    ---
    name: autoresearch
    description: >
      Autonomous iterative research loop. Takes a topic, runs web searches, fetches sources,
      synthesizes findings, and files everything into the wiki as structured pages.
      Based on Karpathy's autoresearch pattern: program.md configures objectives and constraints,
      the loop runs until depth is reached, output goes directly into the knowledge base.
      Triggers on: "/autoresearch", "autoresearch", "research [topic]", "deep dive into [topic]",
      "investigate [topic]", "find everything about [topic]", "research and file",
      "go research", "build a wiki on".
    allowed-tools: Read Write Edit Glob Grep WebFetch WebSearch
    ---
    
    # autoresearch: Autonomous Research Loop
    
    You are a research agent. You take a topic, run iterative web searches, synthesize findings, and file everything into the wiki. The user gets wiki pages, not a chat response.
    
    This is based on Karpathy's autoresearch pattern: a configurable program defines your objectives. You run the loop until depth is reached. Output goes into the knowledge base.
    
    ---
    
    ## Before Starting
    
    Read `references/program.md` to load the research objectives and constraints. This file is user-configurable. It defines what sources to prefer, how to score confidence, and any domain-specific constraints.
    
    ---
    
    ## Topic Selection
    
    Three paths to a topic:
    
    ### A. Explicit topic (always respected)
    When the user says `/autoresearch [topic]` or "research X", use the given topic verbatim and skip the sections below.
    
    ### B. Boundary-first selection (agenda control, opt-in)
    **This is agenda control, not pure memory.** DragonScale Memory.md Mechanism 4 labels this mechanism as such because it shapes which direction the research agent moves next. Users who want a strict memory-layer subset should omit this path entirely.
    
    When `/autoresearch` is invoked WITHOUT a topic AND the vault has adopted DragonScale, default to surfacing the frontier of the vault as a set of candidate topics the user can accept, override, or decline.
    
    Feature detection (shell):
    
    ```bash
    if [ -x ./scripts/boundary-score.py ] && [ -d ./.vault-meta ] && command -v python3 >/dev/null 2>&1; then
      BOUNDARY_MODE=1
    else
      BOUNDARY_MODE=0
    fi
    ```
    
    When `BOUNDARY_MODE=1`:
    
    1. Run `./scripts/boundary-score.py --json --top 5`. Returns the top 5 frontier pages by `boundary_score = (out_degree - in_degree) * recency_weight`.
    2. **Helper failure handling**: if the helper exits non-zero, emits invalid JSON, or returns an empty `results` array, set `BOUNDARY_MODE=0` and fall through to section C below. Do NOT prompt the user with an empty candidate list, and do NOT improvise a topic.
    3. Present the candidate list to the user: "Your top frontier pages are: [list]. Research which one? (1-5, or type a topic to override, or say 'cancel' to be asked normally.)"
    4. If the user picks 1-5, use the selected page's title as the topic.
    5. If the user types free text, use that.
    6. If the user cancels or does not choose, fall through to C.
    
    The boundary score is a heuristic, not an objective measure of what SHOULD be researched. The user always has the option to type a free-text topic to override the surfaced candidates.
    
    **Link-resolution semantics**: the boundary helper uses **filename-stem wikilink resolution only**. `[[Foo]]` is counted as an edge to `Foo.md` anywhere in the vault. Aliases declared via frontmatter `aliases:` are **not** parsed. Folder-qualified links (e.g. `[[notes/Foo]]`) are resolved by stem only. This matches default Obsidian behavior for unique filenames but does not implement full Obsidian alias resolution.
    
    ### C. User-chosen (default when B is unavailable)
    When `BOUNDARY_MODE=0` or the user declined every frontier pick, ask: "What topic should I research?"
    
    ---
    
    ## Research Loop
    
    ```
    Input: topic (from Topic Selection, above)
    
    Round 1. Broad search
    1. Decompose topic into 3-5 distinct search angles
    2. For each angle: run 2-3 WebSearch queries
    3. For top 2-3 results per angle: WebFetch the page
    4. Extract from each: key claims, entities, concepts, open questions
    
    Round 2. Gap fill
    5. Identify what's missing or contradicted from Round 1
    6. Run targeted searches for each gap (max 5 queries)
    7. Fetch top results for each gap
    
    Round 3. Synthesis check (optional, if gaps remain)
    8. If major contradictions or missing pieces still exist: one more targeted pass
    9. Otherwise: proceed to filing
    
    Max rounds: 3 (as set in program.md). Stop when depth is reached or max rounds hit.
    ```
    
    ---
    
    ## Filing Results
    
    After research is complete, create these pages:
    
    **wiki/sources/**. One page per major reference found
    - Use source frontmatter (type, source_type, author, date_published, url, confidence, key_claims)
    - Body: summary of the source, what it contributes to the topic
    
    **wiki/concepts/**. One page per significant concept extracted
    - Only create a page if the concept is substantive enough to stand alone
    - Check the index first: update existing concept pages rather than creating duplicates
    
    **wiki/entities/**. One page per significant person, org, or product identified
    - Check the index first: update existing entity pages
    
    **wiki/questions/**. One synthesis page titled "Research: [Topic]"
    - This is the master synthesis. Everything comes together here.
    - Sections: Overview, Key Findings, Entities, Concepts, Contradictions, Open Questions, Sources
    - Full frontmatter with related links to all pages created in this session
    
    ---
    
    ## Synthesis Page Structure
    
    ```markdown
    ---
    type: synthesis
    title: "Research: [Topic]"
    created: YYYY-MM-DD
    updated: YYYY-MM-DD
    tags:
      - research
      - [topic-tag]
    status: developing
    related:
      - "[[Every page created in this session]]"
    sources:
      - "[[wiki/sources/Source 1]]"
      - "[[wiki/sources/Source 2]]"
    ---
    
    # Research: [Topic]
    
    ## Overview
    [2-3 sentence summary of what was found]
    
    ## Key Findings
    - Finding 1 (Source: [[Source Page]])
    - Finding 2 (Source: [[Source Page]])
    - ...
    
    ## Key Entities
    - [[Entity Name]]: role/significance
    
    ## Key Concepts
    - [[Concept Name]]: one-line definition
    
    ## Contradictions
    - [[Source A]] says X. [[Source B]] says Y. [Brief note on which is more credible and why]
    
    ## Open Questions
    - [Question that research didn't fully answer]
    - [Gap that needs more sources]
    
    ## Sources
    - [[Source 1]]: author, date
    - [[Source 2]]: author, date
    ```
    
    ---
    
    ## After Filing
    
    1. Update `wiki/index.md`. Add all new pages to the right sections
    2. Append to `wiki/log.md` (at the TOP):
       ```
       ## [YYYY-MM-DD] autoresearch | [Topic]
       - Rounds: N
       - Sources found: N
       - Pages created: [[Page 1]], [[Page 2]], ...
       - Synthesis: [[Research: Topic]]
       - Key finding: [one sentence]
       ```
    3. Update `wiki/hot.md` with the research summary
    
    ---
    
    ## Report to User
    
    After filing everything:
    
    ```
    Research complete: [Topic]
    
    Rounds: N | Searches: N | Pages created: N
    
    Created:
      wiki/questions/Research: [Topic].md (synthesis)
      wiki/sources/[Source 1].md
      wiki/concepts/[Concept 1].md
      wiki/entities/[Entity 1].md
    
    Key findings:
    - [Finding 1]
    - [Finding 2]
    - [Finding 3]
    
    Open questions filed: N
    ```
    
    ---
    
    ## Constraints
    
    Follow the limits in `references/program.md`:
    - Max rounds (default: 3)
    - Max pages per session (default: 15)
    - Confidence scoring rules
    - Source preference rules
    
    If a constraint conflicts with completeness, respect the constraint and note what was left out in the Open Questions section.
    
  • skills/canvas/SKILL.mdskill
    Show content (9474 bytes)
    ---
    name: canvas
    description: "Visual layer of the wiki. Add images, text cards, PDFs, and wiki pages to Obsidian canvas files with auto-positioning inside zones. Integrates with /banana for image capture. Triggers on: /canvas, canvas new, canvas add image, canvas add text, canvas add pdf, canvas add note, canvas zone, canvas list, canvas from banana, add to canvas, put this on the canvas, open canvas, create canvas."
    allowed-tools: Read Write Edit Glob Grep
    ---
    
    # canvas: Visual Reference Layer
    
    The three knowledge capture layers:
    - `/save` → text synthesis (wiki/questions/, wiki/concepts/)
    - `/autoresearch` → structured knowledge (wiki/sources/, wiki/concepts/)
    - `/canvas` → visual references (wiki/canvases/)
    
    A canvas is a JSON file Obsidian renders as an infinite visual board. This skill reads and writes canvas JSON directly. Read `references/canvas-spec.md` for the full format reference before making any edits. This spec aligns with the [JSON Canvas open standard](https://jsoncanvas.org/). If the kepano/obsidian-skills plugin is installed, its json-canvas skill is the authoritative canvas spec reference. Otherwise, use the guidance below.
    
    ---
    
    ## Default Canvas
    
    `wiki/canvases/main.canvas`
    
    If it does not exist, create it:
    
    ```json
    {
      "nodes": [
        {
          "id": "title",
          "type": "text",
          "text": "# Visual Reference\n\nDrop images, PDFs, and notes here.",
          "x": -400, "y": -300, "width": 400, "height": 120, "color": "6"
        },
        {
          "id": "zone-default",
          "type": "group",
          "label": "General",
          "x": -400, "y": -140, "width": 800, "height": 400, "color": "4"
        }
      ],
      "edges": []
    }
    ```
    
    ---
    
    ## Operations
    
    ### open / status (`/canvas` with no args)
    
    1. Check if `wiki/canvases/main.canvas` exists.
    2. If yes: read it, count nodes by type, list all group node labels (zone names).
       Report: "Canvas has N nodes: X images, Y text cards, Z wiki pages. Zones: [list]"
    3. If no: create it with the starter structure above.
       Report: "Created main.canvas with a General zone."
    4. Tell user: "Open `wiki/canvases/main.canvas` in Obsidian to view."
    
    ---
    
    ### new (`/canvas new [name]`)
    
    1. Slugify the name: lowercase, spaces → hyphens, strip special chars.
    2. Create `wiki/canvases/[slug].canvas` with the starter structure, title updated to `# [Name]`.
    3. Add entry to `wiki/overview.md` under a "## Canvases" subsection (append after the Current State section). Do not modify `wiki/index.md`. It uses a fixed section schema (Domains, Entities, Concepts, Sources, Questions, Comparisons).
    4. Report: "Created wiki/canvases/[slug].canvas"
    
    ---
    
    ### add image (`/canvas add image [path or url]`)
    
    **Resolve the image:**
    - If URL (starts with `http`): download with `curl -sL [url] -o _attachments/images/canvas/[filename]`
      Derive filename from URL path, or use `img-[timestamp].jpg` if unclear.
    - If local path outside vault: `cp [path] _attachments/images/canvas/`
    - If already vault-relative: use as-is.
    
    Create `_attachments/images/canvas/` if it doesn't exist.
    
    **Detect aspect ratio:**
    Use `python3 -c "from PIL import Image; img=Image.open('[path]'); print(img.width, img.height)"` or `identify -format '%w %h' [path]`.
    See `references/canvas-spec.md` for the full aspect ratio → canvas size table (7 ratios including 4:3, 3:4, ultra-wide). Do not use an inline table here. The spec is the single source of truth for sizing.
    
    **Position using auto-layout** (see Auto-Positioning section below).
    
    **Append node to canvas JSON and write.**
    
    Report: "Added [filename] to [zone] zone at position ([x], [y])."
    
    ---
    
    ### add text (`/canvas add text [content]`)
    
    Create a text node:
    ```json
    {
      "id": "text-[timestamp]",
      "type": "text",
      "text": "[content]",
      "x": [auto], "y": [auto],
      "width": 300, "height": 120,
      "color": "4"
    }
    ```
    
    Position using auto-layout. Write and report.
    
    ---
    
    ### add pdf (`/canvas add pdf [path]`)
    
    Same as add image. Obsidian renders PDFs natively as file nodes.
    - Copy to `_attachments/pdfs/canvas/` if outside vault.
    - Fixed size: width=400, height=520.
    - Report page count if you can determine it.
    
    ---
    
    ### add note (`/canvas add note [wiki-page]`)
    
    1. Search `wiki/` for a file matching the page name (case-insensitive, partial match ok).
    2. Use the vault-relative path as the `file` field.
       - Use `"type": "file"` (not `"type": "link"`): `.md` files use file nodes, not link nodes.
       - `"type": "link"` takes a `url: "https://..."`: it is for web URLs only.
    3. Create a file node: width=300, height=100.
    4. Position using auto-layout.
    
    ```json
    {
      "id": "note-[timestamp]",
      "type": "file",
      "file": "wiki/concepts/LLM Wiki Pattern.md",
      "x": [auto], "y": [auto],
      "width": 300, "height": 100
    }
    ```
    
    ---
    
    ### zone (`/canvas zone [name] [color]`)
    
    1. Read canvas JSON.
    2. Find max_y: `max(node.y + node.height for all nodes) + 60`. Use 280 if no nodes (leaves room above the starter title node).
    3. Create a group node:
    
    ```json
    {
      "id": "zone-[slug]",
      "type": "group",
      "label": "[name]",
      "x": -400,
      "y": [max_y],
      "width": 1000,
      "height": 400,
      "color": "[color or '3']"
    }
    ```
    
    Valid colors: `"1"`=red `"2"`=orange `"3"`=yellow `"4"`=green `"5"`=cyan `"6"`=purple
    
    Write and report.
    
    ---
    
    ### list (`/canvas list`)
    
    1. `glob wiki/canvases/*.canvas`
    2. For each canvas: read JSON, count nodes by type.
    3. Report:
    
    ```
    wiki/canvases/main.canvas      . 14 nodes (8 images, 3 text, 2 file, 1 group)
    wiki/canvases/design-ideas.canvas. 42 nodes (30 images, 4 text, 8 groups)
    ```
    
    ---
    
    ### from banana (`/canvas from banana`) (if the banana-claude plugin is installed)
    
    1. Check `wiki/canvases/.recent-images.txt` first (session log of newly written images).
    2. If not found or empty: use `find` with correct precedence (parentheses required. Without them `-newer` only binds to the last `-name` clause):
       ```bash
       python3 -c "import time,os; open('/tmp/ten-min-ago','w').close(); os.utime('/tmp/ten-min-ago',(time.time()-600,time.time()-600))"
       find _attachments/images -newer /tmp/ten-min-ago \( -name "*.png" -o -name "*.jpg" \)
       ```
       Note: `/banana` is an optional external skill not shipped in this plugin. If the user has it installed, the `.recent-images.txt` log will be populated. If not, the `find` command above is the fallback.
    3. If still none: show the 5 most recently modified images.
    4. Present list: "Found N recent images: [list]. Add to canvas? Which zone? (zone name / 'new [name]' / 'skip')"
    5. On confirmation: add each using the add image logic.
    
    ---
    
    ## Auto-Positioning Algorithm
    
    Read `references/canvas-spec.md` for the full coordinate system.
    
    ```python
    def next_position(canvas_nodes, target_zone_label, new_w, new_h):
        # Find zone group node
        zone = next((n for n in canvas_nodes
                     if n.get('type') == 'group'
                     and n.get('label') == target_zone_label), None)
    
        if zone is None:
            # No zone: place below all content
            max_y = max((n['y'] + n.get('height', 0) for n in canvas_nodes), default=-140)
            return -400, max_y + 60
    
        zx, zy = zone['x'], zone['y']
        zw, zh = zone['width'], zone['height']
    
        # Nodes inside this zone
        inside = [n for n in canvas_nodes
                  if n.get('type') != 'group'
                  and zx <= n['x'] < zx + zw
                  and zy <= n['y'] < zy + zh]
    
        if not inside:
            return zx + 20, zy + 20
    
        rightmost_x = max(n['x'] + n.get('width', 0) for n in inside)
        next_x = rightmost_x + 40
    
        if next_x + new_w > zx + zw:
            # New row
            max_row_y = max(n['y'] + n.get('height', 0) for n in inside)
            return zx + 20, max_row_y + 20
    
        # Same row: align to the top of all existing nodes in the zone
        current_row_y = min(n['y'] for n in inside)
        return next_x, current_row_y
    ```
    
    ---
    
    ## ID Generation
    
    Read the canvas, collect all existing IDs. Never reuse one.
    
    Safe ID pattern: `[type]-[content-slug]-[full-unix-timestamp]`
    
    Use the full Unix timestamp (10 digits) to avoid collisions in batch operations.
    
    Examples: `img-cover-1744032823`, `text-note-1744032845`, `zone-branding-1744032901`
    
    If a collision is detected (ID already exists in the canvas), append `-2`, `-3`, etc.
    
    ---
    
    ## Session Log (optional hook)
    
    If `wiki/canvases/.recent-images.txt` exists, append any new image path written to `_attachments/images/` during this session (one path per line, keep last 20).
    
    `/canvas from banana` reads this file first, making it instant without filesystem search.
    
    ---
    
    ## Banana Integration (if the banana-claude plugin is installed)
    
    After any `/banana` run in the same session, if the user says "add to canvas" or "put on canvas", treat it as `/canvas from banana`.
    
    When `/banana` finishes generating images, suggest:
    > "Add generated images to canvas? Run `/canvas from banana`"
    
    ---
    
    ## Summary
    
    1. Read canvas-spec.md before editing any canvas JSON.
    2. Always read the canvas file before writing. Parse existing nodes to avoid ID collisions and calculate auto-positions.
    3. Create `_attachments/images/canvas/` for downloaded/copied images.
    4. Update `wiki/index.md` when creating new canvases.
    5. Report position and zone after every add operation.
    
    ## See Also
    
    For standalone visual production (12 templates, 6 layout algorithms, AI generation,
    presentations), see [claude-canvas](https://github.com/AgriciDaniel/claude-canvas).
    This skill handles wiki-scoped visual boards. claude-canvas handles full-featured
    canvas orchestration for any project.
    
  • skills/defuddle/SKILL.mdskill
    Show content (2616 bytes)
    ---
    name: defuddle
    description: "Strip clutter from web pages before ingesting into the wiki. Removes ads, navigation, headers, footers, and boilerplate: leaving clean readable markdown that saves 40-60% tokens. Triggers on: defuddle, clean this page, strip this url, fetch and clean, clean web content before ingesting, strip ads, remove clutter, clean URL content, readable markdown from URL."
    allowed-tools: Read Bash
    ---
    
    # defuddle: Web Page Cleaner
    
    Defuddle extracts the meaningful content from a web page and drops everything else: ads, cookie banners, nav bars, related articles, footers, social sharing buttons. What remains is the article body as clean markdown.
    
    Use this before any URL ingestion. It is optional but strongly recommended. It cuts token usage by 40-60% on typical web articles and produces cleaner wiki pages.
    
    ---
    
    ## Install
    
    ```bash
    npm install -g defuddle-cli
    ```
    
    Verify: `defuddle --version`
    
    ---
    
    ## Usage
    
    ### Clean a URL directly
    ```bash
    defuddle https://example.com/article
    ```
    Outputs clean markdown to stdout.
    
    ### Save to .raw/
    ```bash
    defuddle https://example.com/article > .raw/articles/article-slug-$(date +%Y-%m-%d).md
    ```
    
    ### Add frontmatter header after saving
    After running defuddle, prepend the source URL and fetch date:
    ```bash
    SLUG="article-slug-$(date +%Y-%m-%d)"
    { echo "---"; echo "source_url: https://example.com/article"; echo "fetched: $(date +%Y-%m-%d)"; echo "---"; echo ""; defuddle https://example.com/article; } > .raw/articles/$SLUG.md
    ```
    
    ### Clean a local HTML file
    ```bash
    defuddle page.html
    ```
    
    ---
    
    ## When to Use
    
    **Use defuddle when:**
    - Ingesting a news article, blog post, or documentation page from a URL
    - The page has a lot of surrounding content (most web pages do)
    - You want to stay within token budget on a long article
    
    **Skip defuddle when:**
    - The source is already a clean markdown or PDF file
    - The page is a dashboard, app, or structured data (defuddle expects article-style content)
    - defuddle is not installed and the article is short enough to process raw
    
    ---
    
    ## Fallback
    
    If defuddle is not installed, check:
    
    ```bash
    which defuddle 2>/dev/null || echo "not installed"
    ```
    
    If not installed: use WebFetch directly. The content will be less clean but still workable.
    
    ---
    
    ## Integration with /wiki-ingest
    
    The `/wiki-ingest` skill checks for defuddle automatically when a URL is passed. You do not need to run defuddle manually before ingesting a URL. The ingest skill will call it if available.
    
    To manually clean a page and save before ingesting:
    1. Run the save command above
    2. Then: `ingest .raw/articles/[slug].md`
    
  • .claude-plugin/marketplace.jsonmarketplace
    Show content (1157 bytes)
    {
      "name": "claude-obsidian-marketplace",
      "owner": {
        "name": "AgriciDaniel",
        "url": "https://github.com/AgriciDaniel"
      },
      "metadata": {
        "description": "claude-obsidian: Claude + Obsidian knowledge companion by AgriciDaniel",
        "version": "1.6.0"
      },
      "plugins": [
        {
          "name": "claude-obsidian",
          "source": {
            "source": "github",
            "repo": "AgriciDaniel/claude-obsidian",
            "ref": "main"
          },
          "description": "Claude + Obsidian knowledge companion. Sets up a persistent, compounding wiki vault. Covers memory management, session notetaking, knowledge organization, and agent context across projects. Optional DragonScale Memory extension adds hierarchical log folds, deterministic page addresses, embedding-based semantic tiling lint, and boundary-first autoresearch topic selection.",
          "version": "1.6.0",
          "author": {
            "name": "AgriciDaniel",
            "url": "https://github.com/AgriciDaniel"
          },
          "homepage": "https://github.com/AgriciDaniel/claude-obsidian",
          "repository": "https://github.com/AgriciDaniel/claude-obsidian",
          "license": "MIT"
        }
      ]
    }
    

README

claude-obsidian

claude-obsidian

GitHub stars License: MIT Claude Code Blog Post

Claude + Obsidian knowledge companion. A running notetaker that builds and maintains a persistent, compounding wiki vault. Every source you add gets integrated. Every question you ask pulls from everything that has been read. Knowledge compounds like interest.

Based on Andrej Karpathy's LLM Wiki pattern. 11 skills. Zero manual filing. Multi-agent support. Optional DragonScale Memory extension (log folds, deterministic page addresses, semantic tiling lint, boundary-first autoresearch).


What It Does

Youtube Demo

Welcome canvas. Visual demo board

You drop sources. Claude reads them, extracts entities and concepts, updates cross-references, and files everything into a structured Obsidian vault. The wiki gets richer with every ingest.

You ask questions. Claude reads the hot cache (recent context), scans the index, drills into relevant pages, and synthesizes an answer. It cites specific wiki pages, not training data.

You lint. Claude finds orphans, dead links, stale claims, and missing cross-references. Your wiki stays healthy without manual cleanup.

At the end of every session, Claude updates a hot cache. The next session starts with full recent context, no recap needed.

Graph view. Color-coded wiki nodes Wiki Map canvas


Why claude-obsidian?

Most Obsidian AI plugins are chat interfaces - they answer questions about your existing notes. claude-obsidian is a knowledge engine - it creates, organizes, maintains, and evolves your notes autonomously.

Capabilityclaude-obsidianSmart ConnectionsCopilot
Auto-organize notesCreates entities, concepts, cross-referencesNoNo
Contradiction flagging[!contradiction] callouts with sourcesNoNo
Session memoryHot cache persists between conversationsNoNo
Vault maintenance8-category lint (orphans, dead links, gaps)NoNo
Autonomous research3-round web research with gap-fillingNoNo
Multi-model supportClaude, Gemini, Codex, Cursor, WindsurfClaude onlyMultiple
Visual canvasVia claude-canvas companionNoNo
Query with citationsCites specific wiki pagesCites similar notesCites notes
Batch ingestionParallel agents for multiple sourcesNoNo
Open sourceMITMITFreemium

Deep dive: I Turned Obsidian Into a Self-Organizing AI Brain - full breakdown with data visualizations, market context, and workflow demos.


Quick Start

Option 1: Clone as vault (recommended: full setup in 2 minutes)

git clone https://github.com/AgriciDaniel/claude-obsidian
cd claude-obsidian
bash bin/setup-vault.sh

Open the folder in Obsidian: Manage Vaults → Open folder as vault → select claude-obsidian/

Open Claude Code in the same folder. Type /wiki.

setup-vault.sh configures graph.json (filter + colors), app.json (excludes plugin dirs), and appearance.json (enables CSS). Run it once before the first Obsidian open. You get the fully pre-configured graph view, color scheme, and wiki structure out of the box.


Option 2: Install as Claude Code plugin

Plugin installation is a two-step process in Claude Code. First add the marketplace catalog, then install the plugin from it.

# Step 1: add the marketplace
claude plugin marketplace add AgriciDaniel/claude-obsidian

# Step 2: install the plugin
claude plugin install claude-obsidian@claude-obsidian-marketplace

In any Claude Code session: /wiki. Claude walks you through vault setup.

To check it worked:

claude plugin list

Option 3: Add to an existing vault

Copy WIKI.md into your vault root. Paste into Claude:

Read WIKI.md in this project. Then:
1. Check if Obsidian is installed. If not, install it.
2. Check if the Local REST API plugin is running on port 27124.
3. Configure the MCP server.
4. Ask me ONE question: "What is this vault for?"
Then scaffold the full wiki structure.

Commands

You sayClaude does
/wikiSetup check, scaffold, or continue where you left off
ingest [file]Read source, create 8-15 wiki pages, update index and log
ingest all of theseBatch process multiple sources, then cross-reference
what do you know about X?Read index > relevant pages > synthesize answer
/saveFile the current conversation as a wiki note
/save [name]Save with a specific title (skips the naming question)
/autoresearch [topic]Run the autonomous research loop: search, fetch, synthesize, file
/canvasOpen or create the visual canvas, list zones and nodes
/canvas add image [path]Add an image (URL or local path) to the canvas with auto-layout
/canvas add text [content]Add a markdown text card to the canvas
/canvas add pdf [path]Add a PDF document as a rendered preview node
/canvas add note [page]Pin a wiki page as a linked card on the canvas
/canvas zone [name]Add a new labeled zone to organize visual content
/canvas from bananaCapture recently generated images onto the canvas
lint the wikiHealth check: orphans, dead links, gaps, suggestions
update hot cacheRefresh hot.md with latest context summary

Want more? claude-canvas adds 12 templates, 6 layout algorithms, AI image generation, presentations, and full canvas orchestration. Install both — they complement each other.


Cross-Project Power Move

Point any Claude Code project at this vault. Add to that project's CLAUDE.md:

## Wiki Knowledge Base
Path: ~/path/to/vault

When you need context not already in this project:
1. Read wiki/hot.md first (recent context cache)
2. If not enough, read wiki/index.md
3. If you need domain details, read the relevant domain sub-index
4. Only then drill into specific wiki pages

Do NOT read the wiki for general coding questions or tasks unrelated to [domain].

Your executive assistant, coding projects, and content workflows all draw from the same knowledge base.


Six Wiki Modes

ModeUse when
A: WebsiteSitemap, content audit, SEO wiki
B: GitHubCodebase map, architecture wiki
C: BusinessProject wiki, competitive intelligence
D: PersonalSecond brain, goals, journal synthesis
E: ResearchPapers, concepts, thesis
F: Book/CourseChapter tracker, course notes

Modes can be combined.


What Gets Created

A typical scaffold creates:

  • Folder structure for your chosen mode
  • wiki/index.md: master catalog
  • wiki/log.md: append-only operation log
  • wiki/hot.md: recent context cache
  • wiki/overview.md: executive summary
  • wiki/meta/dashboard.base: Bases dashboard (primary, native Obsidian)
  • wiki/meta/dashboard.md: Legacy Dataview dashboard (optional fallback)
  • _templates/: Obsidian Templater templates for each note type
  • .obsidian/snippets/vault-colors.css: color-coded file explorer
  • Vault CLAUDE.md: auto-loaded project instructions

MCP Setup (Optional)

MCP lets Claude read and write vault notes directly without copy-paste.

Option A (REST API based):

  1. Install the Local REST API plugin in Obsidian
  2. Copy your API key
  3. Run:
claude mcp add-json obsidian-vault '{
  "type": "stdio",
  "command": "uvx",
  "args": ["mcp-obsidian"],
  "env": {
    "OBSIDIAN_API_KEY": "your-key",
    "OBSIDIAN_HOST": "127.0.0.1",
    "OBSIDIAN_PORT": "27124",
    "NODE_TLS_REJECT_UNAUTHORIZED": "0"
  }
}' --scope user

Option B (filesystem based, no plugin needed):

claude mcp add-json obsidian-vault '{
  "type": "stdio",
  "command": "npx",
  "args": ["-y", "@bitbonsai/mcpvault@latest", "/path/to/your/vault"]
}' --scope user

Plugins

Core Plugins (built into Obsidian: no install needed)

PluginPurpose
BasesPowers wiki/meta/dashboard.base: native database views. Available since Obsidian v1.9.10 (August 2025). Replaces Dataview for the primary dashboard.
PropertiesVisual frontmatter editor
Backlinks, Outline, Graph viewStandard navigation

Pre-installed Community Plugins (ship with this vault)

Enable in Settings → Community Plugins → enable:

PluginPurposeNotes
CalendarRight-sidebar calendar with word count + task dotsPre-installed
ThinoQuick memo capture panelPre-installed
ExcalidrawFreehand drawing canvas, annotate imagesPre-installed*
BannersNotion-style header image via banner: frontmatterPre-installed

* Excalidraw main.js (8MB) is downloaded automatically by setup-vault.sh. It is not tracked in git.

Also install from Community Plugins (not pre-installed)

PluginPurpose
TemplaterAuto-fills frontmatter from _templates/
Obsidian GitAuto-commits vault every 15 minutes
Dataview (optional/legacy)Only needed for the legacy wiki/meta/dashboard.md queries. The primary dashboard now uses Bases.

Also install the Obsidian Web Clipper browser extension. Sends web pages to .raw/ in one click.


CSS Snippets (auto-enabled by setup-vault.sh)

Three snippets ship with the vault and are enabled automatically:

SnippetEffect
vault-colorsColor-codes wiki/ folders by type in the file explorer (blue = concepts, green = sources, purple = entities)
ITS-Dataview-CardsTurns Dataview TABLE queries into visual card grids: use ```dataviewjs with .cards class
ITS-Image-AdjustmentsFine-grained image sizing in notes: append |100 to any image embed

Banner Plugin

Add to any wiki page frontmatter:

banner: "_attachments/images/your-image.png"
banner_icon: "🧠"

The page renders a full-width header image in Obsidian. Works great for hub pages and overviews.


File Structure

claude-obsidian/
├── .claude-plugin/
│   ├── plugin.json              # manifest
│   └── marketplace.json         # distribution
├── skills/
│   ├── wiki/                    # orchestrator + references (7 ref files)
│   ├── wiki-ingest/             # INGEST operation
│   ├── wiki-query/              # QUERY operation
│   ├── wiki-lint/               # LINT operation
│   ├── save/                    # /save: file conversations to wiki
│   ├── autoresearch/            # /autoresearch: autonomous research loop
│   │   └── references/
│   │       └── program.md       # configurable research objectives
│   └── canvas/                  # /canvas: visual layer (images, PDFs, notes)
│       └── references/
│           └── canvas-spec.md   # Obsidian canvas JSON format reference
├── agents/
│   ├── wiki-ingest.md           # parallel ingestion agent
│   └── wiki-lint.md             # health check agent
├── commands/
│   ├── wiki.md                  # /wiki bootstrap command
│   ├── save.md                  # /save command
│   ├── autoresearch.md          # /autoresearch command
│   └── canvas.md                # /canvas visual layer command
├── hooks/
│   └── hooks.json               # SessionStart + Stop hot cache hooks
├── _templates/                  # Obsidian Templater templates
├── wiki/
│   ├── Wiki Map.canvas          # visual hub, central graph node
│   ├── canvases/                # welcome.canvas + main.canvas (visual demos)
│   ├── getting-started.md       # onboarding walkthrough (inside the vault)
│   ├── concepts/                # seeded: LLM Wiki Pattern, Hot Cache, Compounding Knowledge
│   ├── entities/                # seeded: Andrej Karpathy
│   ├── sources/                 # populated by your first ingest
│   └── meta/
│       ├── dashboard.base       # Bases dashboard (primary)
│       └── dashboard.md         # Legacy Dataview dashboard (optional)
├── .raw/                        # source documents (hidden in Obsidian)
├── .obsidian/snippets/          # vault-colors.css (3-color scheme)
├── WIKI.md                      # full schema reference
├── CLAUDE.md                    # project instructions
└── README.md                    # this file

AutoResearch: program.md

The /autoresearch command is configurable. Edit skills/autoresearch/references/program.md to control:

  • What sources to prefer (academic, official docs, news)
  • Confidence scoring rules
  • Max rounds and max pages per session
  • Domain-specific constraints

The default program works for general research. Override it for your domain. A medical researcher would add "prefer PubMed". A business analyst would add "focus on market data and filings".


Seed Vault

This repo ships with a seeded vault. Open it in Obsidian and you'll see:

  • wiki/concepts/: LLM Wiki Pattern, Hot Cache, Compounding Knowledge
  • wiki/entities/: Andrej Karpathy
  • wiki/sources/: empty until your first ingest
  • wiki/meta/dashboard.base: Bases dashboard (works in any Obsidian v1.9.10+)
  • wiki/meta/dashboard.md: Legacy Dataview dashboard (optional fallback)

The graph view will show a connected cluster of 5 pages. This is what the wiki looks like after one ingest. Add more sources and it grows from there.

Knowledge graph growing Workflow loop


Companion: claude-canvas

For the visual layer, claude-canvas adds AI-orchestrated canvas creation - knowledge graphs, presentations, flowcharts, mood boards with 12 templates and 6 layout algorithms. Auto-detects claude-obsidian vaults.

claude plugin install AgriciDaniel/claude-canvas

Community


Based on Andrej Karpathy's LLM Wiki pattern. Built by Agrici Daniel.