Skip to content

Commit 1df68a3

Browse files
2b3proclaude
andcommitted
v2.17.0 feat: add CLI commands for full page view and subpages (#15)
- roam get full <title>: full page view with content + linked references - roam get subpages <prefix>: namespace-based sub-page listing - Update README, CHANGELOG, and CLI reference - Bump version to v2.17.0 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2568e05 commit 1df68a3

5 files changed

Lines changed: 111 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
# Changelog
22

3-
### v2.16.1 (2026-03-17)
3+
### v2.17.0 (2026-03-17)
4+
- **Feature:** Add `roam_fetch_page_full_view` tool + CLI `roam get full` — full page view with content + linked references (#15)
5+
- Page's own content (blocks + heading structure)
6+
- All linked references grouped by source page with breadcrumb context
7+
- Children of each referring block expanded to configurable depth (default 4)
8+
- `max_references` safety valve (default 200) prevents timeouts on heavily-referenced pages
9+
- CLI: `roam get full "Page Title" [-d depth] [-n max-refs]`
10+
- **Feature:** Add `roam_get_subpages` tool + CLI `roam get subpages` — namespace-based sub-page listing
11+
- Lists pages under a prefix (e.g. "Project/", "Framework/")
12+
- Optional `filter_tag` to filter sub-pages containing a specific tag
13+
- Optional `include_content` to include full block content
14+
- CLI: `roam get subpages "Prefix" [--filter-tag tag] [--content]`
15+
- **Refactor:** Extract `fetchChildrenByDepth` into shared helper (`src/tools/helpers/fetch-children.ts`)
16+
- **Fix:** `convertToRoamActions` now correctly passes through `'first'`/`'last'` order strings instead of replacing with index
417
- **Fix:** CLI `roam save <file.md> -p <page>` ignored `-p` flag and created a page from the filename
5-
- When a file was passed as input, the command unconditionally entered PAGE MODE even when `-p` specified a target page
6-
- Now file inputs with `-p` correctly append content to the specified page instead of deriving a page title from the filename
7-
- Affected: any pipeline using `roam save <file> -p <page>` (e.g., AIIntel nightly delivery)
18+
- **Fix:** Typo in `roam_add_content` schema description
819

920
### v2.16.0 (2026-03-16)
1021
- **Feature:** Renamed `roam_fetch_block_with_children``roam_fetch_block` with bidirectional traversal

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,11 @@ The MCP server exposes these tools to AI assistants (like Claude), enabling them
8888
| Tool Name | Description |
8989
| :--- | :--- |
9090
| `roam_fetch_page_by_title` | Fetch page content by title. |
91+
| `roam_fetch_page_full_view` | Fetch a page's content plus all linked references with breadcrumb context and children. |
9192
| `roam_fetch_block` | Fetch a block by UID with optional children (depth) and/or ancestors (up to page root). |
9293
| `roam_create_page` | Create new pages, optionally with mixed text and table content. |
9394
| `roam_update_page_markdown` | Update a page using smart diff (preserves block UIDs). |
95+
| `roam_get_subpages` | List sub-pages under a namespace prefix (e.g. "Project/") with optional tag filter. |
9496
| `roam_search_by_text` | Full-text search across the graph or within specific pages. Supports namespace prefix search for page titles. |
9597
| `roam_search_block_refs` | Find blocks that reference a page, tag, or block UID. |
9698
| `roam_search_by_status` | Find TODO or DONE items. |

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "roam-research-mcp",
3-
"version": "2.16.1",
3+
"version": "2.17.0",
44
"description": "MCP server and CLI for Roam Research",
55
"private": false,
66
"repository": {

src/cli/ROAM-CLI-REFERENCE_LLM.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
2-
version: 2.16.0
2+
version: 2.17.0
33
date: 2026-01-12
4-
last_modified: 2026-03-16
4+
last_modified: 2026-03-17
55
---
66

77
# Roam CLI Reference (LLM-Optimized)
@@ -23,6 +23,8 @@ roam batch -g system --write-key "$ROAM_SYSTEM_WRITE_KEY" commands.json
2323
roam get <title|today|yesterday|tomorrow> # page by title
2424
roam get <9-char-uid> # block by UID
2525
roam get page <uid|url|title> # explicit page (URL/UID/title)
26+
roam get full <title> # full view: content + linked refs
27+
roam get subpages <prefix> # list namespace sub-pages
2628
roam get --uid <title> # resolve title→UID only
2729
roam get --todo [-p <page>] [-i terms] [-e terms]
2830
roam get --done [-p <page>]
@@ -32,7 +34,10 @@ roam get --text <text> [-p <page>]
3234

3335
Options: `-j` json, `-d N` depth (0=no children), `-a` ancestors (chain to page root), `-r [N]` expand refs, `-f` flat, `--sort created|modified|page`, `--group-by page|tag`
3436

35-
**Subcommand:** `roam get page <identifier>` - fetches page by UID, Roam URL, or title explicitly
37+
**Subcommands:**
38+
- `roam get page <identifier>` - fetches page by UID, Roam URL, or title explicitly
39+
- `roam get full <title>` - full page view: content + all linked references with breadcrumb context. Options: `-d N` depth (default 4), `-n N` max refs (default 200)
40+
- `roam get subpages <prefix>` - list sub-pages under namespace prefix (e.g. "Project/"). Options: `--filter-tag <tag>`, `--content`
3641

3742
### `roam search` - Query
3843

@@ -145,6 +150,8 @@ roam status --json # for scripting
145150
| Multiple tags (OR) | `roam get --tag Tag1 --tag Tag2 --any` |
146151
| Block + ancestors | `roam get <uid> -a` |
147152
| Ancestors only | `roam get <uid> -a -d 0` |
153+
| Full view + backlinks | `roam get full "Page"` |
154+
| List sub-pages | `roam get subpages "Prefix"` |
148155
| Quick note | `roam save "Note"` |
149156
| Note to page | `roam save "Note" -p "Page"` |
150157
| Under heading | `roam save --parent "## Section" "Note"` |

src/cli/commands/get.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Command } from 'commander';
22
import { PageOperations } from '../../tools/operations/pages.js';
33
import { BlockRetrievalOperations } from '../../tools/operations/block-retrieval.js';
44
import { SearchOperations } from '../../tools/operations/search/index.js';
5+
import { FullPageViewOperations } from '../../tools/operations/full-page-view.js';
56
import {
67
formatPageOutput,
78
formatBlockOutput,
@@ -248,6 +249,86 @@ Examples:
248249
});
249250
}
250251

