A fast, keyboard-driven terminal client and Rust SDK for Roam Research. Navigate, edit, and search your knowledge graph without leaving the terminal — or use the SDK to build your own tools.
┌─────────────────────────────────────────────────────────┐
│ roam-tui [Graph: my-graph] Feb 24, 2026 │
├─────────────────────────────────────────────────────────┤
│ │
│ February 24, 2026 │
│ │
│ • Meeting notes with [[John]] │
│ • Discussed Q1 roadmap │
│ • Action items: ((ref-uid)) │
│ ▸ Project ideas [3 collapsed] │
│ • Read chapter 5 of **Deep Work** │
│ • Key insight: time blocking works │
│ │
│ February 23, 2026 │
│ │
│ • Finished migration to new API │
│ • {{DONE}} Review PR #42 │
│ │
├─────────────────────────────────────────────────────────┤
│ [i]edit [o]new [/]search [?]help [h/l]collapse/expand│
└─────────────────────────────────────────────────────────┘
Roam Research is powerful but lives in the browser. If you spend most of your day in the terminal, context switching costs add up. roam-tui gives you direct access to your graph — fast, focused, and keyboard-first.
Not a replacement for the web UI. Use roam-tui for quick capture, daily note workflows, and navigating your graph. Use the web for complex queries, graph visualization, and plugin-heavy workflows.
git clone https://github.com/avelino/roam-tui
cd roam-tui
cargo install --path .- Rust 1.70+
- A Roam Research graph with an API token (how to get one)
Run roam for the first time — it creates a config file and tells you where:
roam
# → Created default config at: ~/.config/roam-tui/config.toml
# → Please edit it with your Roam graph name and API token, then run again.Add your credentials:
# ~/.config/roam-tui/config.toml
[graph]
name = "your-graph-name"
api_token = "roam-graph-token-XXXXX"Or use an environment variable:
export ROAM_GRAPH_API__TOKEN="roam-graph-token-XXXXX"Run again:
roamYour daily note loads. Start navigating.
Opens today's note on launch. Navigate to previous days with P / PageUp (vim) or scroll past the last block to auto-load older days. Jump back to today with G.
Full block editing with vim-style modal workflow:
ito edit the selected block,Escto save and exitoto create a new block belowddto delete a blockTab/Shift+Tabto indent/unindent- Undo with
u, redo withCtrl+R - Auto-pairing for
(),[],{} {{TODO}}/{{DONE}}toggle withAlt+EnterorCtrl+Enter
Blocks with children can be collapsed (h) and expanded (l). Press Enter to toggle. Collapsed blocks hide their children from navigation and display — just like the web UI.
Press / to open a search popup. Type to filter across all loaded blocks and cached references. Navigate results with arrow keys, press Enter to jump to the block.
Type (( in edit mode to open the autocomplete popup. Search for any block by content, select with Enter. References are resolved and displayed inline.
Blocks render with full Roam syntax support:
| Syntax | Rendering |
|---|---|
**bold** |
Bold text |
__italic__ |
Italic text |
~~strikethrough~~ |
Strikethrough |
^^highlight^^ |
Highlighted text |
`code` |
Inline code |
[[Page Name]] |
Page link (cyan) |
((block-uid)) |
Block reference (resolved) |
#tag |
Tag (cyan) |
{{TODO}} / {{DONE}} |
Checkbox markers |
{{embed: ((uid))}} |
Embedded block |
Fenced code blocks (```) render with syntax highlighting via tree-sitter. Supported languages: Rust, Python, JavaScript, TypeScript, Go, C, Bash, JSON, TOML, YAML, HTML, CSS, Markdown.
Press ? to see all keybindings for your current preset. Any key closes the help overlay.
API errors (rate limits, auth failures, network issues) appear as a popup overlay with a human-readable title and hint instead of raw JSON. Any key dismisses the popup.
Three built-in presets. Set with keybindings.preset in config.
| Action | vim | emacs | vscode |
|---|---|---|---|
| Move up | k / Up |
Ctrl+P / Up |
Up |
| Move down | j / Down |
Ctrl+N / Down |
Down |
| Cursor left | Left |
Left |
Left |
| Cursor right | Right |
Right |
Right |
| Collapse | h |
Ctrl+B |
Ctrl+Left |
| Expand | l |
Ctrl+F |
Ctrl+Right |
| Toggle open | Enter |
Enter |
Enter |
| Next day | N / PageDown |
Alt+N / PageDown |
Alt+Up / PageDown |
| Previous day | P / PageUp |
Alt+P / PageUp |
Alt+Down / PageUp |
| Go to today | G |
Ctrl+D |
Ctrl+D |
| Navigate back | Ctrl+O / Shift+Left / Alt+[ |
Shift+Left / Alt+[ |
Shift+Left / Alt+[ |
| Navigate forward | Shift+Right / Alt+] |
Shift+Right / Alt+] |
Shift+Right / Alt+] |
| Action | vim | emacs | vscode |
|---|---|---|---|
| Edit block | i |
Enter |
Enter |
| New block | o |
Alt+Enter |
Ctrl+Enter |
| Delete block | dd |
— | — |
| Search | / |
Ctrl+S |
Ctrl+Shift+F |
| Undo | u |
Ctrl+/ |
Ctrl+Z |
| Redo | Ctrl+R |
Ctrl+Shift+/ |
Ctrl+Shift+Z |
| Help | ? |
Ctrl+H |
F1 |
| Quick switcher | Ctrl+P |
— | Ctrl+P |
| Toggle sidebar | b |
— | Ctrl+B |
| Quit | q |
Ctrl+Q |
Ctrl+Q |
| Action | Key |
|---|---|
| Save and exit | Esc |
| Move cursor | Arrow keys, Home, End |
| Move by word | Ctrl+Left / Ctrl+Right |
| Toggle TODO | Alt+Enter or Ctrl+Enter |
| Block ref autocomplete | (( |
| Indent | Tab |
| Unindent | Shift+Tab |
Override any key in the config file:
[keybindings]
preset = "vim"
[keybindings.bindings]
quit = "Ctrl+q"
search = "Ctrl+f"Config file location: ~/.config/roam-tui/config.toml
All options with defaults:
[graph]
name = "" # required — your Roam graph name
api_token = "" # required — or set ROAM_GRAPH_API__TOKEN env var
[ui]
theme = "dark" # dark | light
sidebar_default = true # show sidebar on startup
sidebar_width_percent = 35 # sidebar width as percentage
[keybindings]
preset = "vim" # vim | emacs | vscode
# [keybindings.bindings] # override individual keys
# quit = "Ctrl+q"Environment variables override config file values. Prefix with ROAM_, use __ for nesting:
ROAM_GRAPH_NAME=my-graph
ROAM_GRAPH_API__TOKEN=roam-graph-token-XXXXXsrc/
main.rs Entry point, terminal setup
app.rs State machine, event loop, actions
config.rs TOML + env var configuration
edit_buffer.rs Text editing with cursor management
markdown.rs Roam-flavored markdown parser
highlight.rs Tree-sitter syntax highlighting
api/
client.rs HTTP client (reqwest + rustls)
queries.rs Datalog query builders
types.rs Block, DailyNote, WriteAction types
keys/
mod.rs Keybinding resolution
preset.rs vim/emacs/vscode presets
parser.rs Key string parser ("Ctrl+k" → KeyEvent)
ui/
mod.rs Layout + popups (search, help, autocomplete)
header.rs Graph name + date
main_area.rs Block tree rendering
status_bar.rs Hints + mode indicator
Built on Ratatui + Tokio + Roam Backend API.
What's working now and what's next.
- Daily notes with multi-day navigation
- Block tree editing (create, edit, delete, indent, move)
- Collapse/expand blocks
- Undo/redo
- Full-text search across blocks
- Block reference autocomplete (
(() - Markdown + Roam syntax rendering
- Code block syntax highlighting (14 languages)
- Three keybinding presets (vim, emacs, vscode)
- Custom keybinding overrides
- Help overlay
- Optimistic UI updates (no lag on edits)
- Auto-refresh from API
- Page navigation (follow
[[links]]) - Navigation history (back/forward)
- Cursor navigation (left/right within blocks)
- User-friendly error popups (rate limits, auth, network)
- Quick switcher (fuzzy page navigation)
- Linked references / backlinks panel
- Page creation from
[[links]]and Quick Switcher
- Sidebar with page references
- Unlinked references
- Light theme
- Breadcrumb display
git clone https://github.com/avelino/roam-tui
cd roam-tui
cargo test # 339 tests
cargo run # requires config with valid API tokenTests run without network access — API interactions use wiremock for mocking.
MIT — see LICENSE for details.