SkillAgentSearch skills...

obsidian-bases

Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries

Install / Use

npx skills add kepano/obsidian-skills --skill obsidian-bases

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

97/100

Category

Automation

Supported Platforms

Universal

Our assessment of obsidian-bases

obsidian-bases scores 97/100 on our quality scale, 153rd of 2,878 Automation skills we index (top 6%).

Its SKILL.md is 13 KB long, well organised into 55 sections with 18 code examples: a thorough specification that gives an agent plenty to work with.

With 48,836 GitHub stars, it is one of the more widely adopted skills in the catalogue.

Substance
30/30
Structure
20/20
Description
12/15
Adoption
20/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated about 2 months ago, so obsidian-bases is actively maintained.
  • Our last check on 2026-10-23 found the source still online.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

Safety scan

No issues found

Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful.

AI review by kimi-k2.7-code on 2026-09-26. Automated pattern scan on 2026-09-26. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.

obsidian-bases compared with similar skills

All 4 of these similar skills score higher than obsidian-bases; compare them before choosing.

SkillScoreStarsUpdatedFormat
obsidian-bases (this skill)by kepano9748.8k54d agoSKILL.md
Agent-Reachby Panniantong100110.3k1d agoCLAUDE.md
Scraplingby D4Vinci10099.8ktodayMCP Server
rufloby ruvnet10081.3ktodayMCP Server
algorithmic-artby anthropics100177.9k47d agoSKILL.md

Frequently asked questions

How do I install obsidian-bases?
Run npx skills add kepano/obsidian-skills --skill obsidian-bases. The install tabs above show the steps for each supported agent.
Which AI agents does obsidian-bases work with?
It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
Is obsidian-bases safe to use?
Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful. It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is obsidian-bases still maintained?
The repository was last updated about 2 months ago, so obsidian-bases is actively maintained.

name: obsidian-bases 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 Skill

Workflow

  1. Create the file: Create a .base file in the vault with valid YAML content
  2. Define scope: Add filters to select which notes appear (by tag, folder, property, or date)
  3. Add formulas (optional): Define computed properties in the formulas section
  4. Configure views: Add one or more views (table, cards, list, or map) with order specifying which properties to display
  5. Validate: Verify the file is valid YAML with no syntax errors. Check that all referenced properties and formulas exist. Common issues: unquoted strings containing special YAML characters, mismatched quotes in formula expressions, referencing formula.X without defining X in formulas
  6. Test in Obsidian: Open the .base file in Obsidian to confirm the view renders correctly. If it shows a YAML error, check quoting rules below

Schema

Base files use the .base extension and contain valid YAML.

# Global filters apply to ALL views in the base
filters:
  # Can be a single filter string
  # OR a recursive filter object with exactly ONE key: and, or, or not
  and:
    - 'status == "active"'
    - not:
        - 'file.hasTag("archived")'

# 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 follow the same rules
      and:
        - 'status == "active"'
    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

# 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 | | <code>!</code> | 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.

formulas:
  # Simple arithmetic
  total: "price * quantity"

  # Conditional logic
  status_icon: 'if(done, "✅", "⏳")'

  # String formatting
  formatted_price: 'if(price, price.toFixed(2) + " dollars")'

  # Date formatting
  created: 'file.ctime.format("YYYY-MM-DD")'

  # Calculate days since created (use .days for Duration)
  days_old: '(now() - file.ctime).days'

  # Calculate days until due date
  days_until_due: 'if(due_date, (date(due_date) - today()).days, "")'

Key Functions

Most commonly used functions. For the complete reference of all types (Date, String, Number, List, File, Link, Object, RegExp), see FUNCTIONS_REFERENCE.md.

| Function | Signature | Description | |----------|-----------|-------------| | date() | date(string): date | Parse string to date (YYYY-MM-DD HH:mm:ss) | | now() | now(): date | Current date and time | | today() | today(): date | Current date (time = 00:00:00) | | if() | if(condition, trueResult, falseResult?) | Conditional | | duration() | duration(string): duration | Parse duration string | | file() | file(path): file | Get file object | | link() | link(path, display?): Link | Create a link |

Duration Type

When subtracting two dates, the result is a Duration type (not a number).

Duration Fields: duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds

IMPORTANT: Duration does NOT support .round(), .floor(), .ceil() directly. Access a numeric field first (like .days), then apply number functions.

# CORRECT: Calculate days between dates
"(date(due_date) - today()).days"                    # Returns number of days
"(now() - file.ctime).days"                          # Days since created
"(date(due_date) - today()).days.round(0)"           # Rounded days

# WRONG - will cause error:
# "((date(due) - today()) / 86400000).round(0)"      # Duration doesn't support division then round

Date Arithmetic

# Duration units: y/year/years, M/month/months, d/day/days,
#                 w/week/weeks, h/hour/hours, m/minute/minutes, s/second/seconds
"now() + \"1 day\""       # Tomorrow
"today() + \"7d\""        # A week from today
"now() - file.ctime"      # Returns Duration
"(now() - file.ctime).days"  # Get days as number

View Types

Table View

views:
  - type: table
    name: "My Table"
    order:
      - file.name
      - status
      - due_date
    summaries:
      price: Sum
      count: Average

Cards View

views:
  - type: cards
    name: "Gallery"
    order:
      - file.name
      - cover_image
      - description

List View

views:
  - type: list
    name: "Simple List"
    order:
      - file.name
      - status

Map View

Requires latitude/longitude properties and the Maps community plugin.

views:
  - type: map
    name: "Locations"
    # Map-specific settings for lat/lng properties

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 | | Range | Date | Latest - Earliest | | 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

filters:
  and:
    - file.hasTag("task")
    - 'file.ext == "md"'

formulas:
  days_until_due: 'if(due, (date(due) - today()).days, "")'
  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

filters:
  or:
    - file.hasTag("book")
    - file.hasTag("article")

formulas:
  reading_time: 'if(pages, (pages * 2).toString() + " min", "")'
  status_icon: 'if(status == "reading", "📖", if(status == "done", "✅", "📚"))'
  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

Daily Notes Index

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:

![[MyBase.base]]

<!-- Specific view -->
![[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

Troubleshooting

YAML Syntax Errors

Unquoted special characters: Strings containing :, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, ` must be quoted.

# WRONG - colon in unquoted string
displayName: Status: Active

# CORRECT
displayName: "Status: Active"

Mismatched quotes in formulas: When a formula contains double quotes, wrap the entire formula in single quotes.

# WRONG - double quotes inside double quotes
formulas:
  label: "if(done, "Yes", "No")"

# CORRECT - single quotes wrapping double quotes
formulas:
  label: 'if(done, "Yes", "No")'

Common Formula Errors

Duration math without field access: Subtracting dates returns a Duration, not a number. Always access `.

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars48.8k
CategoryAutomation
Updated1mo ago
Forks3.5k

Trust signals

100/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

No cautions