关于 obsidian-bases
为兼容 skills 的 Agent 提供 Obsidian Bases 文件编写指导,可创建和编辑包含视图、筛选器、公式及相关配置的有效 .base 文件。适合需要在 Obsidian 笔记库中定义动态笔记视图的用户。
主要功能
- 01创建和编辑 .base 文件
- 02配置表格、卡片和列表视图
- 03设置全局及视图筛选器
- 04使用公式和属性
- 05配置汇总计算
适用场景
- 01构建任务跟踪视图
- 02整理阅读清单
- 03汇总项目笔记
- 04索引每日笔记
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ jackjin1997/ clawforge --skill obsidian-bases安装后在 Claude Code 中输入/obsidian-bases确认已加载。
详细介绍
Obsidian Bases 技能
此技能可让兼容技能的 Agent 创建和编辑有效的 Obsidian Bases(.base)文件,包括视图、筛选器、公式及所有相关配置。
概述
Obsidian Bases 是基于 YAML 的文件,用于定义 Obsidian 库中笔记的动态视图。Base 文件可以包含多个视图、全局筛选器、公式、属性配置和自定义摘要。
文件格式
Base 文件使用 .base 扩展名,并包含有效的 YAML。它们也可以嵌入 Markdown 代码块中。
完整架构
# 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
筛选器语法
筛选器用于缩小结果范围。可以全局应用,也可以按视图应用。
筛选器结构
# 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")
筛选器运算符
| 运算符 | 描述 |
|---|---|
== | 等于 |
!= | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于或等于 |
<= | 小于或等于 |
&& | 逻辑与 |
|| | 逻辑或 |
! | 逻辑非 |
属性
三种属性类型
- 笔记属性 - 来自 frontmatter:
note.author或仅使用author - 文件属性 - 文件元数据:
file.name、file.mtime等 - 公式属性 - 计算得出的值:
formula.my_formula
文件属性参考
| 属性 | 类型 | 描述 |
|---|---|---|
file.name | String | 文件名 |
file.basename | String | 不含扩展名的文件名 |
file.path | String | 文件的完整路径 |
file.folder | String | 父文件夹路径 |
file.ext | String | 文件扩展名 |
file.size | Number | 文件大小(字节) |
file.ctime | Date | 创建时间 |
file.mtime | Date | 修改时间 |
file.tags | List | 文件中的所有标签 |
file.links | List | 文件中的内部链接 |
file.backlinks | List | 链接到此文件的文件 |
file.embeds | List | 笔记中的嵌入内容 |
file.properties | Object | 所有 frontmatter 属性 |
this 关键字
- 在主内容区域中:指 Base 文件本身
- 嵌入时:指嵌入该内容的文件
- 在侧边栏中:指主内容中的活动文件
公式语法
公式根据属性计算值。定义在 formulas 部分中。
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, "")'
函数参考
全局函数
| 函数 | 签名 | 描述 |
|---|---|---|
date() | date(string): date | 将字符串解析为日期。格式:YYYY-MM-DD HH:mm:ss |
duration() | duration(string): duration | 解析时长字符串 |
now() | now(): date | 当前日期和时间 |
today() | today(): date | 当前日期(时间 = 00:00:00) |
if() | if(condition, trueResult, falseResult?) | 条件判断 |
min() | min(n1, n2, ...): number | 最小数值 |
max() | max(n1, n2, ...): number | 最大数值 |
number() | number(any): number | 转换为数值 |
link() | link(path, display?): Link | 创建链接 |
list() | list(element): List | 如果尚未是列表,则将其包装为列表 |
file() | file(path): file | 获取文件对象 |
image() | image(path): image | 创建用于渲染的图像 |
icon() | icon(name): icon | 按名称获取 Lucide 图标 |
html() | html(string): html | 渲染为 HTML |
escapeHTML() | escapeHTML(string): string | 转义 HTML 字符 |
任意类型函数
| 函数 | 签名 | 描述 |
|---|---|---|
isTruthy() | any.isTruthy(): boolean | 转换为布尔值 |
isType() | any.isType(type): boolean | 检查类型 |
toString() | any.toString(): string | 转换为字符串 |
日期函数和字段
字段: date.year、date.month、date.day、date.hour、date.minute、date.second、date.millisecond
| 函数 | 签名 | 描述 |
|---|---|---|
date() | date.date(): date | 移除时间部分 |
format() | date.format(string): string | 使用 Moment.js 模式格式化 |
time() | date.time(): string | 获取字符串形式的时间 |
relative() | date.relative(): string | 易于阅读的相对时间 |
isEmpty() | date.isEmpty(): boolean | 日期始终不为空 |
Duration 类型
减去两个日期时,结果是 Duration 类型(而非数字)。Duration 有自己的属性和方法。
Duration 字段:
| 字段 | 类型 | 描述 |
|---|---|---|
duration.days | Number | 持续时间的总天数 |
duration.hours | Number | 持续时间的总小时数 |
duration.minutes | Number | 持续时间的总分钟数 |
duration.seconds | Number | 持续时间的总秒数 |
duration.milliseconds | Number | 持续时间的总毫秒数 |
重要: Duration 不直接支持 .round()、.floor()、.ceil()。必须先访问一个数字字段(如 .days),然后再应用数字函数。
# CORRECT: Calculate days between dates
"(date(due_date) - today()).days" # Returns number of days
"(now() - file.ctime).days" # Days since created
# CORRECT: Round the numeric result if needed
"(date(due_date) - today()).days.round(0)" # Rounded days
"(now() - file.ctime).hours.round(0)" # Rounded hours
# WRONG - will cause error:
# "((date(due) - today()) / 86400000).round(0)" # Duration doesn't support division then round
日期运算
# 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 returns Duration type
"now() - file.ctime" # Returns Duration
"(now() - file.ctime).days" # Get days as number
"(now() - file.ctime).hours" # Get hours as number
# Complex duration arithmetic
"now() + (duration('1d') * 2)"
字符串函数
字段: string.length
| 函数 | 签名 | 描述 |
|---|---|---|
contains() | string.contains(value): boolean | 检查子字符串 |
containsAll() | string.containsAll(...values): boolean | 所有子字符串均存在 |
containsAny() | string.containsAny(...values): boolean | 任一子字符串存在 |
startsWith() | string.startsWith(query): boolean | 是否以查询字符串开头 |
endsWith() | string.endsWith(query): boolean | 是否以查询字符串结尾 |
isEmpty() | string.isEmpty(): boolean | 为空或不存在 |
lower() | string.lower(): string | 转为小写 |
title() | string.title(): string | 转为标题大小写 |
trim() | string.trim(): string | 移除空白字符 |
replace() | string.replace(pattern, replacement): string | 替换模式 |
repeat() | string.repeat(count): string | 重复字符串 |
reverse() | string.reverse(): string | 反转字符串 |
slice() | string.slice(start, end?): string | 子字符串 |
split() | string.split(separator, n?): list | 拆分为列表 |
数字函数
| 函数 | 签名 | 描述 |
|---|---|---|
abs() | number.abs(): number | 绝对值 |
ceil() | number.ceil(): number | 向上取整 |
floor() | number.floor(): number | 向下取整 |
round() | number.round(digits?): number | 四舍五入到指定位数 |
toFixed() | number.toFixed(precision): string | 定点表示法 |
isEmpty() | number.isEmpty(): boolean | 不存在 |
列表函数
字段: list.length
| 函数 | 签名 | 描述 |
|---|---|---|
contains() | list.contains(value): boolean | 元素是否存在 |
containsAll() | list.containsAll(...values): boolean | 所有元素均存在 |
containsAny() | list.containsAny(...values): boolean | 任一元素存在 |
filter() | list.filter(expression): list | 按条件筛选(使用 value、index) |
map() | list.map(expression): list | 转换元素(使用 value、index) |
reduce() | list.reduce(expression, initial): any | 将列表归约为单个值(使用 value、index、acc) |
flat() | list.flat(): list | 展平嵌套列表 |
join() | list.join(separator): string | 拼接为字符串 |
reverse() | list.reverse(): list | 反转顺序 |
slice() | list.slice(start, end?): list | 子列表 |
sort() | list.sort(): list | 升序排序 |
unique() | list.unique(): list | 移除重复项 |
isEmpty() | list.isEmpty(): boolean | 没有元素 |
文件函数
| 函数 | 签名 | 描述 |
|---|---|---|
asLink() | file.asLink(display?): Link | 转换为链接 |
hasLink() | file.hasLink(otherFile): boolean | 是否链接到文件 |
hasTag() | file.hasTag(...tags): boolean | 是否包含任一标签 |
hasProperty() | file.hasProperty(name): boolean | 是否包含属性 |
inFolder() | file.inFolder(folder): boolean | 是否位于文件夹或子文件夹中 |
链接函数
| 函数 | 签名 | 描述 |
|---|---|---|
asFile() | link.asFile(): file | 获取文件对象 |
linksTo() | link.linksTo(file): boolean | 是否链接到文件 |
对象函数
| 函数 | 签名 | 描述 |
|---|---|---|
isEmpty() | object.isEmpty(): boolean | 没有属性 |
keys() | object.keys(): list | 键列表 |
values() | object.values(): list | 值列表 |
正则表达式函数
| 函数 | 签名 | 描述 |
|---|---|---|
matches() | regexp.matches(string): boolean | 测试是否匹配 |
视图类型
表格视图
views:
- type: table
name: "My Table"
order:
- file.name
- status
- due_date
summaries:
price: Sum
count: Average
卡片视图
views:
- type: cards
name: "Gallery"
order:
- file.name
- cover_image
- description
列表视图
views:
- type: list
name: "Simple List"
order:
- file.name
- status
地图视图
需要纬度/经度属性和 Maps 社区插件。
views:
- type: map
name: "Locations"
# Map-specific settings for lat/lng properties
默认汇总公式
| 名称 | 输入类型 | 描述 |
|---|---|---|
Average | Number | 数学平均值 |
Min | Number | 最小值 |
Max | Number | 最大值 |
Sum | Number | 所有数值之和 |
Range | Number | 最大值 - 最小值 |
Median | Number | 数学中位数 |
Stddev | Number | 标准差 |
Earliest | Date | 最早日期 |
Latest | Date | 最晚日期 |
Range | Date | 最晚日期 - 最早日期 |
Checked | Boolean | true 值的数量 |
Unchecked | Boolean | false 值的数量 |
Empty | Any | 空值的数量 |
Filled | Any | 非空值的数量 |
Unique | Any | 唯一值的数量 |
完整示例
任务跟踪器 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
阅读清单 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
项目笔记 Base
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
每日笔记索引
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
嵌入 Bases
嵌入 Markdown 文件:
![[MyBase.base]]
![[MyBase.base#View Name]]
YAML 引号规则
- 对包含双引号的公式使用单引号:
'if(done, "Yes", "No")' - 对简单字符串使用双引号:
"My View Name" - 在复杂表达式中正确转义嵌套引号
常见模式
按标签筛选
filters:
and:
- file.hasTag("project")
按文件夹筛选
filters:
and:
- file.inFolder("Notes")
按日期范围筛选
filters:
and:
- 'file.mtime > now() - "7d"'
按属性值筛选
filters:
and:
- 'status == "active"'
- 'priority >= 3'
合并多个条件
filters:
or:
- and:
- file.hasTag("important")
- 'status != "done"'
- and:
- 'priority == 1'
- 'due != ""'
参考资料
评论
支持 Markdown