Obsidian Base Create

SkillFiles & storage

Generates Obsidian .base files from natural language descriptions. Translates requests like "show me all active project notes sorted by date" into valid .base YAML with filters, formulas, views, and summaries. Activates on "create base", "make a view", "show me all notes where", "dashboard", or when user wants structured views of their vault.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Obsidian Base Create skill

What this skill tells your AI

The instructions your AI receives, as published by elliotjlt/claude-skill-potions in skills/obsidian-base-create/SKILL.md and read by ahel’s review.

When To Activate

Do NOT trigger for:

  • Editing existing .base files (edit directly)
  • Simple search queries (use obsidian-vault-search)
  • Views that don't depend on frontmatter properties

Instructions

Step 1: Understand What the User Wants to See

RequestView TypeKey FilterSort
"All my meetings"tabletype == meetingdate desc
"Active projects"cardstype == project AND status == activename asc
"Tasks this week"tabletype == task AND date >= week startdate asc
"Recent notes"table(none or date-based)file.mtime desc
"Reading list"cardstype == reference AND status == draftcreated desc

Ask if not obvious:

  • What properties should show as columns?
  • How should it be sorted?
  • Table, cards, or list view?

Step 2: Check Available Properties

# Find all frontmatter properties used in the vault
grep -rh "^[a-z].*:" "$VAULT_PATH" --include="*.md" | \
  grep -v "^#\|^-\|^ " | sort | uniq -c | sort -rn | head -20

Common properties from the vault schema (check CLAUDE.md):

  • type: note, meeting, project, daily, reference, task
  • status: draft, active, completed, archived
  • date: YYYY-MM-DD
  • created: YYYY-MM-DD
  • project: project name
  • tags: array of tags
  • attendees: list (meetings)

Don't create filters on properties that don't exist in the vault.

Step 3: Build the Base YAML

# Global filter (applies to all views)
filter:
  - property: <name>
    operator: "<op>"
    value: "<value>"

# Computed properties
formulas:
  formula-name: '<expression>'

# View configurations
views:
  - name: "View Name"
    type: table  # table, cards, list, map
    properties:
      - file.name
      - property-name
    sort:
      - property: <name>
        order: asc  # or desc
    filter:  # view-specific filter (in addition to global)
      - property: <name>
        operator: "<op>"
        value: "<value>"

Filter operators:

OperatorMeaning
==equals
!=not equals
>greater than
<less than
>=greater or equal
<=less or equal

Compound filters (AND/OR/NOT):

filter:
  # AND (default — sequential conditions)
  - property: type
    operator: "=="
    value: meeting
  - property: status
    operator: "=="
    value: active

  # OR (explicit)
  - operator: OR
    conditions:
      - property: type
        operator: "=="
        value: meeting
      - property: type
        operator: "=="
        value: project

  # NOT
  - operator: NOT
    conditions:
      - property: status
        operator: "=="
        value: archived

File metadata properties:

file.name     — Note filename without extension
file.path     — Full path from vault root
file.mtime    — Last modified time
file.ctime    — Creation time
file.size     — File size in bytes
file.folder   — Parent folder path
file.ext      — File extension

Step 4: Add Formulas (if needed)

formulas:
  # Days since creation
  age: '(now() - this.created).days'

  # Status badge
  badge: 'if(this.status == "active", "🟢", if(this.status == "draft", "🟡", "⚪"))'

  # Overdue check
  overdue: 'if(this.date < today(), "⚠️ Overdue", "On track")'

  # Tag count
  tag-count: 'this.tags.length'

  # Full name from path
  display: 'this.file.name'

Useful formula functions:

  • Date: now(), today(), date("YYYY-MM-DD"), format(date, "MMM DD"), relative(date)
  • String: contains(str, substr), replace(str, old, new), lower(str), trim(str)
  • Number: abs(), ceil(), floor(), round()
  • List: filter(), map(), join(), sort(), .length
  • File: hasTag(tag), hasProperty(prop), inFolder(path), asLink()
  • Logic: if(condition, then, else)

The this keyword refers to the current row's note.

Step 5: Configure View

Cards view (best for visual browsing):

views:
  - name: "Active Projects"
    type: cards
    properties:
      - file.name
      - status
      - tags
    sort:
      - property: file.name
        order: asc

List view (best for simple lists):

views:
  - name: "Quick List"
    type: list
    properties:
      - file.name
    sort:
      - property: file.mtime
        order: desc

Multiple views (same base, different perspectives):

views:
  - name: "Table"
    type: table
    properties: [file.name, status, date]
    sort: [{property: date, order: desc}]

  - name: "Cards"
    type: cards
    properties: [file.name, status]
    sort: [{property: status, order: asc}]

Summaries (aggregate values shown at column bottom):

views:
  - name: "Project Budget"
    type: table
    properties:
      - file.name
      - budget
      - spent
    summaries:
      budget: sum
      spent: sum

Summary types: average, min, max, sum, range, median, count, earliest, latest, checked, unchecked, empty, filled, unique

Step 6: Write and Verify

Write the YAML. Then verify by checking the YAML is valid:

python3 -c "import yaml; yaml.safe_load(open('$BASE_PATH'))" && echo "Valid YAML"

Confirm:

Base created: base-name.base

View: [table / cards / list]
Filter: [what's filtered]
Columns: [listed properties]
Sort: [sort order]

Open in Obsidian to see your data.

Output Format

## Base Created

**File:** base-name.base
**View:** [table / cards / list / map]
**Filter:** [description of filter logic]
**Columns:** [list of shown properties]
**Sort:** [property, direction]
**Formulas:** [any computed properties]

Open in Obsidian to interact with the view.

NEVER

  • Create filters on properties that don't exist in the vault
  • Write invalid YAML (always validate)
  • Skip checking what properties exist first
  • Use complex formulas without explaining what they compute
  • Create a base without at least one view configured
  • Assume property names — check CLAUDE.md or scan existing notes

ALWAYS

  • Check what frontmatter properties exist in the vault first
  • Validate the YAML output
  • Include at least file.name in every view's properties
  • Use descriptive view names
  • Explain the filter logic in plain English
  • Suggest additional views or formulas that might be useful

Example

User: "Make me a dashboard showing all active projects with their status and last modified date"

filter:
  - property: type
    operator: "=="
    value: project
  - property: status
    operator: "!="
    value: archived

formulas:
  last-active: 'relative(this.file.mtime)'

views:
  - name: "Active Projects"
    type: table
    properties:
      - file.name
      - status
      - project
      - tags
      - last-active
    sort:
      - property: file.mtime
        order: desc

  - name: "Project Cards"
    type: cards
    properties:
      - file.name
      - status
      - last-active
    sort:
      - property: status
        order: asc
Base created: project-dashboard.base

View 1: "Active Projects" (table)
  Filter: type == project AND status != archived
  Columns: name, status, project, tags, last active (relative time)
  Sort: last modified (newest first)

View 2: "Project Cards" (cards)
  Same filter, card layout for visual browsing

Open in Obsidian to see your projects.

Signals

GitHub stars
62
Forks
2
Last commit
Feb 2026
Advanced
Catalog kind
skill
Gateway key
obsidian-base-create
Source
github.com/elliotjlt/claude-skill-potions