mercury-agent 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +438 -0
  3. package/container/Dockerfile +127 -0
  4. package/container/Dockerfile.base +109 -0
  5. package/container/Dockerfile.power +17 -0
  6. package/container/agent-package.json +8 -0
  7. package/container/build.sh +54 -0
  8. package/docs/TODOS.md +147 -0
  9. package/docs/auth/dashboard.md +28 -0
  10. package/docs/auth/overview.md +109 -0
  11. package/docs/auth/whatsapp.md +173 -0
  12. package/docs/configuration.md +54 -0
  13. package/docs/container-lifecycle.md +349 -0
  14. package/docs/context-architecture.md +87 -0
  15. package/docs/deployment.md +199 -0
  16. package/docs/extensions.md +375 -0
  17. package/docs/graceful-shutdown.md +62 -0
  18. package/docs/kb-distillation.md +77 -0
  19. package/docs/media/overview.md +140 -0
  20. package/docs/media/whatsapp.md +171 -0
  21. package/docs/memory.md +137 -0
  22. package/docs/permissions.md +217 -0
  23. package/docs/pipeline.md +228 -0
  24. package/docs/prd-chat-memory.md +76 -0
  25. package/docs/prd-config-load.md +82 -0
  26. package/docs/rate-limiting.md +166 -0
  27. package/docs/scheduler.md +288 -0
  28. package/docs/setup-discord.md +100 -0
  29. package/docs/setup-slack.md +119 -0
  30. package/docs/setup-whatsapp.md +94 -0
  31. package/docs/subagents.md +166 -0
  32. package/docs/web-search.md +62 -0
  33. package/examples/extensions/README.md +12 -0
  34. package/examples/extensions/charts/index.ts +13 -0
  35. package/examples/extensions/charts/skill/SKILL.md +98 -0
  36. package/examples/extensions/gws/README.md +52 -0
  37. package/examples/extensions/gws/index.ts +106 -0
  38. package/examples/extensions/gws/skill/SKILL.md +57 -0
  39. package/examples/extensions/gws/skill/references/calendar.md +101 -0
  40. package/examples/extensions/gws/skill/references/docs.md +65 -0
  41. package/examples/extensions/gws/skill/references/drive.md +79 -0
  42. package/examples/extensions/gws/skill/references/gmail.md +85 -0
  43. package/examples/extensions/gws/skill/references/sheets.md +60 -0
  44. package/examples/extensions/napkin/index.ts +821 -0
  45. package/examples/extensions/napkin/prompts/consolidation-monthly.md +73 -0
  46. package/examples/extensions/napkin/prompts/consolidation-weekly.md +67 -0
  47. package/examples/extensions/napkin/prompts/kb-distillation.md +176 -0
  48. package/examples/extensions/napkin/skill/SKILL.md +728 -0
  49. package/examples/extensions/pdf/index.ts +23 -0
  50. package/examples/extensions/pdf/skill/LICENSE.txt +30 -0
  51. package/examples/extensions/pdf/skill/SKILL.md +314 -0
  52. package/examples/extensions/pdf/skill/forms.md +294 -0
  53. package/examples/extensions/pdf/skill/reference.md +612 -0
  54. package/examples/extensions/pdf/skill/scripts/check_bounding_boxes.py +65 -0
  55. package/examples/extensions/pdf/skill/scripts/check_fillable_fields.py +11 -0
  56. package/examples/extensions/pdf/skill/scripts/convert_pdf_to_images.py +33 -0
  57. package/examples/extensions/pdf/skill/scripts/create_validation_image.py +37 -0
  58. package/examples/extensions/pdf/skill/scripts/extract_form_field_info.py +122 -0
  59. package/examples/extensions/pdf/skill/scripts/extract_form_structure.py +115 -0
  60. package/examples/extensions/pdf/skill/scripts/fill_fillable_fields.py +98 -0
  61. package/examples/extensions/pdf/skill/scripts/fill_pdf_form_with_annotations.py +107 -0
  62. package/examples/extensions/permission-guard/index.ts +65 -0
  63. package/examples/extensions/pinchtab/index.ts +199 -0
  64. package/examples/extensions/pinchtab/lib/session-injector.ts +144 -0
  65. package/examples/extensions/pinchtab/skill/SKILL.md +224 -0
  66. package/examples/extensions/pinchtab/skill/TRUST.md +69 -0
  67. package/examples/extensions/pinchtab/skill/references/api.md +297 -0
  68. package/examples/extensions/pinchtab/skill/references/env.md +45 -0
  69. package/examples/extensions/pinchtab/skill/references/profiles.md +107 -0
  70. package/examples/extensions/tradestation/host/refresh.ts +102 -0
  71. package/examples/extensions/tradestation/index.ts +153 -0
  72. package/examples/extensions/tradestation/skill/SKILL.md +67 -0
  73. package/examples/extensions/tradestation/skill/scripts/ts-cli.ts +111 -0
  74. package/examples/extensions/voice-synth/index.ts +94 -0
  75. package/examples/extensions/voice-synth/skill/SKILL.md +38 -0
  76. package/examples/extensions/voice-transcribe/index.ts +381 -0
  77. package/examples/extensions/voice-transcribe/requirements.txt +8 -0
  78. package/examples/extensions/voice-transcribe/scripts/transcribe.py +179 -0
  79. package/examples/extensions/voice-transcribe/skill/SKILL.md +53 -0
  80. package/examples/extensions/web-search/index.ts +22 -0
  81. package/examples/extensions/web-search/skill/SKILL.md +114 -0
  82. package/examples/extensions/web-search/skill/references/apartments.md +178 -0
  83. package/examples/extensions/web-search/skill/references/car-purchase.md +132 -0
  84. package/examples/extensions/web-search/skill/references/car-rental.md +113 -0
  85. package/examples/extensions/web-search/skill/references/flights.md +133 -0
  86. package/examples/extensions/web-search/skill/references/hotels.md +148 -0
  87. package/examples/extensions/yahoo-mail/cli/bun.lock +66 -0
  88. package/examples/extensions/yahoo-mail/cli/package.json +13 -0
  89. package/examples/extensions/yahoo-mail/cli/ymail.mjs +353 -0
  90. package/examples/extensions/yahoo-mail/index.ts +57 -0
  91. package/examples/extensions/yahoo-mail/skill/SKILL.md +78 -0
  92. package/package.json +106 -0
  93. package/resources/agents/explore.md +50 -0
  94. package/resources/agents/worker.md +24 -0
  95. package/resources/builtin-extensions.txt +3 -0
  96. package/resources/connection-env-vars.json +25 -0
  97. package/resources/extensions/.gitkeep +0 -0
  98. package/resources/pi-extensions/subagent/agents.ts +126 -0
  99. package/resources/pi-extensions/subagent/index.ts +964 -0
  100. package/resources/profiles/coding/AGENTS.md +43 -0
  101. package/resources/profiles/coding/mercury-profile.yaml +15 -0
  102. package/resources/profiles/general/AGENTS.md +31 -0
  103. package/resources/profiles/general/mercury-profile.yaml +15 -0
  104. package/resources/profiles/research/AGENTS.md +40 -0
  105. package/resources/profiles/research/mercury-profile.yaml +15 -0
  106. package/resources/skills/config/SKILL.md +25 -0
  107. package/resources/skills/context/SKILL.md +33 -0
  108. package/resources/skills/conversation-recap/SKILL.md +19 -0
  109. package/resources/skills/media/SKILL.md +27 -0
  110. package/resources/skills/mutes/SKILL.md +31 -0
  111. package/resources/skills/permissions/SKILL.md +19 -0
  112. package/resources/skills/preferences/SKILL.md +31 -0
  113. package/resources/skills/recall/SKILL.md +24 -0
  114. package/resources/skills/roles/SKILL.md +18 -0
  115. package/resources/skills/spaces/SKILL.md +18 -0
  116. package/resources/skills/tasks/SKILL.md +45 -0
  117. package/resources/templates/AGENTS.md +157 -0
  118. package/resources/templates/env.template +34 -0
  119. package/resources/templates/mercury.example.yaml +75 -0
  120. package/src/adapters/discord-native.ts +534 -0
  121. package/src/adapters/discord.ts +38 -0
  122. package/src/adapters/setup.ts +89 -0
  123. package/src/adapters/slack.ts +9 -0
  124. package/src/adapters/whatsapp-media.ts +337 -0
  125. package/src/adapters/whatsapp.ts +629 -0
  126. package/src/agent/api-socket.ts +127 -0
  127. package/src/agent/container-entry.ts +967 -0
  128. package/src/agent/container-error.ts +49 -0
  129. package/src/agent/container-runner.ts +1272 -0
  130. package/src/agent/model-capabilities-core.ts +23 -0
  131. package/src/agent/model-capabilities.ts +231 -0
  132. package/src/agent/pi-failure-class.ts +83 -0
  133. package/src/agent/pi-jsonl-parser.ts +306 -0
  134. package/src/agent/preferences-prompt.ts +20 -0
  135. package/src/agent/user-error-messages.ts +78 -0
  136. package/src/bridges/discord.ts +171 -0
  137. package/src/bridges/slack.ts +177 -0
  138. package/src/bridges/teams.ts +160 -0
  139. package/src/bridges/telegram.ts +571 -0
  140. package/src/bridges/whatsapp.ts +290 -0
  141. package/src/chat-shim.ts +259 -0
  142. package/src/cli/mercury.ts +2508 -0
  143. package/src/cli/mrctl-http.ts +27 -0
  144. package/src/cli/mrctl.ts +611 -0
  145. package/src/cli/whatsapp-auth.ts +260 -0
  146. package/src/config-file.ts +397 -0
  147. package/src/config-model-chain.ts +30 -0
  148. package/src/config.ts +316 -0
  149. package/src/core/api-types.ts +58 -0
  150. package/src/core/api.ts +105 -0
  151. package/src/core/commands.ts +76 -0
  152. package/src/core/conversation.ts +47 -0
  153. package/src/core/handler.ts +206 -0
  154. package/src/core/media.ts +200 -0
  155. package/src/core/mute-duration.ts +22 -0
  156. package/src/core/outbox.ts +76 -0
  157. package/src/core/permissions.ts +192 -0
  158. package/src/core/profiles.ts +245 -0
  159. package/src/core/rate-limiter.ts +127 -0
  160. package/src/core/router.ts +191 -0
  161. package/src/core/routes/chat.ts +172 -0
  162. package/src/core/routes/config-builtin.ts +107 -0
  163. package/src/core/routes/config.ts +81 -0
  164. package/src/core/routes/connections.ts +190 -0
  165. package/src/core/routes/console.ts +668 -0
  166. package/src/core/routes/control.ts +46 -0
  167. package/src/core/routes/conversations.ts +66 -0
  168. package/src/core/routes/dashboard.ts +2491 -0
  169. package/src/core/routes/extensions.ts +37 -0
  170. package/src/core/routes/index.ts +14 -0
  171. package/src/core/routes/media.ts +72 -0
  172. package/src/core/routes/messages.ts +37 -0
  173. package/src/core/routes/mutes.ts +89 -0
  174. package/src/core/routes/prefs.ts +95 -0
  175. package/src/core/routes/roles.ts +125 -0
  176. package/src/core/routes/spaces.ts +60 -0
  177. package/src/core/routes/storage.ts +126 -0
  178. package/src/core/routes/tasks.ts +189 -0
  179. package/src/core/routes/tradestation.ts +268 -0
  180. package/src/core/routes/tts.ts +51 -0
  181. package/src/core/runtime.ts +1140 -0
  182. package/src/core/space-queue.ts +103 -0
  183. package/src/core/storage-cleanup.ts +140 -0
  184. package/src/core/storage-guard.ts +24 -0
  185. package/src/core/task-scheduler.ts +132 -0
  186. package/src/core/telegram-format.ts +178 -0
  187. package/src/core/trigger.ts +142 -0
  188. package/src/dashboard/index.html +729 -0
  189. package/src/dashboard/tokens.css +53 -0
  190. package/src/extensions/api.ts +252 -0
  191. package/src/extensions/catalog.ts +117 -0
  192. package/src/extensions/config-registry.ts +83 -0
  193. package/src/extensions/context.ts +36 -0
  194. package/src/extensions/hooks.ts +156 -0
  195. package/src/extensions/image-builder.ts +617 -0
  196. package/src/extensions/installer.ts +306 -0
  197. package/src/extensions/jobs.ts +122 -0
  198. package/src/extensions/loader.ts +271 -0
  199. package/src/extensions/permission-guard.ts +52 -0
  200. package/src/extensions/reserved.ts +28 -0
  201. package/src/extensions/skills.ts +123 -0
  202. package/src/extensions/types.ts +462 -0
  203. package/src/logger.ts +174 -0
  204. package/src/main.ts +586 -0
  205. package/src/server.ts +391 -0
  206. package/src/storage/db.ts +1624 -0
  207. package/src/storage/memory.ts +45 -0
  208. package/src/storage/pi-auth.ts +95 -0
  209. package/src/text/markdown.ts +117 -0
  210. package/src/text/rtl.ts +38 -0
  211. package/src/tradestation/host-api.ts +77 -0
  212. package/src/tradestation/pending-orders.ts +69 -0
  213. package/src/tts/azure.ts +52 -0
  214. package/src/tts/google.ts +128 -0
  215. package/src/tts/index.ts +8 -0
  216. package/src/tts/language.ts +20 -0
  217. package/src/tts/synthesize.ts +133 -0
  218. package/src/types.ts +295 -0
