$npx -y skills add AgriciDaniel/claude-obsidian --skill obsidian-basesCreate 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 vi
| 1 | # obsidian-bases: Obsidian's Database Layer |
| 2 | |
| 3 | 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. |
| 4 | |
| 5 | **Substrate preference (v1.7+)**: This skill is a self-contained fallback. **Prefer `kepano/obsidian-skills`** as the authoritative substrate — its `obsidian-bases` skill is the canonical reference for Bases YAML, formulas, and view definitions. If you see an `obsidian-bases` skill available without the `claude-obsidian:` namespace, that is kepano's version: use it. The reference below is provided so the plugin remains functional when kepano's marketplace is not installed. Install: `claude plugin marketplace add kepano/obsidian-skills`. Official Bases docs: https://help.obsidian.md/bases/syntax |
| 6 | |
| 7 | --- |
| 8 | |
| 9 | ## File Format |
| 10 | |
| 11 | `.base` files contain valid YAML. The root keys are `filters`, `formulas`, `properties`, `summaries`, and `views`. |
| 12 | |
| 13 | ```yaml |
| 14 | # Global filters: apply to ALL views |
| 15 | filters: |
| 16 | and: |
| 17 | - file.hasTag("wiki") |
| 18 | - 'status != "archived"' |
| 19 | |
| 20 | # Computed properties |
| 21 | formulas: |
| 22 | age_days: '(now() - file.ctime).days.round(0)' |
| 23 | status_icon: 'if(status == "mature", "✅", "🔄")' |
| 24 | |
| 25 | # Display name overrides for properties panel |
| 26 | properties: |
| 27 | status: |
| 28 | displayName: "Status" |
| 29 | formula.age_days: |
| 30 | displayName: "Age (days)" |
| 31 | |
| 32 | # One or more views |
| 33 | views: |
| 34 | - type: table |
| 35 | name: "All Pages" |
| 36 | order: |
| 37 | - file.name |
| 38 | - type |
| 39 | - status |
| 40 | - updated |
| 41 | - formula.age_days |
| 42 | ``` |
| 43 | |
| 44 | --- |
| 45 | |
| 46 | ## Filters |
| 47 | |
| 48 | Filters select which notes appear. Applied globally or per-view. |
| 49 | |
| 50 | ```yaml |
| 51 | # Single string filter |
| 52 | filters: 'status == "current"' |
| 53 | |
| 54 | # AND: all must be true |
| 55 | filters: |
| 56 | and: |
| 57 | - 'status != "archived"' |
| 58 | - file.hasTag("wiki") |
| 59 | |
| 60 | # OR: any can be true |
| 61 | filters: |
| 62 | or: |
| 63 | - file.hasTag("concept") |
| 64 | - file.hasTag("entity") |
| 65 | |
| 66 | # NOT: exclude matches |
| 67 | filters: |
| 68 | not: |
| 69 | - file.inFolder("wiki/meta") |
| 70 | |
| 71 | # Nested |
| 72 | filters: |
| 73 | and: |
| 74 | - file.inFolder("wiki/") |
| 75 | - or: |
| 76 | - 'type == "concept"' |
| 77 | - 'type == "entity"' |
| 78 | ``` |
| 79 | |
| 80 | ### Filter operators |
| 81 | |
| 82 | `==` `!=` `>` `<` `>=` `<=` |
| 83 | |
| 84 | ### Useful filter functions |
| 85 | |
| 86 | | Function | Example | |
| 87 | |----------|---------| |
| 88 | | `file.hasTag("x")` | Notes with tag `x` | |
| 89 | | `file.inFolder("path/")` | Notes in folder | |
| 90 | | `file.hasLink("Note")` | Notes linking to Note | |
| 91 | |
| 92 | --- |
| 93 | |
| 94 | ## Properties |
| 95 | |
| 96 | Three types: |
| 97 | - **Note properties**: from frontmatter: `status`, `type`, `updated` |
| 98 | - **File properties**: metadata: `file.name`, `file.mtime`, `file.size`, `file.ctime`, `file.tags`, `file.folder` |
| 99 | - **Formula properties**: computed: `formula.age_days` |
| 100 | |
| 101 | --- |
| 102 | |
| 103 | ## Formulas |
| 104 | |
| 105 | Defined in `formulas:`. Referenced as `formula.name` in `order:` and `properties:`. |
| 106 | |
| 107 | ```yaml |
| 108 | formulas: |
| 109 | # Days since created |
| 110 | age_days: '(now() - file.ctime).days.round(0)' |
| 111 | |
| 112 | # Days until a date property |
| 113 | days_until: 'if(due_date, (date(due_date) - today()).days, "")' |
| 114 | |
| 115 | # Conditional label |
| 116 | status_icon: 'if(status == "mature", "✅", if(status == "developing", "🔄", "🌱"))' |
| 117 | |
| 118 | # Word count estimate |
| 119 | word_est: '(file.size / 5).round(0)' |
| 120 | ``` |
| 121 | |
| 122 | **Key rule**: Subtracting two dates returns a `Duration`. Not a number. Always access `.days` first: |
| 123 | ```yaml |
| 124 | # CORRECT |
| 125 | age: '(now() - file.ctime).days' |
| 126 | |
| 127 | # WRONG: crashes |
| 128 | age: '(now() - file.ctime).round(0)' |
| 129 | ``` |
| 130 | |
| 131 | **Always guard nullable properties with `if()`**: |
| 132 | ```yaml |
| 133 | # CORRECT |
| 134 | days_left: 'if(due_date, (date(due_date) - today()).days, "")' |
| 135 | ``` |
| 136 | |
| 137 | --- |
| 138 | |
| 139 | ## View Types |
| 140 | |
| 141 | ### Table |
| 142 | ```yaml |
| 143 | views: |
| 144 | - type: table |
| 145 | name: "Wiki Index" |
| 146 | limit: 100 |
| 147 | order: |
| 148 | - file.name |
| 149 | - type |
| 150 | - status |
| 151 | - updated |
| 152 | groupBy: |
| 153 | property: type |
| 154 | direction: ASC |
| 155 | ``` |
| 156 | |
| 157 | ### Cards |
| 158 | ```yaml |
| 159 | views: |
| 160 | - type: cards |
| 161 | name: "Gallery" |
| 162 | order: |
| 163 | - file.name |
| 164 | - tags |
| 165 | - status |
| 166 | ``` |
| 167 | |
| 168 | ### List |
| 169 | ```yaml |
| 170 | views: |
| 171 | - type: list |
| 172 | name: "Quick List" |
| 173 | order: |
| 174 | - file.name |
| 175 | - status |
| 176 | ``` |
| 177 | |
| 178 | --- |
| 179 | |
| 180 | ## Wiki Vault Templates |
| 181 | |
| 182 | ### Wiki content dashboard (all non-meta pages) |
| 183 | |
| 184 | ```yaml |
| 185 | filters: |
| 186 | and: |
| 187 | - file.inFolder("wiki/") |
| 188 | - not: |
| 189 | - file.inFolder("wiki/meta") |
| 190 | |
| 191 | formulas: |
| 192 | age: '(now() - file.ctime).days.round(0)' |
| 193 | |
| 194 | properties: |
| 195 | formula.age: |
| 196 | displayName: "Age (days)" |
| 197 | |
| 198 | views: |
| 199 | - type: table |
| 200 | name: "All Wiki Pages" |
| 201 | order: |
| 202 | - file.name |
| 203 | - type |
| 204 | - status |
| 205 | - updated |
| 206 | - formula.age |
| 207 | groupBy: |
| 208 | property: type |
| 209 | direction: ASC |
| 210 | ``` |
| 211 | |
| 212 | ### Entity index (people, orgs, repos) |
| 213 | |
| 214 | ```yaml |
| 215 | filters: |
| 216 | and: |
| 217 | - file.inFolder("wiki/entities/") |
| 218 | - 'file.ext == "md"' |
| 219 | |
| 220 | views: |
| 221 | - type: table |
| 222 | name: "Entities" |
| 223 | order: |
| 224 | - file.name |