252+
/**
253+
* Create the 'full' subcommand for full page view (content + linked references)
254+
*/
255+
function createFullSubcommand(): Command {
256+
return new Command('full')
257+
.description('Fetch full page view: content + linked references with breadcrumb context')
258+
.argument('<title>', 'Page title (for date pages use "January 2nd, 2025")')
259+
.option('-d, --depth <n>', 'Child depth for referring blocks (default: 4)', '4')
260+
.option('-n, --max-refs <n>', 'Max linked references (default: 200)', '200')
261+
.option('-g, --graph <name>', 'Target graph key (multi-graph mode)')
262+
.option('--debug', 'Show debug information')
263+
.addHelpText('after', `
264+
Examples:
265+
roam get full "Project Notes" # Full view with backlinks
266+
roam get full "TODO" -n 50 # Cap references at 50
267+
roam get full "Meeting Notes" -d 2 # Shallow children depth
268+
`)
269+
.action(async (title: string, options: GraphOptions & { depth?: string; maxRefs?: string; debug?: boolean }) => {
270+
try {
271+
const resolvedTitle = resolveRelativeDate(title);
272+
const depth = parseInt(options.depth || '4', 10);
273+
const maxRefs = parseInt(options.maxRefs || '200', 10);
274+
275+
if (options.debug) {
276+
printDebug('Title', resolvedTitle);
277+
printDebug('Children depth', depth);
278+
printDebug('Max references', maxRefs);
279+
printDebug('Graph', options.graph || 'default');
280+
}
281+
282+
const graph = resolveGraph(options, false);
283+
const pageOps = new PageOperations(graph);
284+
const fullViewOps = new FullPageViewOperations(graph, pageOps);
285+
const result = await fullViewOps.fetchPageFullView(resolvedTitle, depth, maxRefs);
286+
console.log(result);
287+
} catch (error) {
288+
const message = error instanceof Error ? error.message : String(error);
289+
exitWithError(message);
290+
}
291+
});
292+
}
293+
294+
/**
295+
* Create the 'subpages' subcommand for namespace-based sub-page listing
296+
*/
297+
function createSubpagesSubcommand(): Command {
298+
return new Command('subpages')
299+
.description('List sub-pages under a namespace prefix (e.g. "Project/", "Framework/")')
300+
.argument('<prefix>', 'Namespace prefix (trailing "/" added automatically)')
301+
.option('--filter-tag <tag>', 'Only sub-pages containing this tag')
302+
.option('--content', 'Include each sub-page\'s block content')
303+
.option('-g, --graph <name>', 'Target graph key (multi-graph mode)')
304+
.option('--debug', 'Show debug information')
305+
.addHelpText('after', `
306+
Examples:
307+
roam get subpages "Project" # List all Project/* pages
308+
roam get subpages "Framework" --content # With block content
309+
roam get subpages "Project" --filter-tag active # Only active projects
310+
`)
311+
.action(async (prefix: string, options: GraphOptions & { filterTag?: string; content?: boolean; debug?: boolean }) => {
312+
try {
313+
if (options.debug) {
314+
printDebug('Prefix', prefix);
315+
printDebug('Filter tag', options.filterTag || 'none');
316+
printDebug('Include content', options.content || false);
317+
printDebug('Graph', options.graph || 'default');
318+
}
319+
320+
const graph = resolveGraph(options, false);
321+
const pageOps = new PageOperations(graph);
322+
const fullViewOps = new FullPageViewOperations(graph, pageOps);
323+
const result = await fullViewOps.fetchSubPages(prefix, options.filterTag, options.content);
324+
console.log(result);
325+
} catch (error) {
326+
const message = error instanceof Error ? error.message : String(error);
327+
exitWithError(message);
328+
}
329+
});
330+
}
331+
251332
export function createGetCommand(): Command {
252333
const cmd = new Command('get')
253334
.description('Fetch pages, blocks, or TODO/DONE items with optional ref expansion')
@@ -708,6 +789,8 @@ Note: For flat results with UIDs, use 'roam search' instead.
708789

709790
// Add subcommands
710791
cmd.addCommand(createPageSubcommand());
792+
cmd.addCommand(createFullSubcommand());
793+
cmd.addCommand(createSubpagesSubcommand());
711794

712795
return cmd;
713796
}

0 commit comments

Comments
 (0)