--- name: obsidian-bases category: document-processing description: Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries. Use when working with .base files, creating database-like views of notes, or when the user mentions Bases, table views, card views, filters, or formulas in Obsidian. --- # Obsidian Bases This skill enables Claude Code to create and edit valid Obsidian Bases (`.base` files) including views, filters, formulas, and all related configurations. ## Overview Obsidian Bases are YAML-based files that define dynamic views of notes in an Obsidian vault. A Base file can contain multiple views, global filters, formulas, property configurations, and custom summaries. ## When to Use This Skill - Creating database-like views of notes in Obsidian - Building task trackers, reading lists, or project dashboards - Filtering and organizing notes by properties or tags - Creating calculated/formula fields - Setting up table, card, list, or map views - Working with .base files in an Obsidian vault ## File Format Base files use the `.base` extension and contain valid YAML. They can also be embedded in Markdown code blocks. ## Complete Schema ```yaml # Global filters apply to ALL views in the base filters: # Can be a single filter string # OR a recursive filter object with and/or/not and: [] or: [] not: [] # Define formula properties that can be used across all views formulas: formula_name: 'expression' # Configure display names and settings for properties properties: property_name: displayName: "Display Name" formula.formula_name: displayName: "Formula Display Name" file.ext: displayName: "Extension" # Define custom summary formulas summaries: custom_summary_name: 'values.mean().round(3)' # Define one or more views views: - type: table | cards | list | map name: "View Name" limit: 10 # Optional: limit results groupBy: # Optional: group results property: property_name direction: ASC | DESC filters: # View-specific filters and: [] order: # Properties to display in order - file.name - property_name - formula.formula_name summaries: # Map properties to summary formulas property_name: Average ``` ## Filter Syntax Filters narrow down results. They can be applied globally or per-view. ### Filter Structure ```yaml # Single filter filters: 'status == "done"' # AND - all conditions must be true filters: and: - 'status == "done"' - 'priority > 3' # OR - any condition can be true filters: or: - file.hasTag("book") - file.hasTag("article") # NOT - exclude matching items filters: not: - file.hasTag("archived") # Nested filters filters: or: - file.hasTag("tag") - and: - file.hasTag("book") - file.hasLink("Textbook") - not: - file.hasTag("book") - file.inFolder("Required Reading") ``` ### Filter Operators | Operator | Description | |----------|-------------| | `==` | equals | | `!=` | not equal | | `>` | greater than | | `<` | less than | | `>=` | greater than or equal | | `<=` | less than or equal | | `&&` | logical and | | `\|\|` | logical or | | `!` | logical not | ## Properties ### Three Types of Properties 1. **Note properties** - From frontmatter: `note.author` or just `author` 2. **File properties** - File metadata: `file.name`, `file.mtime`, etc. 3. **Formula properties** - Computed values: `formula.my_formula` ### File Properties Reference | Property | Type | Description | |----------|------|-------------| | `file.name` | String | File name | | `file.basename` | String | File name without extension | | `file.path` | String | Full path to file | | `file.folder` | String | Parent folder path | | `file.ext` | String | File extension | | `file.size` | Number | File size in bytes | | `file.ctime` | Date | Created time | | `file.mtime` | Date | Modified time | | `file.tags` | List | All tags in file | | `file.links` | List | Internal links in file | | `file.backlinks` | List | Files linking to this file | | `file.embeds` | List | Embeds in the note | | `file.properties` | Object | All frontmatter properties | ### The `this` Keyword - In main content area: refers to the base file itself - When embedded: refers to the embedding file - In sidebar: refers to the active file in main content ## Formula Syntax Formulas compute values from properties. Defined in the `formulas` section. ```yaml formulas: # Simple arithmetic total: "price * quantity" # Conditional logic status_icon: 'if(done, "check", "pending")' # String formatting formatted_price: 'if(price, price.toFixed(2) + " dollars")' # Date formatting created: 'file.ctime.format("YYYY-MM-DD")' # Complex expressions days_old: '((now() - file.ctime) / 86400000).round(0)' ``` ## Functions Reference ### Global Functions | Function | Signature | Description | |----------|-----------|-------------| | `date()` | `date(string): date` | Parse string to date | | `duration()` | `duration(string): duration` | Parse duration string | | `now()` | `now(): date` | Current date and time | | `today()` | `today(): date` | Current date (time = 00:00:00) | | `if()` | `if(condition, trueResult, falseResult?)` | Conditional | | `min()` | `min(n1, n2, ...): number` | Smallest number | | `max()` | `max(n1, n2, ...): number` | Largest number | | `number()` | `number(any): number` | Convert to number | | `link()` | `link(path, display?): Link` | Create a link | | `list()` | `list(element): List` | Wrap in list if not already | | `file()` | `file(path): file` | Get file object | | `image()` | `image(path): image` | Create image for rendering | | `icon()` | `icon(name): icon` | Lucide icon by name | | `html()` | `html(string): html` | Render as HTML | | `escapeHTML()` | `escapeHTML(string): string` | Escape HTML characters | ### Date Functions & Fields **Fields:** `date.year`, `date.month`, `date.day`, `date.hour`, `date.minute`, `date.second`, `date.millisecond` | Function | Signature | Description | |----------|-----------|-------------| | `date()` | `date.date(): date` | Remove time portion | | `format()` | `date.format(string): string` | Format with Moment.js pattern | | `time()` | `date.time(): string` | Get time as string | | `relative()` | `date.relative(): string` | Human-readable relative time | | `isEmpty()` | `date.isEmpty(): boolean` | Always false for dates | ### Date Arithmetic ```yaml # Duration units: y/year/years, M/month/months, d/day/days, # w/week/weeks, h/hour/hours, m/minute/minutes, s/second/seconds # Add/subtract durations "date + \"1M\"" # Add 1 month "date - \"2h\"" # Subtract 2 hours "now() + \"1 day\"" # Tomorrow "today() + \"7d\"" # A week from today # Subtract dates for millisecond difference "now() - file.ctime" # Complex duration arithmetic "now() + (duration('1d') * 2)" ``` ### String Functions **Field:** `string.length` | Function | Description | |----------|-------------| | `contains(value)` | Check substring | | `containsAll(...values)` | All substrings present | | `containsAny(...values)` | Any substring present | | `startsWith(query)` | Starts with query | | `endsWith(query)` | Ends with query | | `isEmpty()` | Empty or not present | | `lower()` | To lowercase | | `title()` | To Title Case | | `trim()` | Remove whitespace | | `replace(pattern, replacement)` | Replace pattern | | `repeat(count)` | Repeat string | | `reverse()` | Reverse string | | `slice(start, end?)` | Substring | | `split(separator, n?)` | Split to list | ### Number Functions | Function | Description | |----------|-------------| | `abs()` | Absolute value | | `ceil()` | Round up | | `floor()` | Round down | | `round(digits?)` | Round to digits | | `toFixed(precision)` | Fixed-point notation | | `isEmpty()` | Not present | ### List Functions **Field:** `list.length` | Function | Description | |----------|-------------| | `contains(value)` | Element exists | | `containsAll(...values)` | All elements exist | | `containsAny(...values)` | Any element exists | | `filter(expression)` | Filter by condition (uses `value`, `index`) | | `map(expression)` | Transform elements (uses `value`, `index`) | | `reduce(expression, initial)` | Reduce to single value (uses `value`, `index`, `acc`) | | `flat()` | Flatten nested lists | | `join(separator)` | Join to string | | `reverse()` | Reverse order | | `slice(start, end?)` | Sublist | | `sort()` | Sort ascending | | `unique()` | Remove duplicates | | `isEmpty()` | No elements | ### File Functions | Function | Description | |----------|-------------| | `asLink(display?)` | Convert to link | | `hasLink(otherFile)` | Has link to file | | `hasTag(...tags)` | Has any of the tags | | `hasProperty(name)` | Has property | | `inFolder(folder)` | In folder or subfolder | ## View Types ### Table View ```yaml views: - type: table name: "My Table" order: - file.name - status - due_date summaries: price: Sum count: Average ``` ### Cards View ```yaml views: - type: cards name: "Gallery" order: - file.name - cover_image - description ``` ### List View ```yaml views: - type: list name: "Simple List" order: - file.name - status ``` ### Map View Requires latitude/longitude properties and the Maps plugin. ```yaml views: - type: map name: "Locations" ``` ## Default Summary Formulas | Name | Input Type | Description | |------|------------|-------------| | `Average` | Number | Mathematical mean | | `Min` | Number | Smallest number | | `Max` | Number | Largest number | | `Sum` | Number | Sum of all numbers | | `Range` | Number | Max - Min | | `Median` | Number | Mathematical median | | `Stddev` | Number | Standard deviation | | `Earliest` | Date | Earliest date | | `Latest` | Date | Latest date | | `Checked` | Boolean | Count of true values | | `Unchecked` | Boolean | Count of false values | | `Empty` | Any | Count of empty values | | `Filled` | Any | Count of non-empty values | | `Unique` | Any | Count of unique values | ## Complete Examples ### Task Tracker Base ```yaml filters: and: - file.hasTag("task") - 'file.ext == "md"' formulas: days_until_due: 'if(due, ((date(due) - today()) / 86400000).round(0), "")' is_overdue: 'if(due, date(due) < today() && status != "done", false)' priority_label: 'if(priority == 1, "High", if(priority == 2, "Medium", "Low"))' properties: status: displayName: Status formula.days_until_due: displayName: "Days Until Due" formula.priority_label: displayName: Priority views: - type: table name: "Active Tasks" filters: and: - 'status != "done"' order: - file.name - status - formula.priority_label - due - formula.days_until_due groupBy: property: status direction: ASC summaries: formula.days_until_due: Average - type: table name: "Completed" filters: and: - 'status == "done"' order: - file.name - completed_date ``` ### Reading List Base ```yaml filters: or: - file.hasTag("book") - file.hasTag("article") formulas: reading_time: 'if(pages, (pages * 2).toString() + " min", "")' status_icon: 'if(status == "reading", "reading", if(status == "done", "done", "to-read"))' year_read: 'if(finished_date, date(finished_date).year, "")' properties: author: displayName: Author formula.status_icon: displayName: "" formula.reading_time: displayName: "Est. Time" views: - type: cards name: "Library" order: - cover - file.name - author - formula.status_icon filters: not: - 'status == "dropped"' - type: table name: "Reading List" filters: and: - 'status == "to-read"' order: - file.name - author - pages - formula.reading_time ``` ### Project Notes Base ```yaml filters: and: - file.inFolder("Projects") - 'file.ext == "md"' formulas: last_updated: 'file.mtime.relative()' link_count: 'file.links.length' summaries: avgLinks: 'values.filter(value.isType("number")).mean().round(1)' properties: formula.last_updated: displayName: "Updated" formula.link_count: displayName: "Links" views: - type: table name: "All Projects" order: - file.name - status - formula.last_updated - formula.link_count summaries: formula.link_count: avgLinks groupBy: property: status direction: ASC - type: list name: "Quick List" order: - file.name - status ``` ### Daily Notes Index ```yaml filters: and: - file.inFolder("Daily Notes") - '/^\d{4}-\d{2}-\d{2}$/.matches(file.basename)' formulas: word_estimate: '(file.size / 5).round(0)' day_of_week: 'date(file.basename).format("dddd")' properties: formula.day_of_week: displayName: "Day" formula.word_estimate: displayName: "~Words" views: - type: table name: "Recent Notes" limit: 30 order: - file.name - formula.day_of_week - formula.word_estimate - file.mtime ``` ## Embedding Bases Embed in Markdown files: ```markdown ![[MyBase.base]] ![[MyBase.base#View Name]] ``` ## YAML Quoting Rules - Use single quotes for formulas containing double quotes: `'if(done, "Yes", "No")'` - Use double quotes for simple strings: `"My View Name"` - Escape nested quotes properly in complex expressions ## Common Patterns ### Filter by Tag ```yaml filters: and: - file.hasTag("project") ``` ### Filter by Folder ```yaml filters: and: - file.inFolder("Notes") ``` ### Filter by Date Range ```yaml filters: and: - 'file.mtime > now() - "7d"' ``` ### Filter by Property Value ```yaml filters: and: - 'status == "active"' - 'priority >= 3' ``` ### Combine Multiple Conditions ```yaml filters: or: - and: - file.hasTag("important") - 'status != "done"' - and: - 'priority == 1' - 'due != ""' ``` ## References - [Bases Syntax](https://help.obsidian.md/bases/syntax) - [Functions](https://help.obsidian.md/bases/functions) - [Views](https://help.obsidian.md/bases/views) - [Formulas](https://help.obsidian.md/formulas)