The notes_browser supports remote control via JSON-RPC 2.0 protocol over three transport modes:
All requests use line-delimited JSON format. Each JSON-RPC request is sent as a single line followed by newline (LF) character.
--control-tcp-enabled --control-tcp-port 8711localhost:8711Health check - returns current page key
Request: {"jsonrpc": "2.0", "id": 1, "method": "status.ping", "params": {}}
Response: {"jsonrpc": "2.0", "id": 1, "result": {"ok": true, "page": "current/page/key"}}
List all available RPC methods and browser capabilities
Request: {"jsonrpc": "2.0", "id": 1, "method": "status.capabilities", "params": {}}
Response: {"jsonrpc": "2.0", "id": 1, "result": {"version": 1, "read_only": true, "methods": [...]}}
Navigate to a specific page by key
Params: {"key": "page/key"}
Result: {"page": "page/key"}
Go back in navigation history
Params: {}
Result: {"page": "previous/page"}
Go forward in navigation history
Params: {}
Result: {"page": "next/page"}
Params: {}
Result: {"page": ""}
Refresh current page from data source
Params: {}
Result: {"page": "current/page"}
Get current page key and URL
Params: {}
Result: {"key": "current/page", "url": "http://base/url/current/page"}
Get current page JSONHTL document
Params: {}
Result: {"document": {"title": "...", "content": [...]}}
Write a JSONHTL document to a page key
Params: {"key": "page/key", "document": {...}}
Result: {"status": "ok", "key": "page/key"}
Get all rendered text from current page (blocks joined by newlines)
Params: {}
Result: {"text": "rendered page text..."}
Get current zoom percentage
Params: {}
Result: {"zoom_percent": 100}
Increase zoom by 10%
Params: {}
Result: {"zoom_percent": 110}
Params: {}
Result: {"zoom_percent": 100}
Set zoom to specific percentage
Params: {"zoom_percent": 150}
Result: {"zoom_percent": 150}
Scroll by number of pages (positive=down, negative=up)
Params: {"pages": 1}
Result: {"scrolled": true, "pages": 1}
Get current selection range and mode
Params: {}
Result: {"selection": {"block_start": 0, "offset_start": 0, "block_end": 0, "offset_end": 5}, "selection_mode": "logical-only"}
Set selection by block indices and offsets
Params: {"block_index_start": 0, "offset_start": 0, "block_index_end": 0, "offset_end": 5}
Result: {"selection": {...}, "native_selected": true, "selection_mode": "native-word"}
Select first occurrence of a word using native word-selection
Params: {"text": "word", "occurrence": 1}
Result: {"selected_text": "word", "selection_mode": "native-word"}
Select a line containing text using native line-selection
Params: {"text": "partial text", "occurrence": 1}
Result: {"selected_text": "full line containing partial text...", "selection_mode": "native-line"}
Read text from current selection
Params: {}
Result: {"text": "selected text...", "selection_mode": "logical-only"}
Replace selected text and persist document
Params: {"text": "replacement text"}
Result: {"selection": {...}, "text": "replacement text", "selection_mode": "logical-only"}
Set selection and capture screenshot with highlighted region
Params: {"block_index_start": 0, "offset_start": 0, "block_index_end": 0, "offset_end": 5, "path": "/path/to/output.png"}
Result: {"selection": {...}, "text": "...", "path": "/path/to/output.png"}
Get current page link information
Params: {}
Result: {"key": "current/page", "url": "http://base/url/current/page"}
Capture current window as PNG
Params: {"path": "optional/output/path.png"}
Result: {"path": "/absolute/path/to/screenshot.png"}
Capture window as SIXEL terminal graphics format
Params: {"path": "optional/output.txt", "include_data": true}
Result: {"format": "sixel-body", "width": 1024, "height": 768, "colors": 216, "sixel": "...", "path": "..."}
Resize browser window
Params: {"width": 1024, "height": 768}
Result: {"width": 1024, "height": 768}
Close browser window and exit
Params: {}
Result: {"status": "quitting"}
JSON-RPC 2.0 errors follow standard format:
import socket
import json
def send_rpc(method, params=None):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect(('127.0.0.1', 8711))
cmd = {
'jsonrpc': '2.0',
'id': 1,
'method': method,
'params': params or {}
}
sock.sendall((json.dumps(cmd) + '\n').encode('utf-8'))
response = sock.recv(8192).decode('utf-8')
return json.loads(response)
finally:
sock.close()
# Navigate and capture
send_rpc('navigate.go_to_page', {'key': 'setup/notes-browser'})
send_rpc('ui.capture_screenshot', {'path': 'test.png'})
import socket
import json
def send_rpc(method, params=None):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect(('127.0.0.1', 8711))
cmd = {
'jsonrpc': '2.0',
'id': 1,
'method': method,
'params': params or {}
}
sock.sendall((json.dumps(cmd) + '\n').encode('utf-8'))
response = sock.recv(8192).decode('utf-8')
return json.loads(response)
finally:
sock.close()
# Navigate and capture
send_rpc('navigate.go_to_page', {'key': 'setup/notes-browser'})
send_rpc('ui.capture_screenshot', {'path': 'test.png'})
send_rpc('ui.quit')
# TCP only (default)
python3 notes_browser.py --url http://127.0.0.1:8021 --control-tcp-enabled
# TCP on custom port
python3 notes_browser.py --url http://127.0.0.1:8021 \
--control-tcp-enabled --control-tcp-port 9000
# TCP + UDP (both enabled)
python3 notes_browser.py --url http://127.0.0.1:8021 \
--control-tcp-enabled --control-udp-enabled
# From config file
python3 notes_browser.py --config ~/.notes_browser.yaml
notes_url: http://127.0.0.1:8021
html_base_url: http://127.0.0.1/notes
control_tcp_enabled: true
control_tcp_port: 8711
control_host: 127.0.0.1
control_token: ''
render_font_family: "'Courier New', Courier, monospace"
render_font_size_pt: 10