@@ -0,0 +1,728 @@
1
+ ---
2
+ name: napkin
3
+ 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.
4
+ ---
5
+
6
+ # napkin
7
+
8
+ CLI for Obsidian vaults. Operates directly on markdown files — no Obsidian app, no Electron, no Catalyst license.
9
+
10
+ Install: `npm install -g napkin-ai`
11
+
12
+ **IMPORTANT**: Always pass `--vault $NAPKIN_VAULT` to every napkin command. The vault lives in the `knowledge/` subdirectory, not the workspace root.
13
+
14
+ ## Reading this vault's memory notes
15
+
16
+ This vault is maintained by an automatic distillation loop. Entity notes (under `people/`, `projects/`, `references/`) follow a temporal convention — read them this way:
17
+
18
+ - **`NAPKIN.md`** is the map of the vault. Start here for a quick overview of who and what is remembered.
19
+ - **Frontmatter + `## Current View`** hold the **authoritative present value** of every fact. When the user asks "what is X now?", answer from here.
20
+ - **`## 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?".
21
+
22
+ One file per entity, one directory per category — a person is always a file inside `people/`, never a section in a flat `people.md`.
23
+
24
+ ### Episodes (`episodes/`)
25
+
26
+ 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.
27
+
28
+ - Episodes may appear in your context as `<active_episodes>` XML — these are automatically injected when the user's message is relevant.
29
+ - 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).
30
+ - You can **resolve** episodes when the user indicates closure: set `status: resolved` in the frontmatter.
31
+ - Episode `status` values: `active` (current), `cooling` (not mentioned recently — set by consolidation, not by you), `resolved` (explicitly closed), `faded` (long-dormant — set by consolidation).
32
+ - `## History` in episodes is append-only, same as entity files.
33
+
34
+ ### Memory suggestions (`.memory-suggestions.md`)
35
+
36
+ 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.
37
+
38
+ ## Syntax
39
+
40
+ napkin uses standard CLI flags. Quote values with spaces:
41
+
42
+ ```bash
43
+ napkin --vault $NAPKIN_VAULT create --name "My Note" --content "Hello world"
44
+ ```
45
+
46
+ ### Global flags
47
+
48
+ | Flag | Description |
49
+ |------|-------------|
50
+ | `--json` | Output as JSON (use this for programmatic access) |
51
+ | `-q, --quiet` | Suppress output |
52
+ | `--vault <path>` | Vault path (default: auto-detect by walking up from cwd looking for `.obsidian/`) |
53
+ | `--copy` | Copy output to clipboard |
54
+
55
+ ### File targeting
56
+
57
+ - `--file <name>` — resolves like a wikilink (name only, no path or extension needed)
58
+ - `--path <path>` — exact path from vault root, e.g. `Projects/note.md`
59
+
60
+ ## Commands
61
+
62
+ ### Vault
63
+
64
+ ```bash
65
+ napkin --vault $NAPKIN_VAULT vault # Vault info (name, path, files, folders, size)
66
+ napkin --vault $NAPKIN_VAULT version # CLI version
67
+ ```
68
+
69
+ ### Files & folders — `napkin file`
70
+
71
+ ```bash
72
+ napkin --vault $NAPKIN_VAULT file info <name> # File info (path, size, dates)
73
+ napkin --vault $NAPKIN_VAULT file list # List all files
74
+ napkin --vault $NAPKIN_VAULT file list --ext md # Filter by extension
75
+ napkin --vault $NAPKIN_VAULT file list --folder Projects # Filter by folder
76
+ napkin --vault $NAPKIN_VAULT file list --total # Count files
77
+ napkin --vault $NAPKIN_VAULT file folder <path> # Folder info (files, folders, size)
78
+ napkin --vault $NAPKIN_VAULT file folder <path> --info files # Just the file count
79
+ napkin --vault $NAPKIN_VAULT file folders # List all folders
80
+ napkin --vault $NAPKIN_VAULT file folders --total # Count folders
81
+ ```
82
+
83
+ ### Read & write
84
+
85
+ ```bash
86
+ napkin --vault $NAPKIN_VAULT read <file> # Read file contents
87
+ napkin --vault $NAPKIN_VAULT create --name "Note" --content "# Hello"
88
+ napkin --vault $NAPKIN_VAULT create --name "Note" --path "Projects" --template "Meeting Note"
89
+ napkin --vault $NAPKIN_VAULT append --file "Note" --content "New line at end"
90
+ napkin --vault $NAPKIN_VAULT prepend --file "Note" --content "New line after frontmatter"
91
+ napkin --vault $NAPKIN_VAULT move --file "Note" --to Archive
92
+ napkin --vault $NAPKIN_VAULT rename --file "Note" --name "Renamed Note"
93
+ napkin --vault $NAPKIN_VAULT delete --file "Note" # Move to .trash
94
+ napkin --vault $NAPKIN_VAULT delete --file "Note" --permanent # Delete permanently
95
+ ```
96
+
97
+ ### Daily notes — `napkin daily`
98
+
99
+ Reads config from `.obsidian/daily-notes.json` (folder, format, template).
100
+
101
+ ```bash
102
+ napkin --vault $NAPKIN_VAULT daily today # Create today's daily note (from template if configured)
103
+ napkin --vault $NAPKIN_VAULT daily path # Print daily note path
104
+ napkin --vault $NAPKIN_VAULT daily read # Print daily note contents
105
+ napkin --vault $NAPKIN_VAULT daily append --content "- [ ] Buy groceries"
106
+ napkin --vault $NAPKIN_VAULT daily prepend --content "## Morning"
107
+ ```
108
+
109
+ ### Search
110
+
111
+ Full-text search with relevance ranking (fuzzy matching, prefix search, filename boosting).
112
+
113
+ ```bash
114
+ napkin --vault $NAPKIN_VAULT search "meeting" # Find files matching text
115
+ napkin --vault $NAPKIN_VAULT search --query "meeting" # Same, using flag
116
+ napkin --vault $NAPKIN_VAULT search "TODO" --path Projects # Limit to folder
117
+ napkin --vault $NAPKIN_VAULT search "bug" --total # Count matches
118
+ napkin --vault $NAPKIN_VAULT search "deploy" --limit 5 # Top 5 results
119
+ napkin --vault $NAPKIN_VAULT search "TODO" --context # Grep-style file:line:text output
120
+ ```
121
+
122
+ ### Tasks — `napkin task`
123
+
124
+ ```bash
125
+ napkin --vault $NAPKIN_VAULT task list # List all tasks
126
+ napkin --vault $NAPKIN_VAULT task list --todo # Incomplete only
127
+ napkin --vault $NAPKIN_VAULT task list --done # Completed only
128
+ napkin --vault $NAPKIN_VAULT task list --daily # Today's daily note tasks
129
+ napkin --vault $NAPKIN_VAULT task list --file "Project A" # Tasks in specific file
130
+ napkin --vault $NAPKIN_VAULT task list --verbose # Group by file with line numbers
131
+ napkin --vault $NAPKIN_VAULT task list --total # Count tasks
132
+ napkin --vault $NAPKIN_VAULT task show --file "note" --line 3 # Show task info
133
+ napkin --vault $NAPKIN_VAULT task show --file "note" --line 3 --toggle # Toggle ✓/○
134
+ napkin --vault $NAPKIN_VAULT task show --file "note" --line 3 --done # Mark done
135
+ napkin --vault $NAPKIN_VAULT task show --ref "note.md:3" --todo # Mark todo (file:line shorthand)
136
+ ```
137
+
138
+ ### Tags — `napkin tag`
139
+
140
+ ```bash
141
+ napkin --vault $NAPKIN_VAULT tag list # List all tags
142
+ napkin --vault $NAPKIN_VAULT tag list --counts # With occurrence counts
143
+ napkin --vault $NAPKIN_VAULT tag list --sort count # Sort by frequency
144
+ napkin --vault $NAPKIN_VAULT tag info --name "project" # Tag info (count)
145
+ napkin --vault $NAPKIN_VAULT tag info --name "project" --verbose # With file list
146
+ napkin --vault $NAPKIN_VAULT tag aliases # List all aliases in vault
147
+ napkin --vault $NAPKIN_VAULT tag aliases --file "note" # Aliases for a file
148
+ napkin --vault $NAPKIN_VAULT tag aliases --total # Count aliases
149
+ ```
150
+
151
+ ### Properties — `napkin property`
152
+
153
+ ```bash
154
+ napkin --vault $NAPKIN_VAULT property list # List all property names in vault
155
+ napkin --vault $NAPKIN_VAULT property list --file "note" # Properties for a specific file
156
+ napkin --vault $NAPKIN_VAULT property list --counts # With occurrence counts
157
+ napkin --vault $NAPKIN_VAULT property read --file "note" --name title
158
+ napkin --vault $NAPKIN_VAULT property set --file "note" --name status --value done
159
+ napkin --vault $NAPKIN_VAULT property remove --file "note" --name status
160
+ ```
161
+
162
+ ### Links — `napkin link`
163
+
164
+ ```bash
165
+ napkin --vault $NAPKIN_VAULT link back --file "note" # Files linking TO this file
166
+ napkin --vault $NAPKIN_VAULT link out --file "note" # Outgoing links FROM this file
167
+ napkin --vault $NAPKIN_VAULT link unresolved # Broken links (target doesn't exist)
168
+ napkin --vault $NAPKIN_VAULT link orphans # Files with no incoming links
169
+ napkin --vault $NAPKIN_VAULT link deadends # Files with no outgoing links
170
+ ```
171
+
172
+ ### Outline
173
+
174
+ ```bash
175
+ napkin --vault $NAPKIN_VAULT outline --file "note" # Heading tree
176
+ napkin --vault $NAPKIN_VAULT outline --file "note" --format md # Markdown list
177
+ napkin --vault $NAPKIN_VAULT outline --file "note" --format json # JSON array
178
+ ```
179
+
180
+ ### Templates — `napkin template`
181
+
182
+ ```bash
183
+ napkin --vault $NAPKIN_VAULT template list # List templates
184
+ napkin --vault $NAPKIN_VAULT template read --name "Daily Note" # Read template content
185
+ napkin --vault $NAPKIN_VAULT template read --name "Meeting" --resolve --title "Standup" # Resolve variables
186
+ napkin --vault $NAPKIN_VAULT template insert --file "note" --name "Template" # Insert template into file
187
+ ```
188
+
189
+ ### Bookmarks — `napkin bookmark`
190
+
191
+ ```bash
192
+ napkin --vault $NAPKIN_VAULT bookmark list # List bookmarks
193
+ napkin --vault $NAPKIN_VAULT bookmark list --total # Count bookmarks
194
+ napkin --vault $NAPKIN_VAULT bookmark add --file "note" # Bookmark a file
195
+ napkin --vault $NAPKIN_VAULT bookmark add --folder "Projects" # Bookmark a folder
196
+ napkin --vault $NAPKIN_VAULT bookmark add --search "TODO" # Bookmark a search
197
+ napkin --vault $NAPKIN_VAULT bookmark add --url "https://example.com" --title "Example"
198
+ ```
199
+
200
+ ### Bases — `napkin base`
201
+
202
+ Query vault files using Obsidian Bases `.base` files (YAML-defined filters over frontmatter properties, powered by SQLite in-memory).
203
+
204
+ ```bash
205
+ napkin --vault $NAPKIN_VAULT base list # List .base files
206
+ napkin --vault $NAPKIN_VAULT base views --file "projects" # List views in a base
207
+ napkin --vault $NAPKIN_VAULT base query --file "projects" # Query default view
208
+ napkin --vault $NAPKIN_VAULT base query --file "projects" --view "Active" # Query named view
209
+ napkin --vault $NAPKIN_VAULT base query --file "projects" --format paths # Just file paths
210
+ napkin --vault $NAPKIN_VAULT base query --file "projects" --format csv # CSV output
211
+ napkin --vault $NAPKIN_VAULT base create --file "projects" --name "New Item" # Create item in base
212
+ ```
213
+
214
+ ### Canvas — `napkin canvas`
215
+
216
+ Read and write JSON Canvas files (`.canvas`) — nodes, edges, groups.
217
+
218
+ ```bash
219
+ napkin --vault $NAPKIN_VAULT canvas list # List .canvas files
220
+ napkin --vault $NAPKIN_VAULT canvas list --total # Count canvases
221
+ napkin --vault $NAPKIN_VAULT canvas read --file "Board" # Dump canvas (nodes + edges)
222
+ napkin --vault $NAPKIN_VAULT canvas nodes --file "Board" # List all nodes
223
+ napkin --vault $NAPKIN_VAULT canvas nodes --file "Board" --type text # Filter by type
224
+ napkin --vault $NAPKIN_VAULT canvas create --file "Board" # Create empty canvas
225
+ napkin --vault $NAPKIN_VAULT canvas create --file "Board" --path "Projects"
226
+ napkin --vault $NAPKIN_VAULT canvas add-node --file "Board" --type text --text "# Hello"
227
+ napkin --vault $NAPKIN_VAULT canvas add-node --file "Board" --type file --note-file "Notes/note.md"
228
+ napkin --vault $NAPKIN_VAULT canvas add-node --file "Board" --type link --url "https://example.com"
229
+ napkin --vault $NAPKIN_VAULT canvas add-node --file "Board" --type group --label "My Group"
230
+ napkin --vault $NAPKIN_VAULT canvas add-node --file "Board" --type text --text "Positioned" --x 100 --y 200
231
+ napkin --vault $NAPKIN_VAULT canvas add-edge --file "Board" --from abc1 --to def2 --label "relates to"
232
+ napkin --vault $NAPKIN_VAULT canvas remove-node --file "Board" --id abc1 # Removes node + connected edges
233
+ ```
234
+
235
+ Node IDs are 16-char hex. `--from`/`--to`/`--id` accept ID prefixes for convenience.
236
+ Node types: `text`, `file`, `link`, `group`. Colors: `1`-`6` or hex.
237
+ New nodes auto-position to the right of existing content.
238
+
239
+ ### Word count
240
+
241
+ ```bash
242
+ napkin --vault $NAPKIN_VAULT wordcount --file "note" # Words + characters
243
+ napkin --vault $NAPKIN_VAULT wordcount --file "note" --words # Words only
244
+ napkin --vault $NAPKIN_VAULT wordcount --file "note" --characters # Characters only
245
+ ```
246
+
247
+ ### Agent onboarding
248
+
249
+ ```bash
250
+ napkin --vault $NAPKIN_VAULT onboard # Print instructions for CLAUDE.md/AGENTS.md
251
+ ```
252
+
253
+ ## JSON output
254
+
255
+ Every command supports `--json`. Always use `--json` for programmatic access:
256
+
257
+ ```bash
258
+ napkin --vault $NAPKIN_VAULT task list --todo --json
259
+ # {"tasks": [{"text": "Buy groceries", "done": false, "file": "Daily/2024-01-15.md", "line": 5}, ...]}
260
+
261
+ napkin --vault $NAPKIN_VAULT search "deploy" --json
262
+ # {"files": ["Projects/Deploy Guide.md", "Notes/CI-CD.md"]}
263
+
264
+ napkin --vault $NAPKIN_VAULT property read --file "note" --name status --json
265
+ # {"value": "done"}
266
+ ```
267
+
268
+ ## Common workflows
269
+
270
+ ### Morning standup prep
271
+
272
+ ```bash
273
+ napkin --vault $NAPKIN_VAULT daily read --json # What did I write yesterday?
274
+ napkin --vault $NAPKIN_VAULT task list --todo --json # What's pending?
275
+ napkin --vault $NAPKIN_VAULT search "blocker" --json # Any blockers?
276
+ ```
277
+
278
+ ### Project overview
279
+
280
+ ```bash
281
+ napkin --vault $NAPKIN_VAULT file list --folder Projects --json # List project files
282
+ napkin --vault $NAPKIN_VAULT tag list --counts --json # Tag distribution
283
+ napkin --vault $NAPKIN_VAULT link orphans --json # Forgotten files
284
+ napkin --vault $NAPKIN_VAULT link unresolved --json # Broken links to fix
285
+ ```
286
+
287
+ ### Note management
288
+
289
+ ```bash
290
+ napkin --vault $NAPKIN_VAULT create --name "Meeting Notes" --template "Meeting Note" --path "Meetings"
291
+ napkin --vault $NAPKIN_VAULT property set --file "Meeting Notes" --name attendees --value "Alice, Bob"
292
+ napkin --vault $NAPKIN_VAULT append --file "Meeting Notes" --content "- [ ] Follow up on deployment"
293
+ ```
294
+
295
+ ---
296
+
297
+ # Obsidian Markdown Reference
298
+
299
+ napkin operates on Obsidian Flavored Markdown files. This section covers the syntax for creating valid content.
300
+
301
+ ## Properties (frontmatter)
302
+
303
+ YAML frontmatter at the start of a note:
304
+
305
+ ```yaml
306
+ ---
307
+ title: My Note
308
+ date: 2024-01-15
309
+ tags:
310
+ - project
311
+ - important
312
+ aliases:
313
+ - My Note
314
+ - Alternative Name
315
+ cssclasses:
316
+ - custom-class
317
+ status: in-progress
318
+ rating: 4.5
319
+ completed: false
320
+ ---
321
+ ```
322
+
323
+ ### Property types
324
+
325
+ | Type | Example |
326
+ |------|---------|
327
+ | Text | `title: My Title` |
328
+ | Number | `rating: 4.5` |
329
+ | Checkbox | `completed: true` |
330
+ | Date | `date: 2024-01-15` |
331
+ | Date & Time | `due: 2024-01-15T14:30:00` |
332
+ | List | `tags: [one, two]` or YAML list |
333
+ | Links | `related: "[[Other Note]]"` |
334
+
335
+ Default properties: `tags`, `aliases`, `cssclasses`
336
+
337
+ ## Internal links (wikilinks)
338
+
339
+ ```markdown
340
+ [[Note Name]] Link to note
341
+ [[Note Name|Display Text]] Custom display text
342
+ [[Note Name#Heading]] Link to heading
343
+ [[Note Name#^block-id]] Link to block
344
+ [[#Heading in same note]] Same-file heading link
345
+ ```
346
+
347
+ ## Embeds
348
+
349
+ ```markdown
350
+ ![[Note Name]] Embed entire note
351
+ ![[Note Name#Heading]] Embed section
352
+ ![[image.png]] Embed image
353
+ ![[image.png|300]] Image with width
354
+ ![[document.pdf]] Embed PDF
355
+ ![[document.pdf#page=3]] PDF at page
356
+ ```
357
+
358
+ ## Tags
359
+
360
+ ```markdown
361
+ #tag
362
+ #nested/tag
363
+ #tag-with-dashes
364
+
365
+ # In frontmatter:
366
+ tags:
367
+ - tag1
368
+ - nested/tag2
369
+ ```
370
+
371
+ Tags can contain letters, numbers (not first), underscores, hyphens, forward slashes.
372
+
373
+ ## Task lists
374
+
375
+ ```markdown
376
+ - [ ] Incomplete task
377
+ - [x] Completed task
378
+ - [ ] Parent task
379
+ - [ ] Subtask
380
+ - [x] Done subtask
381
+ ```
382
+
383
+ ## Callouts
384
+
385
+ ```markdown
386
+ > [!note]
387
+ > This is a note callout.
388
+
389
+ > [!warning] Custom Title
390
+ > Warning with custom title.
391
+
392
+ > [!faq]- Collapsed by default
393
+ > Hidden until expanded.
394
+
395
+ > [!tip]+ Expanded by default
396
+ > Visible but collapsible.
397
+ ```
398
+
399
+ 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`
400
+
401
+ ## Text formatting
402
+
403
+ | Style | Syntax |
404
+ |-------|--------|
405
+ | Bold | `**text**` |
406
+ | Italic | `*text*` |
407
+ | Bold + Italic | `***text***` |
408
+ | Strikethrough | `~~text~~` |
409
+ | Highlight | `==text==` |
410
+ | Inline code | `` `code` `` |
411
+
412
+ ## Code blocks
413
+
414
+ ````markdown
415
+ ```javascript
416
+ function hello() {
417
+ console.log("Hello");
418
+ }
419
+ ```
420
+ ````
421
+
422
+ ## Math (LaTeX)
423
+
424
+ ```markdown
425
+ Inline: $e^{i\pi} + 1 = 0$
426
+
427
+ Block:
428
+ $$
429
+ \sum_{i=1}^{n} x_i
430
+ $$
431
+ ```
432
+
433
+ ## Block references
434
+
435
+ ```markdown
436
+ This paragraph can be linked to. ^my-block-id
437
+
438
+ Link to it: [[Note#^my-block-id]]
439
+ Embed it: ![[Note#^my-block-id]]
440
+ ```
441
+
442
+ ## Comments
443
+
444
+ ```markdown
445
+ This is visible %%but this is hidden%% text.
446
+
447
+ %%
448
+ This entire block is hidden.
449
+ %%
450
+ ```
451
+
452
+ ---
453
+
454
+ # Bases Reference
455
+
456
+ Bases are YAML-defined views that query vault files using their frontmatter properties. Saved as `.base` files.
457
+
458
+ ## Structure
459
+
460
+ ```yaml
461
+ filters:
462
+ and:
463
+ - file.hasTag("project")
464
+ - 'status != "done"'
465
+ formulas:
466
+ days_left: '(date(due) - today()).days'
467
+ properties:
468
+ status:
469
+ displayName: Status
470
+ views:
471
+ - type: table
472
+ name: "Active"
473
+ order:
474
+ - file.name
475
+ - status
476
+ limit: 20
477
+ ```
478
+
479
+ ## Filters
480
+
481
+ ```yaml
482
+ # Single filter
483
+ filters:
484
+ file.hasTag("project")
485
+
486
+ # AND
487
+ filters:
488
+ and:
489
+ - file.hasTag("project")
490
+ - 'status != "done"'
491
+
492
+ # OR
493
+ filters:
494
+ or:
495
+ - file.hasTag("book")
496
+ - file.hasTag("article")
497
+
498
+ # NOT
499
+ filters:
500
+ not:
501
+ - file.hasTag("archived")
502
+
503
+ # Nested
504
+ filters:
505
+ or:
506
+ - file.hasTag("urgent")
507
+ - and:
508
+ - file.hasTag("project")
509
+ - 'priority >= 3'
510
+ ```
511
+
512
+ ### Filter operators
513
+
514
+ | Operator | Description |
515
+ |----------|-------------|
516
+ | `==` | equals |
517
+ | `!=` | not equal |
518
+ | `>` | greater than |
519
+ | `<` | less than |
520
+ | `>=` | greater than or equal |
521
+ | `<=` | less than or equal |
522
+
523
+ ### File functions for filters
524
+
525
+ | Function | Description |
526
+ |----------|-------------|
527
+ | `file.hasTag("tag1", "tag2")` | Has any of the tags (includes nested) |
528
+ | `file.hasLink("Note")` | Has link to note |
529
+ | `file.hasProperty("name")` | Has frontmatter property |
530
+ | `file.inFolder("Projects")` | In folder or subfolder |
531
+
532
+ ### File properties
533
+
534
+ | Property | Type | Description |
535
+ |----------|------|-------------|
536
+ | `file.name` | String | File name |
537
+ | `file.basename` | String | Name without extension |
538
+ | `file.path` | String | Full path from vault root |
539
+ | `file.folder` | String | Parent folder path |
540
+ | `file.ext` | String | File extension |
541
+ | `file.size` | Number | Size in bytes |
542
+ | `file.ctime` | Date | Created time |
543
+ | `file.mtime` | Date | Modified time |
544
+ | `file.tags` | List | All tags |
545
+ | `file.links` | List | Internal links |
546
+
547
+ ### Note properties
548
+
549
+ Frontmatter properties accessed as `note.property` or just `property`:
550
+
551
+ ```yaml
552
+ filters:
553
+ and:
554
+ - 'status == "active"' # shorthand
555
+ - 'note.priority >= 3' # explicit
556
+ ```
557
+
558
+ ## Formulas
559
+
560
+ ```yaml
561
+ formulas:
562
+ total: "price * quantity"
563
+ status_icon: 'if(done, "✅", "⏳")'
564
+ formatted_price: 'if(price, price.toFixed(2) + " dollars")'
565
+ created: 'file.ctime.format("YYYY-MM-DD")'
566
+ days_old: '(now() - file.ctime).days'
567
+ days_until_due: 'if(due_date, (date(due_date) - today()).days, "")'
568
+ ```
569
+
570
+ ### Global functions
571
+
572
+ | Function | Description |
573
+ |----------|-------------|
574
+ | `date(string)` | Parse date (`YYYY-MM-DD HH:mm:ss`) |
575
+ | `now()` | Current datetime |
576
+ | `today()` | Current date (time = 00:00:00) |
577
+ | `if(cond, true, false?)` | Conditional |
578
+ | `min(n1, n2, ...)` | Smallest number |
579
+ | `max(n1, n2, ...)` | Largest number |
580
+ | `number(any)` | Convert to number |
581
+ | `link(path, display?)` | Create link |
582
+ | `list(element)` | Wrap in list |
583
+
584
+ ### Date arithmetic
585
+
586
+ ```yaml
587
+ "date + \"1M\"" # Add 1 month
588
+ "now() + \"1 day\"" # Tomorrow
589
+ "today() + \"7d\"" # Week from today
590
+ "(now() - file.ctime).days" # Days since created
591
+ ```
592
+
593
+ Duration units: `y`/`year`/`years`, `M`/`month`/`months`, `d`/`day`/`days`, `w`/`week`/`weeks`, `h`/`hour`/`hours`, `m`/`minute`/`minutes`, `s`/`second`/`seconds`
594
+
595
+ ### String functions
596
+
597
+ `contains()`, `startsWith()`, `endsWith()`, `lower()`, `trim()`, `replace()`, `split()`, `slice()`, `isEmpty()`, `.length`
598
+
599
+ ### Number functions
600
+
601
+ `abs()`, `ceil()`, `floor()`, `round(digits?)`, `toFixed(precision)`
602
+
603
+ ### List functions
604
+
605
+ `contains()`, `filter()`, `map()`, `join()`, `sort()`, `unique()`, `flat()`, `isEmpty()`, `.length`
606
+
607
+ ## Views
608
+
609
+ ```yaml
610
+ views:
611
+ - type: table # table, list, cards, map
612
+ name: "My View"
613
+ limit: 10
614
+ order:
615
+ - file.name
616
+ - status
617
+ - due_date
618
+ filters: # View-level filters (AND'd with global)
619
+ 'status != "done"'
620
+ groupBy:
621
+ property: status
622
+ direction: ASC # or DESC
623
+ summaries:
624
+ price: Sum
625
+ count: Average
626
+ ```
627
+
628
+ ### Summary functions
629
+
630
+ | Name | Input | Description |
631
+ |------|-------|-------------|
632
+ | `Average` | Number | Mean |
633
+ | `Min` | Number | Smallest |
634
+ | `Max` | Number | Largest |
635
+ | `Sum` | Number | Sum |
636
+ | `Range` | Number | Max - Min |
637
+ | `Median` | Number | Median |
638
+ | `Earliest` | Date | Earliest date |
639
+ | `Latest` | Date | Latest date |
640
+ | `Empty` | Any | Count of empty values |
641
+ | `Filled` | Any | Count of non-empty values |
642
+ | `Unique` | Any | Count of unique values |
643
+
644
+ ## Example: Task tracker
645
+
646
+ ```yaml
647
+ filters:
648
+ and:
649
+ - file.hasTag("task")
650
+ - 'file.ext == "md"'
651
+ formulas:
652
+ days_until_due: 'if(due, (date(due) - today()).days, "")'
653
+ priority_label: 'if(priority == 1, "🔴 High", if(priority == 2, "🟡 Medium", "🟢 Low"))'
654
+ views:
655
+ - type: table
656
+ name: "Active Tasks"
657
+ filters:
658
+ and:
659
+ - 'status != "done"'
660
+ order:
661
+ - file.name
662
+ - status
663
+ - formula.priority_label
664
+ - due
665
+ - formula.days_until_due
666
+ groupBy:
667
+ property: status
668
+ direction: ASC
669
+ ```
670
+
671
+ ---
672
+
673
+ # JSON Canvas Reference
674
+
675
+ Canvas files (`.canvas`) are JSON following the [JSON Canvas Spec 1.0](https://jsoncanvas.org/spec/1.0/).
676
+
677
+ ```json
678
+ {
679
+ "nodes": [
680
+ {"id": "aabb11223344", "type": "text", "x": 0, "y": 0, "width": 300, "height": 150, "text": "# Hello\nMarkdown content"},
681
+ {"id": "ccdd55667788", "type": "file", "x": 400, "y": 0, "width": 300, "height": 200, "file": "Notes/note.md"},
682
+ {"id": "eeff99001122", "type": "link", "x": 0, "y": 300, "width": 300, "height": 100, "url": "https://example.com"},
683
+ {"id": "1122334455667788", "type": "group", "x": -50, "y": -50, "width": 800, "height": 500, "label": "My Group", "color": "4"}
684
+ ],
685
+ "edges": [
686
+ {"id": "aabbccddeeff0011", "fromNode": "aabb11223344", "fromSide": "right", "toNode": "ccdd55667788", "toSide": "left", "label": "links to"}
687
+ ]
688
+ }
689
+ ```
690
+
691
+ ### Node types
692
+
693
+ | Type | Required fields | Description |
694
+ |------|----------------|-------------|
695
+ | `text` | `text` | Markdown content |
696
+ | `file` | `file`, optional `subpath` | Reference to vault file |
697
+ | `link` | `url` | External URL |
698
+ | `group` | optional `label`, `background`, `backgroundStyle` | Visual container |
699
+
700
+ ### Common fields
701
+
702
+ All nodes: `id` (16-char hex), `type`, `x`, `y`, `width`, `height`, optional `color` (1-6 or hex).
703
+ Edges: `id`, `fromNode`, `toNode`, optional `fromSide`/`toSide` (top/right/bottom/left), `fromEnd`/`toEnd` (none/arrow), `label`, `color`.
704
+
705
+ ---
706
+
707
+ ## Example: Project notes
708
+
709
+ ```yaml
710
+ filters:
711
+ and:
712
+ - file.inFolder("Projects")
713
+ - 'file.ext == "md"'
714
+ formulas:
715
+ last_updated: 'file.mtime.relative()'
716
+ link_count: 'file.links.length'
717
+ views:
718
+ - type: table
719
+ name: "All Projects"
720
+ order:
721
+ - file.name
722
+ - status
723
+ - formula.last_updated
724
+ - formula.link_count
725
+ groupBy:
726
+ property: status
727
+ direction: ASC
728
+ ```