roam-research-mcp 2.4.0 → 2.13.0
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.
- package/README.md +175 -667
- package/build/Roam_Markdown_Cheatsheet.md +138 -289
- package/build/cache/page-uid-cache.js +40 -2
- package/build/cli/batch/translator.js +1 -1
- package/build/cli/commands/batch.js +3 -8
- package/build/cli/commands/get.js +478 -60
- package/build/cli/commands/refs.js +51 -31
- package/build/cli/commands/save.js +61 -10
- package/build/cli/commands/search.js +63 -58
- package/build/cli/commands/status.js +3 -4
- package/build/cli/commands/update.js +71 -28
- package/build/cli/utils/graph.js +6 -2
- package/build/cli/utils/input.js +10 -0
- package/build/cli/utils/output.js +28 -5
- package/build/cli/utils/sort-group.js +110 -0
- package/build/config/graph-registry.js +31 -13
- package/build/config/graph-registry.test.js +42 -5
- package/build/markdown-utils.js +114 -4
- package/build/markdown-utils.test.js +125 -0
- package/build/query/generator.js +330 -0
- package/build/query/index.js +149 -0
- package/build/query/parser.js +319 -0
- package/build/query/parser.test.js +389 -0
- package/build/query/types.js +4 -0
- package/build/search/ancestor-rule.js +14 -0
- package/build/search/block-ref-search.js +1 -5
- package/build/search/hierarchy-search.js +5 -12
- package/build/search/index.js +1 -0
- package/build/search/status-search.js +10 -9
- package/build/search/tag-search.js +8 -24
- package/build/search/text-search.js +70 -27
- package/build/search/types.js +13 -0
- package/build/search/utils.js +71 -2
- package/build/server/roam-server.js +4 -3
- package/build/shared/index.js +2 -0
- package/build/shared/page-validator.js +233 -0
- package/build/shared/page-validator.test.js +128 -0
- package/build/shared/staged-batch.js +144 -0
- package/build/tools/helpers/batch-utils.js +57 -0
- package/build/tools/helpers/page-resolution.js +136 -0
- package/build/tools/helpers/refs.js +68 -0
- package/build/tools/operations/batch.js +75 -3
- package/build/tools/operations/block-retrieval.js +15 -4
- package/build/tools/operations/block-retrieval.test.js +87 -0
- package/build/tools/operations/blocks.js +1 -288
- package/build/tools/operations/memory.js +32 -90
- package/build/tools/operations/outline.js +38 -156
- package/build/tools/operations/pages.js +169 -122
- package/build/tools/operations/todos.js +5 -37
- package/build/tools/schemas.js +20 -9
- package/build/tools/tool-handlers.js +4 -4
- package/build/utils/helpers.js +27 -0
- package/package.json +1 -1
|
@@ -1,128 +1,85 @@
|
|
|
1
|
-
# Roam Markdown Cheatsheet
|
|
1
|
+
# Roam Markdown Cheatsheet v2.1.0
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Core Syntax
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Quick Reference: Core Syntax
|
|
8
|
-
|
|
9
|
-
### Text Formatting
|
|
10
|
-
| Style | Syntax | Example |
|
|
11
|
-
|-------|--------|---------|
|
|
12
|
-
| Bold | `**text**` | **bold text** |
|
|
13
|
-
| Italic | `__text__` | __italic text__ |
|
|
14
|
-
| Highlight | `^^text^^` | ^^highlighted^^ |
|
|
15
|
-
| Strikethrough | `~~text~~` | ~~struck~~ |
|
|
16
|
-
| Inline code | `` `code` `` | `code` |
|
|
17
|
-
| LaTeX | `$$E=mc^2$$` | rendered math |
|
|
5
|
+
### Formatting
|
|
6
|
+
`**bold**` · `__italic__` · `^^highlight^^` · `~~strike~~` · `` `code` `` · `$$LaTeX$$`
|
|
18
7
|
|
|
19
8
|
### Links & References
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
| Hyphenated | `#self-esteem` | Naturally hyphenated terms |
|
|
36
|
-
|
|
37
|
-
⚠️ **CRITICAL**: Never concatenate multi-word tags. `#knowledgemanagement` ≠ `#[[knowledge management]]`
|
|
38
|
-
|
|
39
|
-
⚠️ **CRITICAL**: Never use `#` to mean "number" (e.g., `#1`, `#2`). In Roam, `#` **always** creates a hashtag. Write `Step 1`, `No. 1`, or just spell out the number instead.
|
|
9
|
+
- **Page ref:** `[[Page Name]]` — creates/links to page
|
|
10
|
+
- **Block ref:** `((block-uid))` — embeds block content inline
|
|
11
|
+
- **Block embed:** `{{[[embed]]: ((block-uid))}}` — full block with children
|
|
12
|
+
- **External:** `[text](URL)`
|
|
13
|
+
- **Aliased page:** `[display text]([[Actual Page]])`
|
|
14
|
+
- **Aliased block:** `[display text](<((block-uid))>)` — note the angle brackets
|
|
15
|
+
- **Image:** ``
|
|
16
|
+
|
|
17
|
+
### Tags
|
|
18
|
+
- Single word: `#tag`
|
|
19
|
+
- Multi-word: `#[[multiple words]]`
|
|
20
|
+
- Hyphenated: `#self-esteem`
|
|
21
|
+
|
|
22
|
+
⚠️ Never concatenate: `#knowledgemanagement` ≠ `#[[knowledge management]]`
|
|
23
|
+
⚠️ `#` always creates tags — write `Step 1` not `#1`
|
|
40
24
|
|
|
41
25
|
### Dates
|
|
42
|
-
|
|
43
|
-
- Ordinals: 1st, 2nd, 3rd, 4th–20th, 21st, 22nd, 23rd, 24th–30th, 31st
|
|
26
|
+
Always ordinal format: `[[January 1st, 2025]]`, `[[December 23rd, 2024]]`
|
|
44
27
|
|
|
45
|
-
###
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
| Todo | `{{[[TODO]]}} task description` |
|
|
49
|
-
| Done | `{{[[DONE]]}} task description` |
|
|
28
|
+
### Tasks
|
|
29
|
+
- Todo: `{{[[TODO]]}} task`
|
|
30
|
+
- Done: `{{[[DONE]]}} task`
|
|
50
31
|
|
|
51
|
-
### Attributes
|
|
32
|
+
### Attributes
|
|
52
33
|
```
|
|
53
34
|
Type:: Book
|
|
54
35
|
Author:: [[Person Name]]
|
|
55
36
|
Rating:: 4/5
|
|
56
|
-
Source:: https://example.com
|
|
57
37
|
```
|
|
58
38
|
|
|
59
|
-
**
|
|
60
|
-
|
|
61
|
-
**When to USE attributes:**
|
|
62
|
-
| Attribute | Why It's Good |
|
|
63
|
-
|-----------|---------------|
|
|
64
|
-
| `Type:: Book` | Reusable across all media you consume |
|
|
65
|
-
| `Author:: [[Person]]` | Links to author page, queryable |
|
|
66
|
-
| `Status:: In Progress` | Standard project states, queryable |
|
|
67
|
-
| `Source:: URL` | Consistent sourcing across notes |
|
|
68
|
-
| `Date:: [[January 1st, 2025]]` | Enables date-based queries |
|
|
69
|
-
|
|
70
|
-
**When NOT to use attributes:**
|
|
71
|
-
| ❌ Wrong | ✅ Use Instead | Why |
|
|
72
|
-
|----------|----------------|-----|
|
|
73
|
-
| `Step 1:: Do this thing` | `**Step 1:** Do this thing` | Step numbers are page-specific, not queryable concepts |
|
|
74
|
-
| `Note:: Some observation` | Just write the text, or use `#note` | One-off labels don't need attribute syntax |
|
|
75
|
-
| `Summary:: The main point` | `**Summary:** The main point` | Section headers are formatting, not metadata |
|
|
76
|
-
| `Definition:: Some text` | `Term:: Definition` | Only use for actual definitions you want to query |
|
|
77
|
-
| `Implementation Tier 3 (Societal Restructuring):: Some text` | `**Implementation Tier 3 (Societal Restructuring):** Some text` | Label is specific to current concept |
|
|
78
|
-
|
|
79
|
-
⚠️ **The Test**: Ask yourself: "Will I ever query for all blocks with this attribute across my graph?" If no, use **bold formatting** (`**Label:**`) instead of `::` syntax.
|
|
39
|
+
**Use `::` when:** queryable across graph (Type, Author, Status, Source, Date)
|
|
40
|
+
**Use bold instead when:** page-specific labels (Step 1, Summary, Note)
|
|
80
41
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
---
|
|
42
|
+
⚠️ Test: "Will I query all blocks with this attribute?" If no → use `**Label:**` instead
|
|
43
|
+
⚠️ Never `**Attr**::` — Roam auto-bolds attributes
|
|
84
44
|
|
|
85
45
|
## Block Structures
|
|
86
46
|
|
|
87
|
-
###
|
|
88
|
-
- Use `-` (dash) followed by space
|
|
89
|
-
- Nested bullets: indent with tab or spaces
|
|
47
|
+
### Bullets
|
|
90
48
|
```
|
|
91
|
-
- Parent
|
|
92
|
-
- Child
|
|
93
|
-
- Grandchild
|
|
49
|
+
- Parent
|
|
50
|
+
- Child
|
|
51
|
+
- Grandchild
|
|
94
52
|
```
|
|
95
53
|
|
|
96
54
|
### Code Blocks
|
|
97
55
|
````
|
|
98
56
|
```javascript
|
|
99
|
-
const
|
|
100
|
-
return "syntax highlighted";
|
|
101
|
-
}
|
|
57
|
+
const x = 1;
|
|
102
58
|
```
|
|
103
59
|
````
|
|
104
60
|
|
|
105
61
|
### Queries
|
|
106
62
|
```
|
|
107
63
|
{{[[query]]: {and: [[tag1]] [[tag2]]}}}
|
|
108
|
-
{{[[query]]: {or: [[
|
|
109
|
-
{{[[query]]: {not: [[exclude
|
|
64
|
+
{{[[query]]: {or: [[A]] [[B]]}}}
|
|
65
|
+
{{[[query]]: {not: [[exclude]]}}}
|
|
110
66
|
{{[[query]]: {between: [[January 1st, 2025]] [[January 31st, 2025]]}}}
|
|
111
67
|
```
|
|
112
68
|
|
|
113
69
|
### Calculator
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
70
|
+
`{{[[calc]]: 2 + 2}}`
|
|
71
|
+
|
|
72
|
+
### Codeblock
|
|
73
|
+
Roam uses "shell" not "bash". Other common languages okay, including "plain text".
|
|
74
|
+
```shell
|
|
75
|
+
echo "Hello world!"
|
|
117
76
|
```
|
|
118
77
|
|
|
119
|
-
---
|
|
120
78
|
|
|
121
79
|
## Complex Structures
|
|
122
80
|
|
|
123
81
|
### Tables
|
|
124
|
-
|
|
125
|
-
|
|
82
|
+
Each column nests ONE LEVEL DEEPER than previous:
|
|
126
83
|
```
|
|
127
84
|
{{[[table]]}}
|
|
128
85
|
- Header 1
|
|
@@ -131,235 +88,114 @@ Tables use nested indentation. Each column header/cell nests ONE LEVEL DEEPER th
|
|
|
131
88
|
- Row 1 Label
|
|
132
89
|
- Cell 1.1
|
|
133
90
|
- Cell 1.2
|
|
134
|
-
- Cell 1.3
|
|
135
91
|
- Row 2 Label
|
|
136
92
|
- Cell 2.1
|
|
137
93
|
- Cell 2.2
|
|
138
|
-
- Cell 2.3
|
|
139
94
|
```
|
|
95
|
+
Keep tables ≤5 columns.
|
|
140
96
|
|
|
141
|
-
|
|
142
|
-
- `{{[[table]]}}` is level 1
|
|
143
|
-
- First header/row-label at level 2
|
|
144
|
-
- Each subsequent column nests +1 level deeper
|
|
145
|
-
- Keep tables ≤5 columns for readability
|
|
146
|
-
|
|
147
|
-
### Kanban Boards
|
|
97
|
+
### Kanban
|
|
148
98
|
```
|
|
149
99
|
{{[[kanban]]}}
|
|
150
|
-
- Column 1
|
|
151
|
-
- Card 1
|
|
152
|
-
- Card 2
|
|
153
|
-
- Column 2
|
|
154
|
-
- Card 3
|
|
100
|
+
- Column 1
|
|
101
|
+
- Card 1
|
|
102
|
+
- Card 2
|
|
103
|
+
- Column 2
|
|
104
|
+
- Card 3
|
|
155
105
|
```
|
|
156
106
|
|
|
157
|
-
### Mermaid
|
|
107
|
+
### Mermaid
|
|
158
108
|
```
|
|
159
109
|
{{[[mermaid]]}}
|
|
160
110
|
- graph TD
|
|
161
111
|
- A[Start] --> B{Decision}
|
|
162
112
|
- B -->|Yes| C[Action]
|
|
163
|
-
- B -->|No| D[Alternative]
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Hiccup (Custom HTML)
|
|
167
|
-
`:hiccup [:iframe {:width "600" :height "400" :src "https://example.com"}]`
|
|
168
|
-
|
|
169
|
-
`:hiccup [:div {:style {:color "red"}} "Custom styled content"]`
|
|
170
|
-
|
|
171
|
-
---
|
|
172
|
-
|
|
173
|
-
## Anti-Patterns — DON'T DO THIS
|
|
174
|
-
|
|
175
|
-
| ❌ Wrong | ✅ Correct | Why |
|
|
176
|
-
|----------|-----------|-----|
|
|
177
|
-
| `Step 1:: Do this` | `**Step 1:** Do this` | `::` creates queryable attributes; use bold for page-specific labels |
|
|
178
|
-
| `#multiplewords` | `#[[multiple words]]` | Concatenated tags create dead references |
|
|
179
|
-
| `#1`, `#2`, `#3` | `Step 1`, `No. 1`, or spell out | `#` always creates hashtags, never means "number" |
|
|
180
|
-
| `[[january 1, 2025]]` | `[[January 1st, 2025]]` | Must use ordinal format with proper capitalization |
|
|
181
|
-
| `[text](((block-uid)))` | `[text](<((block-uid))>)` | Block ref links need angle bracket wrapper |
|
|
182
|
-
| `{{embed: ((uid))}}` | `{{[[embed]]: ((uid))}}` | Embed requires double brackets around keyword |
|
|
183
|
-
| Deeply nested tables (6+ cols) | Max 4-5 columns | Becomes unreadable/unmanageable |
|
|
184
|
-
| `- *bullet` | `- bullet` | Use dash, not asterisk for bullets |
|
|
185
|
-
| `[[TODO]] task` | `{{[[TODO]]}} task` | TODO needs double curly braces |
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## Tool Selection Decision Tree
|
|
190
|
-
|
|
191
113
|
```
|
|
192
|
-
CREATING CONTENT IN ROAM:
|
|
193
|
-
|
|
194
|
-
┌─ Is this a NEW standalone page with structure?
|
|
195
|
-
│ └─ YES → roam_create_page (with content array)
|
|
196
|
-
│
|
|
197
|
-
├─ Adding content to EXISTING page/block?
|
|
198
|
-
│ ├─ Simple outline structure → roam_create_outline
|
|
199
|
-
│ │ (provide page_title_uid and/or block_text_uid)
|
|
200
|
-
│ │
|
|
201
|
-
│ └─ Complex/nested markdown → roam_import_markdown
|
|
202
|
-
│ (for deeply nested content, tables, etc.)
|
|
203
|
-
│
|
|
204
|
-
├─ Replacing/revising ENTIRE page content?
|
|
205
|
-
│ └─ roam_update_page_markdown
|
|
206
|
-
│ (fetches page internally, computes smart diff, preserves UIDs)
|
|
207
|
-
│
|
|
208
|
-
├─ Need to CREATE, UPDATE, MOVE, or DELETE individual blocks?
|
|
209
|
-
│ └─ roam_process_batch_actions
|
|
210
|
-
│ (fine-grained control, UID placeholders for parent refs)
|
|
211
|
-
│
|
|
212
|
-
├─ Creating a TABLE?
|
|
213
|
-
│ └─ roam_create_table
|
|
214
|
-
│ (handles complex nested structure automatically)
|
|
215
|
-
│
|
|
216
|
-
├─ Adding a memory/note to remember?
|
|
217
|
-
│ └─ roam_remember (auto-tags with MEMORIES_TAG)
|
|
218
|
-
│
|
|
219
|
-
├─ Adding TODO items to today?
|
|
220
|
-
│ └─ roam_add_todo (creates individual TODO blocks)
|
|
221
|
-
│
|
|
222
|
-
└─ SEARCHING/READING:
|
|
223
|
-
├─ Find by tag → roam_search_for_tag
|
|
224
|
-
├─ Find by text → roam_search_by_text
|
|
225
|
-
├─ Find by date range → roam_search_by_date
|
|
226
|
-
├─ Find by status → roam_search_by_status
|
|
227
|
-
├─ Find block/page references → roam_search_block_refs
|
|
228
|
-
├─ Find pages modified today → roam_find_pages_modified_today
|
|
229
|
-
├─ Get page content → roam_fetch_page_by_title
|
|
230
|
-
├─ Get block + children → roam_fetch_block_with_children
|
|
231
|
-
├─ Recall memories → roam_recall
|
|
232
|
-
└─ Complex queries → roam_datomic_query
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
---
|
|
236
|
-
|
|
237
|
-
## API Efficiency Guidelines (Rate Limit Avoidance)
|
|
238
|
-
|
|
239
|
-
The Roam API has rate limits. Follow these guidelines to minimize API calls:
|
|
240
|
-
|
|
241
|
-
### Tool Efficiency Ranking (Best to Worst)
|
|
242
|
-
1. **`roam_update_page_markdown`** - Single call: fetches, diffs, and updates (MOST EFFICIENT for revisions)
|
|
243
|
-
2. **`roam_process_batch_actions`** - Single API call for multiple operations
|
|
244
|
-
3. **`roam_create_page`** - Batches content with page creation
|
|
245
|
-
4. **`roam_create_outline` / `roam_import_markdown`** - Include verification queries (use for smaller operations)
|
|
246
|
-
5. **Multiple sequential tool calls** - Each call = multiple API requests (AVOID)
|
|
247
|
-
|
|
248
|
-
### Best Practices for Intensive Operations
|
|
249
|
-
|
|
250
|
-
#### When Updating/Revising a Page:
|
|
251
|
-
1. **Preferred**: Use `roam_update_page_markdown` — it fetches, diffs, and updates in one call
|
|
252
|
-
2. **Alternative** (for fine-grained control): Fetch once with `roam_fetch_page_by_title`, then execute ALL changes in a SINGLE `roam_process_batch_actions` call
|
|
253
|
-
3. Do NOT fetch-modify-fetch-modify in a loop
|
|
254
|
-
|
|
255
|
-
#### When Creating Large Content:
|
|
256
|
-
- For 10+ blocks: Use `roam_process_batch_actions` with nested structure
|
|
257
|
-
- For simple outlines (<10 blocks): `roam_create_outline` is fine
|
|
258
|
-
|
|
259
|
-
#### UID Caching:
|
|
260
|
-
- Save UIDs from previous operations - don't re-query for them
|
|
261
|
-
- Use `page_uid` instead of `page_title` when available (avoids lookup query)
|
|
262
|
-
- Use `block_uid` instead of `block_text_uid` when you have it
|
|
263
114
|
|
|
264
|
-
|
|
265
|
-
|
|
115
|
+
### Hiccup
|
|
116
|
+
`:hiccup [:iframe {:width "600" :height "400" :src "URL"}]`
|
|
266
117
|
|
|
267
|
-
|
|
118
|
+
## Anti-Patterns
|
|
268
119
|
|
|
269
|
-
|
|
120
|
+
| ❌ Wrong | ✅ Correct |
|
|
121
|
+
|----------|-----------|
|
|
122
|
+
| `#multiplewords` | `#[[multiple words]]` |
|
|
123
|
+
| `#1`, `#2` | `Step 1`, `No. 1` |
|
|
124
|
+
| `[[january 1, 2025]]` | `[[January 1st, 2025]]` |
|
|
125
|
+
| `[text](((uid)))` | `[text](<((uid))>)` |
|
|
126
|
+
| `{{embed: ((uid))}}` | `{{[[embed]]: ((uid))}}` |
|
|
127
|
+
| `[[TODO]] task` | `{{[[TODO]]}} task` |
|
|
128
|
+
| `- *bullet` | `- bullet` |
|
|
129
|
+
| `* bullet` | `- bullet` |
|
|
130
|
+
| `**Attr**:: val` | `Attr:: val` |
|
|
131
|
+
|
|
132
|
+
## Tool Selection
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
CREATING:
|
|
136
|
+
├─ New page + structure → roam_create_page
|
|
137
|
+
├─ Add to existing page/block:
|
|
138
|
+
│ ├─ Simple outline → roam_create_outline
|
|
139
|
+
│ └─ Complex markdown → roam_import_markdown
|
|
140
|
+
├─ Revise entire page → roam_update_page_markdown
|
|
141
|
+
├─ Fine-grained CRUD → roam_process_batch_actions
|
|
142
|
+
├─ Table → roam_create_table
|
|
143
|
+
├─ Memory → roam_remember
|
|
144
|
+
└─ Todos → roam_add_todo
|
|
145
|
+
|
|
146
|
+
SEARCHING:
|
|
147
|
+
├─ By tag → roam_search_for_tag
|
|
148
|
+
├─ By text → roam_search_by_text
|
|
149
|
+
├─ By date → roam_search_by_date
|
|
150
|
+
├─ By status → roam_search_by_status
|
|
151
|
+
├─ Block refs → roam_search_block_refs
|
|
152
|
+
├─ Modified today → roam_find_pages_modified_today
|
|
153
|
+
├─ Page content → roam_fetch_page_by_title
|
|
154
|
+
├─ Block + children → roam_fetch_block_with_children
|
|
155
|
+
├─ Memories → roam_recall
|
|
156
|
+
└─ Complex → roam_datomic_query
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## API Efficiency
|
|
160
|
+
|
|
161
|
+
**Ranking (best → worst):**
|
|
162
|
+
1. `roam_update_page_markdown` — single call: fetch + diff + update
|
|
163
|
+
2. `roam_process_batch_actions` — batch multiple ops
|
|
164
|
+
3. `roam_create_page` — batches content with creation
|
|
165
|
+
4. `roam_create_outline` / `roam_import_markdown` — includes verification
|
|
166
|
+
5. Multiple sequential calls — avoid
|
|
167
|
+
|
|
168
|
+
**Best practices:**
|
|
169
|
+
- Use `roam_update_page_markdown` for revisions (handles everything)
|
|
170
|
+
- For 10+ blocks: `roam_process_batch_actions`
|
|
171
|
+
- Cache UIDs — use `page_uid` over `page_title` when available
|
|
172
|
+
- Never fetch-modify-fetch-modify in loops
|
|
173
|
+
|
|
174
|
+
### UID Placeholders
|
|
175
|
+
Use `{{uid:name}}` for parent refs in batch actions:
|
|
270
176
|
```json
|
|
271
177
|
[
|
|
272
|
-
{
|
|
273
|
-
{
|
|
178
|
+
{"action": "create-block", "uid": "{{uid:parent}}", "string": "Parent", "location": {"parent-uid": "pageUid", "order": 0}},
|
|
179
|
+
{"action": "create-block", "string": "Child", "location": {"parent-uid": "{{uid:parent}}", "order": 0}}
|
|
274
180
|
]
|
|
275
181
|
```
|
|
276
|
-
|
|
277
|
-
**Response includes UID mapping:**
|
|
278
|
-
```json
|
|
279
|
-
{
|
|
280
|
-
"success": true,
|
|
281
|
-
"uid_map": {
|
|
282
|
-
"parent": "Xk7mN2pQ9"
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
**Why placeholders?** LLMs are not reliable random generators. The server uses cryptographically secure randomness to generate proper 9-character Roam UIDs.
|
|
288
|
-
|
|
289
|
-
### Example: Efficient Page Revision
|
|
290
|
-
|
|
291
|
-
**Instead of:**
|
|
292
|
-
```
|
|
293
|
-
1. roam_fetch_page_by_title → get content
|
|
294
|
-
2. roam_create_outline → add section 1
|
|
295
|
-
3. roam_create_outline → add section 2
|
|
296
|
-
4. roam_import_markdown → add more content
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
**Do this:**
|
|
300
|
-
```
|
|
301
|
-
1. roam_update_page_markdown → single call handles fetch, diff, and updates
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
**Alternative** (when you need fine-grained control):
|
|
305
|
-
```
|
|
306
|
-
1. roam_fetch_page_by_title → get page UID and content
|
|
307
|
-
2. roam_process_batch_actions → ALL creates/updates in one call
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
---
|
|
182
|
+
Server returns `{"uid_map": {"parent": "Xk7mN2pQ9"}}`.
|
|
311
183
|
|
|
312
184
|
## Structural Defaults
|
|
313
185
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
- `[[Page]]` for concepts you'll expand into full pages
|
|
320
|
-
- `#tag` for categorization/filtering
|
|
321
|
-
4. **When to embed vs reference**:
|
|
322
|
-
- `((uid))` — inline reference (shows content)
|
|
323
|
-
- `{{[[embed]]: ((uid))}}` — full block with children
|
|
324
|
-
- `[text](<((uid))>)` — clickable link only
|
|
325
|
-
|
|
326
|
-
---
|
|
327
|
-
## Visual Separation — Hierarchy First, Separators Never
|
|
328
|
-
|
|
329
|
-
Empty blocks and decorative dividers create clutter. Roam's outliner structure provides all the visual separation you need.
|
|
186
|
+
- **Hierarchy:** 2-4 levels preferred, rarely exceed 5
|
|
187
|
+
- **Blocks:** One idea per block
|
|
188
|
+
- **Page refs vs tags:** `[[Page]]` for expandable concepts, `#tag` for filtering
|
|
189
|
+
- **Embed vs ref:** `((uid))` inline, `{{[[embed]]: ((uid))}}` with children, `[text](<((uid))>)` link only
|
|
190
|
+
- **No empty blocks or `---` dividers** — use hierarchy for visual separation
|
|
330
191
|
|
|
331
|
-
|
|
332
|
-
|----------|-----------|
|
|
333
|
-
| Blank blocks | Let hierarchy create space — child blocks are visually indented |
|
|
334
|
-
| `---` dividers | Use a **heading block** to signal section breaks |
|
|
335
|
-
| Decorative lines `───` | Nest content under a parent block as a structural container |
|
|
336
|
-
|
|
337
|
-
**Principle**: If you feel the urge to add visual breathing room, you probably need *better structure*, not more blocks. Promote a block to a heading, or reorganize into parent/child relationships.
|
|
192
|
+
## Output Conventions
|
|
338
193
|
|
|
339
|
-
**
|
|
194
|
+
**Quote:** `<text> —[[Author]] #quote`
|
|
195
|
+
**Definition:** `Term:: definition #definition`
|
|
196
|
+
**Open question:** `{{[[TODO]]}} Research: <question> #[[open questions]]`
|
|
340
197
|
|
|
341
198
|
---
|
|
342
|
-
|
|
343
|
-
## Output Format Conventions
|
|
344
|
-
|
|
345
|
-
### Quotes
|
|
346
|
-
```
|
|
347
|
-
<quote text> —[[Author Name]] #quote #[[relevant topic]]
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
### Definitions
|
|
351
|
-
```
|
|
352
|
-
Term:: Definition text #definition #[[domain]]
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
### Questions for Future
|
|
356
|
-
```
|
|
357
|
-
{{[[TODO]]}} Research: <question> #[[open questions]]
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
---
|
|
361
|
-
|
|
362
|
-
*End of Generic Foundation — Personalization section follows during user setup.*
|
|
363
199
|
# Roam Preferences — Personalization Layer
|
|
364
200
|
|
|
365
201
|
> This section contains YOUR specific conventions, tagging philosophy, and graph-specific rules. Customize to match your workflow.
|
|
@@ -421,6 +257,11 @@ ASK YOURSELF:
|
|
|
421
257
|
| `#single-word` | Simple, unambiguous category |
|
|
422
258
|
| Attribute `Type::` | Structured metadata for queries |
|
|
423
259
|
|
|
260
|
+
### WHEN creating Endnotes/Footnotes:
|
|
261
|
+
- Find/Create the block with heading "Footnotes::" and nest footnote item below. (Footnotes do not need to be on the same page as the block to which it references. Typically on the same page unless instructed otherwise.)
|
|
262
|
+
- If not known, retrieve the block_uid reference for this footnote item.
|
|
263
|
+
- In the block referencing the footnote, append the reference with footnote-item-block_id, example: "- <block_text> #ref ((block_uid))"
|
|
264
|
+
|
|
424
265
|
### Structural Tagging (Beyond Content)
|
|
425
266
|
|
|
426
267
|
Tag by **patterns and mechanisms**, not just subjects:
|
|
@@ -466,6 +307,9 @@ Always include 2-3 relevant hashtags after quotes.
|
|
|
466
307
|
```
|
|
467
308
|
|
|
468
309
|
### Scheduled Reviews
|
|
310
|
+
|
|
311
|
+
- Any block tagged with a date will show on that respective daily page.
|
|
312
|
+
|
|
469
313
|
```
|
|
470
314
|
[[For review]]: [[Date in ordinal format]]
|
|
471
315
|
```
|
|
@@ -492,6 +336,7 @@ When a tag would awkwardly affect sentence capitalization:
|
|
|
492
336
|
- **Use inconsistent capitalization** — Tags are lowercase unless proper nouns
|
|
493
337
|
- **Create orphan tags** — Check if existing page/tag serves the purpose
|
|
494
338
|
- **Bold Attributes** - ❌ `**Attribute**::`, ✅ `Attribute::` (Roam auto-formats)
|
|
339
|
+
- **Separators** - `---` Don't use them.
|
|
495
340
|
|
|
496
341
|
### DO
|
|
497
342
|
- **Think retrieval-first** — How will you search for this later?
|
|
@@ -516,7 +361,7 @@ CUSTOMIZE THIS SECTION with your specific conventions:
|
|
|
516
361
|
|
|
517
362
|
**Books:**
|
|
518
363
|
```
|
|
519
|
-
[[Book
|
|
364
|
+
[[Book/<title> | <author>]]
|
|
520
365
|
Type:: Book
|
|
521
366
|
Author:: [[Author Name]]
|
|
522
367
|
Status:: Reading | Completed | Abandoned
|
|
@@ -529,14 +374,18 @@ Rating:: X/5
|
|
|
529
374
|
Type:: Person
|
|
530
375
|
Context:: How I know them
|
|
531
376
|
```
|
|
532
|
-
|
|
377
|
+
- When linking bibliographic references —>
|
|
378
|
+
Example: `McAdams, D.P. (2001) [The Psychology of Life Stories](https://journals.sagepub.com/doi/10.1037/1089-2680.5.2.100) — foundational paper`
|
|
379
|
+
- [McAdams, D.P.]([[Dan McAdams]]) - author's name in the graph
|
|
380
|
+
- If source URL, link to source: [The Psychology of Life Stories](https://journals.sagepub.com/doi/10.1037/1089-2680.5.2.100)
|
|
381
|
+
- If notes page exists or will exist in Roam: append ` | [Notes]([[Article/The Psychology of Life Stories]]), if not, just leave it without link.
|
|
382
|
+
|
|
533
383
|
**Projects:**
|
|
534
384
|
```
|
|
535
|
-
[[Project
|
|
385
|
+
[[Project/<project anme>]]
|
|
536
386
|
Status:: Active | Paused | Completed
|
|
537
387
|
Start:: [[Date]]
|
|
538
388
|
```
|
|
539
|
-
|
|
540
389
|
---
|
|
541
390
|
|
|
542
391
|
## Integration Notes
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Simple in-memory cache for page title -> UID mappings.
|
|
2
|
+
* Simple in-memory cache for page title -> UID mappings and UID existence tracking.
|
|
3
3
|
* Pages are stable entities that rarely get deleted, making them safe to cache.
|
|
4
4
|
* This reduces redundant API queries when looking up the same page multiple times.
|
|
5
|
+
*
|
|
6
|
+
* The cache tracks two things:
|
|
7
|
+
* 1. Title -> UID mappings (for getPageUid lookups)
|
|
8
|
+
* 2. Known existing UIDs (for existence validation before batch operations)
|
|
5
9
|
*/
|
|
6
10
|
class PageUidCache {
|
|
7
11
|
constructor() {
|
|
8
12
|
this.cache = new Map(); // title (lowercase) -> UID
|
|
13
|
+
this.knownUids = new Set(); // UIDs confirmed to exist
|
|
9
14
|
}
|
|
10
15
|
/**
|
|
11
16
|
* Get a cached page UID by title.
|
|
@@ -17,11 +22,13 @@ class PageUidCache {
|
|
|
17
22
|
}
|
|
18
23
|
/**
|
|
19
24
|
* Cache a page title -> UID mapping.
|
|
25
|
+
* Also marks the UID as known to exist.
|
|
20
26
|
* @param title - Page title (will be stored lowercase)
|
|
21
27
|
* @param uid - Page UID
|
|
22
28
|
*/
|
|
23
29
|
set(title, uid) {
|
|
24
30
|
this.cache.set(title.toLowerCase(), uid);
|
|
31
|
+
this.knownUids.add(uid);
|
|
25
32
|
}
|
|
26
33
|
/**
|
|
27
34
|
* Check if a page title is cached.
|
|
@@ -30,6 +37,30 @@ class PageUidCache {
|
|
|
30
37
|
has(title) {
|
|
31
38
|
return this.cache.has(title.toLowerCase());
|
|
32
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Check if a UID is known to exist.
|
|
42
|
+
* @param uid - Page or block UID
|
|
43
|
+
*/
|
|
44
|
+
hasUid(uid) {
|
|
45
|
+
return this.knownUids.has(uid);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Mark a UID as known to exist (without title mapping).
|
|
49
|
+
* Use this when you've verified a UID exists but don't know/need its title.
|
|
50
|
+
* @param uid - Page or block UID
|
|
51
|
+
*/
|
|
52
|
+
addUid(uid) {
|
|
53
|
+
this.knownUids.add(uid);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Mark multiple UIDs as known to exist.
|
|
57
|
+
* @param uids - Array of page or block UIDs
|
|
58
|
+
*/
|
|
59
|
+
addUids(uids) {
|
|
60
|
+
for (const uid of uids) {
|
|
61
|
+
this.knownUids.add(uid);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
33
64
|
/**
|
|
34
65
|
* Called when a page is created - immediately add to cache.
|
|
35
66
|
* @param title - Page title
|
|
@@ -43,13 +74,20 @@ class PageUidCache {
|
|
|
43
74
|
*/
|
|
44
75
|
clear() {
|
|
45
76
|
this.cache.clear();
|
|
77
|
+
this.knownUids.clear();
|
|
46
78
|
}
|
|
47
79
|
/**
|
|
48
|
-
* Get the current cache size.
|
|
80
|
+
* Get the current title cache size.
|
|
49
81
|
*/
|
|
50
82
|
get size() {
|
|
51
83
|
return this.cache.size;
|
|
52
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Get the current known UIDs cache size.
|
|
87
|
+
*/
|
|
88
|
+
get uidCacheSize() {
|
|
89
|
+
return this.knownUids.size;
|
|
90
|
+
}
|
|
53
91
|
}
|
|
54
92
|
// Singleton instance - shared across all operations
|
|
55
93
|
export const pageUidCache = new PageUidCache();
|
|
@@ -296,7 +296,7 @@ function translateRemember(cmd, context) {
|
|
|
296
296
|
const tags = params.categories.map(cat => `#[[${cat}]]`).join(' ');
|
|
297
297
|
memoryText = `${params.text} ${tags}`;
|
|
298
298
|
}
|
|
299
|
-
// Add
|
|
299
|
+
// Add ROAM_MEMORIES_TAG if configured (we'll handle this in the CLI command)
|
|
300
300
|
// For now, just create the block
|
|
301
301
|
let parentUid;
|
|
302
302
|
// If heading is specified, we'd need to look it up or create it
|
|
@@ -6,14 +6,7 @@ import { printDebug, exitWithError } from '../utils/output.js';
|
|
|
6
6
|
import { resolveGraph } from '../utils/graph.js';
|
|
7
7
|
import { collectPageTitles, resolveAllPages, resolveDailyPageUid, needsDailyPage, createResolutionContext, getDailyPageTitle } from '../batch/resolver.js';
|
|
8
8
|
import { translateAllCommands } from '../batch/translator.js';
|
|
9
|
-
|
|
10
|
-
async function readStdin() {
|
|
11
|
-
const chunks = [];
|
|
12
|
-
for await (const chunk of process.stdin) {
|
|
13
|
-
chunks.push(chunk);
|
|
14
|
-
}
|
|
15
|
-
return Buffer.concat(chunks).toString('utf-8');
|
|
16
|
-
}
|
|
9
|
+
import { readStdin } from '../utils/input.js';
|
|
17
10
|
// Required params per command type
|
|
18
11
|
const REQUIRED_PARAMS = {
|
|
19
12
|
todo: ['text'],
|
|
@@ -167,6 +160,8 @@ Example:
|
|
|
167
160
|
{"command": "outline", "params": {"parent": "{{overview}}", "items": ["Goal 1", "Goal 2"]}},
|
|
168
161
|
{"command": "todo", "params": {"text": "Review project"}}
|
|
169
162
|
]
|
|
163
|
+
|
|
164
|
+
Output (JSON): { success, pages_created, actions_executed, uid_map? }
|
|
170
165
|
`)
|
|
171
166
|
.action(async (file, options) => {
|
|
172
167
|
try {
|