| name | napkin |
| description | Read, create, search, and manage notes in Obsidian vaults using the napkin CLI. Works directly on markdown files and canvas files — no Obsidian app required. Use when the user asks to interact with their Obsidian vault, manage notes, search vault content, work with tasks, tags, properties, daily notes, templates, bases, bookmarks, aliases, or canvas files from the command line. |
napkin
CLI for Obsidian vaults. Operates directly on markdown files — no Obsidian app, no Electron, no Catalyst license.
Install: npm install -g napkin-ai
IMPORTANT: Always pass --vault $NAPKIN_VAULT to every napkin command. The vault lives in the knowledge/ subdirectory, not the workspace root.
Reading this vault's memory notes
This vault is maintained by an automatic distillation loop. Entity notes (under people/, projects/, references/) follow a temporal convention — read them this way:
NAPKIN.md is the map of the vault. Start here for a quick overview of who and what is remembered.
- Frontmatter +
## Current View hold the authoritative present value of every fact. When the user asks "what is X now?", answer from here.
## History is append-only past context. A bullet ending with *(superseded YYYY-MM-DD — reason)* is an old value that has been replaced — never quote it as current. Use History only to answer "what did X used to think / when did this change?".
One file per entity, one directory per category — a person is always a file inside people/, never a section in a flat people.md.
Episodes (episodes/)
Episodes are time-bounded events or topics — distinct from entity files which capture permanent knowledge. An episode tracks a developing situation (a market event, a personal search, a conflict) that starts, heats up, and eventually resolves or fades.
- Episodes may appear in your context as
<active_episodes> XML — these are automatically injected when the user's message is relevant.
- You can create episodes during conversation using the
write tool: write episodes/car-search.md with the episode frontmatter format (type, status, started, last_mentioned, mentions, keywords, summary).
- You can resolve episodes when the user indicates closure: set
status: resolved in the frontmatter.
- Episode
status values: active (current), cooling (not mentioned recently — set by consolidation, not by you), resolved (explicitly closed), faded (long-dormant — set by consolidation).
## History in episodes is append-only, same as entity files.
Memory suggestions (.memory-suggestions.md)
If the file knowledge/.memory-suggestions.md exists, it contains recommendations from the weekly/monthly consolidation about topics worth adding to MEMORY.md. Read it, decide whether the suggestions are relevant, update MEMORY.md if appropriate, then delete the file.
Syntax
napkin uses standard CLI flags. Quote values with spaces:
napkin --vault $NAPKIN_VAULT create --name "My Note" --content "Hello world"
Global flags
| Flag | Description |
|---|
--json | Output as JSON (use this for programmatic access) |
-q, --quiet | Suppress output |
--vault <path> | Vault path (default: auto-detect by walking up from cwd looking for .obsidian/) |
--copy | Copy output to clipboard |
File targeting
--file <name> — resolves like a wikilink (name only, no path or extension needed)
--path <path> — exact path from vault root, e.g. Projects/note.md
Commands
Vault
napkin --vault $NAPKIN_VAULT vault
napkin --vault $NAPKIN_VAULT version
Files & folders — napkin file
napkin --vault $NAPKIN_VAULT file info <name>
napkin --vault $NAPKIN_VAULT file list
napkin --vault $NAPKIN_VAULT file list --ext md
napkin --vault $NAPKIN_VAULT file list --folder Projects
napkin --vault $NAPKIN_VAULT file list --total
napkin --vault $NAPKIN_VAULT file folder <path>
napkin --vault $NAPKIN_VAULT file folder <path> --info files
napkin --vault $NAPKIN_VAULT file folders
napkin --vault $NAPKIN_VAULT file folders --total
Read & write
napkin --vault $NAPKIN_VAULT read <file>
napkin --vault $NAPKIN_VAULT create --name "Note" --content "# Hello"
napkin --vault $NAPKIN_VAULT create --name "Note" --path "Projects" --template "Meeting Note"
napkin --vault $NAPKIN_VAULT append --file "Note" --content "New line at end"
napkin --vault $NAPKIN_VAULT prepend --file "Note" --content "New line after frontmatter"
napkin --vault $NAPKIN_VAULT move --file "Note" --to Archive
napkin --vault $NAPKIN_VAULT rename --file "Note" --name "Renamed Note"
napkin --vault $NAPKIN_VAULT delete --file "Note"
napkin --vault $NAPKIN_VAULT delete --file "Note" --permanent
Daily notes — napkin daily
Reads config from .obsidian/daily-notes.json (folder, format, template).
napkin --vault $NAPKIN_VAULT daily today
napkin --vault $NAPKIN_VAULT daily path
napkin --vault $NAPKIN_VAULT daily read
napkin --vault $NAPKIN_VAULT daily append --content "- [ ] Buy groceries"
napkin --vault $NAPKIN_VAULT daily prepend --content "## Morning"
Search
Full-text search with relevance ranking (fuzzy matching, prefix search, filename boosting).
napkin --vault $NAPKIN_VAULT search "meeting"
napkin --vault $NAPKIN_VAULT search --query "meeting"
napkin --vault $NAPKIN_VAULT search "TODO" --path Projects
napkin --vault $NAPKIN_VAULT search "bug" --total
napkin --vault $NAPKIN_VAULT search "deploy" --limit 5
napkin --vault $NAPKIN_VAULT search "TODO" --context
Tasks — napkin task
napkin --vault $NAPKIN_VAULT task list
napkin --vault $NAPKIN_VAULT task list --todo
napkin --vault $NAPKIN_VAULT task list --done
napkin --vault $NAPKIN_VAULT task list --daily
napkin --vault $NAPKIN_VAULT task list --file "Project A"
napkin --vault $NAPKIN_VAULT task list --verbose
napkin --vault $NAPKIN_VAULT task list --total
napkin --vault $NAPKIN_VAULT task show --file "note" --line 3
napkin --vault $NAPKIN_VAULT task show --file "note" --line 3 --toggle
napkin --vault $NAPKIN_VAULT task show --file "note" --line 3 --done
napkin --vault $NAPKIN_VAULT task show --ref "note.md:3" --todo
Tags — napkin tag
napkin --vault $NAPKIN_VAULT tag list
napkin --vault $NAPKIN_VAULT tag list --counts
napkin --vault $NAPKIN_VAULT tag list --sort count
napkin --vault $NAPKIN_VAULT tag info --name "project"
napkin --vault $NAPKIN_VAULT tag info --name "project" --verbose
napkin --vault $NAPKIN_VAULT tag aliases
napkin --vault $NAPKIN_VAULT tag aliases --file "note"
napkin --vault $NAPKIN_VAULT tag aliases --total
Properties — napkin property
napkin --vault $NAPKIN_VAULT property list
napkin --vault $NAPKIN_VAULT property list --file "note"
napkin --vault $NAPKIN_VAULT property list --counts
napkin --vault $NAPKIN_VAULT property read --file "note" --name title
napkin --vault $NAPKIN_VAULT property set --file "note" --name status --value done
napkin --vault $NAPKIN_VAULT property remove --file "note" --name status
Links — napkin link
napkin --vault $NAPKIN_VAULT link back --file "note"
napkin --vault $NAPKIN_VAULT link out --file "note"
napkin --vault $NAPKIN_VAULT link unresolved
napkin --vault $NAPKIN_VAULT link orphans
napkin --vault $NAPKIN_VAULT link deadends
Outline
napkin --vault $NAPKIN_VAULT outline --file "note"
napkin --vault $NAPKIN_VAULT outline --file "note" --format md
napkin --vault $NAPKIN_VAULT outline --file "note" --format json
Templates — napkin template
napkin --vault $NAPKIN_VAULT template list
napkin --vault $NAPKIN_VAULT template read --name "Daily Note"
napkin --vault $NAPKIN_VAULT template read --name "Meeting" --resolve --title "Standup"
napkin --vault $NAPKIN_VAULT template insert --file "note" --name "Template"
Bookmarks — napkin bookmark
napkin --vault $NAPKIN_VAULT bookmark list
napkin --vault $NAPKIN_VAULT bookmark list --total
napkin --vault $NAPKIN_VAULT bookmark add --file "note"
napkin --vault $NAPKIN_VAULT bookmark add --folder "Projects"
napkin --vault $NAPKIN_VAULT bookmark add --search "TODO"
napkin --vault $NAPKIN_VAULT bookmark add --url "https://example.com" --title "Example"
Bases — napkin base
Query vault files using Obsidian Bases .base files (YAML-defined filters over frontmatter properties, powered by SQLite in-memory).
napkin --vault $NAPKIN_VAULT base list
napkin --vault $NAPKIN_VAULT base views --file "projects"
napkin --vault $NAPKIN_VAULT base query --file "projects"
napkin --vault $NAPKIN_VAULT base query --file "projects" --view "Active"
napkin --vault $NAPKIN_VAULT base query --file "projects" --format paths
napkin --vault $NAPKIN_VAULT base query --file "projects" --format csv
napkin --vault $NAPKIN_VAULT base create --file "projects" --name "New Item"
Canvas — napkin canvas
Read and write JSON Canvas files (.canvas) — nodes, edges, groups.
napkin --vault $NAPKIN_VAULT canvas list
napkin --vault $NAPKIN_VAULT canvas list --total
napkin --vault $NAPKIN_VAULT canvas read --file "Board"
napkin --vault $NAPKIN_VAULT canvas nodes --file "Board"
napkin --vault $NAPKIN_VAULT canvas nodes --file "Board" --type text
napkin --vault $NAPKIN_VAULT canvas create --file "Board"
napkin --vault $NAPKIN_VAULT canvas create --file "Board" --path "Projects"
napkin --vault $NAPKIN_VAULT canvas add-node --file "Board" --type text --text "# Hello"
napkin --vault $NAPKIN_VAULT canvas add-node --file "Board" --type file --note-file "Notes/note.md"
napkin --vault $NAPKIN_VAULT canvas add-node --file "Board" --type link --url "https://example.com"
napkin --vault $NAPKIN_VAULT canvas add-node --file "Board" --type group --label "My Group"
napkin --vault $NAPKIN_VAULT canvas add-node --file "Board" --type text --text "Positioned" --x 100 --y 200
napkin --vault $NAPKIN_VAULT canvas add-edge --file --from abc1 --to def2 --label
napkin --vault canvas remove-node --file -- abc1
Node IDs are 16-char hex. --from/--to/--id accept ID prefixes for convenience.
Node types: text, file, link, group. Colors: 1-6 or hex.
New nodes auto-position to the right of existing content.
Word count
napkin --vault $NAPKIN_VAULT wordcount --file "note"
napkin --vault $NAPKIN_VAULT wordcount --file "note" --words
napkin --vault $NAPKIN_VAULT wordcount --file "note" --characters
Agent onboarding
napkin --vault $NAPKIN_VAULT onboard
JSON output
Every command supports --json. Always use --json for programmatic access:
napkin --vault $NAPKIN_VAULT task list --todo --json
napkin --vault $NAPKIN_VAULT search "deploy" --json
napkin --vault $NAPKIN_VAULT property read --file "note" --name status --json
Common workflows
Morning standup prep
napkin --vault $NAPKIN_VAULT daily read --json
napkin --vault $NAPKIN_VAULT task list --todo --json
napkin --vault $NAPKIN_VAULT search "blocker" --json
Project overview
napkin --vault $NAPKIN_VAULT file list --folder Projects --json
napkin --vault $NAPKIN_VAULT tag list --counts --json
napkin --vault $NAPKIN_VAULT link orphans --json
napkin --vault $NAPKIN_VAULT link unresolved --json
Note management
napkin --vault $NAPKIN_VAULT create --name "Meeting Notes" --template "Meeting Note" --path "Meetings"
napkin --vault $NAPKIN_VAULT property set --file "Meeting Notes" --name attendees --value "Alice, Bob"
napkin --vault $NAPKIN_VAULT append --file "Meeting Notes" --content "- [ ] Follow up on deployment"
Obsidian Markdown Reference
napkin operates on Obsidian Flavored Markdown files. This section covers the syntax for creating valid content.
Properties (frontmatter)
YAML frontmatter at the start of a note:
---
title: My Note
date: 2024-01-15
tags:
- project
- important
aliases:
- My Note
- Alternative Name
cssclasses:
- custom-class
status: in-progress
rating: 4.5
completed: false
---
Property types
| Type | Example |
|---|
| Text | title: My Title |
| Number | rating: 4.5 |
| Checkbox | completed: true |
| Date | date: 2024-01-15 |
| Date & Time | due: 2024-01-15T14:30:00 |
| List | tags: [one, two] or YAML list |
| Links | related: "[[Other Note]]" |
Default properties: tags, aliases, cssclasses
Internal links (wikilinks)
[[Note Name]] Link to note
[[Note Name|Display Text]] Custom display text
[[Note Name#Heading]] Link to heading
[[Note Name#^block-id]] Link to block
[[#Heading in same note]] Same-file heading link
Embeds
![[Note Name]] Embed entire note
![[Note Name#Heading]] Embed section
![[image.png]] Embed image
![[image.png|300]] Image with width
![[document.pdf]] Embed PDF
![[document.pdf#page=3]] PDF at page
Tags
#tag
#nested/tag
#tag-with-dashes
# In frontmatter:
tags:
- tag1
- nested/tag2
Tags can contain letters, numbers (not first), underscores, hyphens, forward slashes.
Task lists
- [ ] Incomplete task
- [x] Completed task
- [ ] Parent task
- [ ] Subtask
- [x] Done subtask
Callouts
> [!note]
> This is a note callout.
> [!warning] Custom Title
> Warning with custom title.
> [!faq]- Collapsed by default
> Hidden until expanded.
> [!tip]+ Expanded by default
> Visible but collapsible.
Callout types: note, abstract/summary/tldr, info, todo, tip/hint/important, success/check/done, question/help/faq, warning/caution/attention, failure/fail/missing, danger/error, bug, example, quote/cite
Text formatting
| Style | Syntax |
|---|
| Bold | **text** |
| Italic | *text* |
| Bold + Italic | ***text*** |
| Strikethrough | ~~text~~ |
| Highlight | ==text== |
| Inline code | `code` |
Code blocks
```javascript
function hello() {
console.log("Hello");
}
```
Math (LaTeX)
Inline: $e^{i\pi} + 1 = 0$
Block:
$$
\sum_{i=1}^{n} x_i
$$
Block references
This paragraph can be linked to. ^my-block-id
Link to it: [[Note#^my-block-id]]
Embed it: ![[Note#^my-block-id]]
Comments
This is visible %%but this is hidden%% text.
%%
This entire block is hidden.
%%
Bases Reference
Bases are YAML-defined views that query vault files using their frontmatter properties. Saved as .base files.
Structure
filters:
and:
- file.hasTag("project")
- 'status != "done"'
formulas:
days_left: '(date(due) - today()).days'
properties:
status:
displayName: Status
views:
- type: table
name: "Active"
order:
- file.name
- status
limit: 20
Filters
filters:
file.hasTag("project")
filters:
and:
- file.hasTag("project")
- 'status != "done"'
filters:
or:
- file.hasTag("book")
- file.hasTag("article")
filters:
not:
- file.hasTag("archived")
filters:
or:
- file.hasTag("urgent")
- and:
- file.hasTag("project")
- 'priority >= 3'
Filter operators
| Operator | Description |
|---|
== | equals |
!= | not equal |
> | greater than |
< | less than |
>= | greater than or equal |
<= | less than or equal |
File functions for filters
| Function | Description |
|---|
file.hasTag("tag1", "tag2") | Has any of the tags (includes nested) |
file.hasLink("Note") | Has link to note |
file.hasProperty("name") | Has frontmatter property |
file.inFolder("Projects") | In folder or subfolder |
File properties
| Property | Type | Description |
|---|
file.name | String | File name |
file.basename | String | Name without extension |
file.path | String | Full path from vault root |
file.folder | String | Parent folder path |
file.ext | String | File extension |
file.size | Number | Size in bytes |
file.ctime | Date | Created time |
file.mtime | Date | Modified time |
file.tags | List | All tags |
file.links | List | Internal links |
Note properties
Frontmatter properties accessed as note.property or just property:
filters:
and:
- 'status == "active"'
- 'note.priority >= 3'
Formulas
formulas:
total: "price * quantity"
status_icon: 'if(done, "✅", "⏳")'
formatted_price: 'if(price, price.toFixed(2) + " dollars")'
created: 'file.ctime.format("YYYY-MM-DD")'
days_old: '(now() - file.ctime).days'
days_until_due: 'if(due_date, (date(due_date) - today()).days, "")'
Global functions
| Function | Description |
|---|
date(string) | Parse date (YYYY-MM-DD HH:mm:ss) |
now() | Current datetime |
today() | Current date (time = 00:00:00) |
if(cond, true, false?) | Conditional |
min(n1, n2, ...) | Smallest number |
max(n1, n2, ...) | Largest number |
number(any) | Convert to number |
link(path, display?) | Create link |
list(element) | Wrap in list |
Date arithmetic
"date + \"1M\""
"now() + \"1 day\""
"today() + \"7d\""
"(now() - file.ctime).days"
Duration units: y/year/years, M/month/months, d/day/days, w/week/weeks, h/hour/hours, m/minute/minutes, s/second/seconds
String functions
contains(), startsWith(), endsWith(), lower(), trim(), replace(), split(), slice(), isEmpty(), .length
Number functions
abs(), ceil(), floor(), round(digits?), toFixed(precision)
List functions
contains(), filter(), map(), join(), sort(), unique(), flat(), isEmpty(), .length
Views
views:
- type: table
name: "My View"
limit: 10
order:
- file.name
- status
- due_date
filters:
'status != "done"'
groupBy:
property: status
direction: ASC
summaries:
price: Sum
count: Average
Summary functions
| Name | Input | Description |
|---|
Average | Number | Mean |
Min | Number | Smallest |
Max | Number | Largest |
Sum | Number | Sum |
Range | Number | Max - Min |
Median | Number | Median |
Earliest | Date | Earliest date |
Latest | Date | Latest date |
Empty | Any | Count of empty values |
Filled | Any | Count of non-empty values |
Unique | Any | Count of unique values |
Example: Task tracker
filters:
and:
- file.hasTag("task")
- 'file.ext == "md"'
formulas:
days_until_due: 'if(due, (date(due) - today()).days, "")'
priority_label: 'if(priority == 1, "🔴 High", if(priority == 2, "🟡 Medium", "🟢 Low"))'
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
JSON Canvas Reference
Canvas files (.canvas) are JSON following the JSON Canvas Spec 1.0.
{
"nodes": [
{"id": "aabb11223344", "type": "text", "x": 0, "y": 0, "width": 300, "height": 150, "text": "# Hello\nMarkdown content"},
{"id": "ccdd55667788", "type": "file", "x": 400, "y": 0, "width": 300, "height": 200, "file":
Node types
| Type | Required fields | Description |
|---|
text | text | Markdown content |
file | file, optional subpath | Reference to vault file |
link | url | External URL |
group | optional label, background, backgroundStyle | Visual container |
Common fields
All nodes: id (16-char hex), type, x, y, width, height, optional color (1-6 or hex).
Edges: id, fromNode, toNode, optional fromSide/toSide (top/right/bottom/left), fromEnd/toEnd (none/arrow), label, color.
Example: Project notes
filters:
and:
- file.inFolder("Projects")
- 'file.ext == "md"'
formulas:
last_updated: 'file.mtime.relative()'
link_count: 'file.links.length'
views:
- type: table
name: "All Projects"
order:
- file.name
- status
- formula.last_updated
- formula.link_count
groupBy:
property: status
direction: ASC