Documentation
Getting started
titlebase is one program, tbase. It opens a title plant file, searches it, edits it with undo and saves it back, byte for byte where nothing changed. This page takes you from nothing to your first saved edit in a few commands.
What you need
- A Mac.
- A title plant file. That is a titlebase file (
.titlebase) or any PropertySync plant export (.db). Both open as they are. - Enough disk for the plant and a search index beside it (about a fifth of the plant's size).
Get tbase
Builds of tbase come from Limelyte. If you have the source, build the binary with Cargo:
cargo build --release
./target/release/tbase --versionPut tbase on your PATH so the examples below work as written.
Open a plant
Every command takes the plant file as its first argument. Start with file info:
tbase file info sample-county-tx.titlebasesample-county-tx.titlebase
size 4.9 MB
page size 4096
documents 2400
landvalidations 4
autocompletes 11
rows are highest id
tbase: file_info in 0.00sRow counts come from the highest row id, which is instant on any size of plant. Add--exact to count every row. The timing line goes to stderr, so it never mixes with output you pipe.
Find documents
Search by instrument number, instrument type, party and addition. Every filter you give must match.
tbase docs search sample-county-tx.titlebase --type WD --party DOE \
--addition "SAMPLE ADDITION 5" --limit 3 5 1994-001288 WD 829/642 1994-11-02 DOE, JANE -> FIRST SAMPLE BANK [SAMPLE ADDITION 5]
75 2015-001350 WD 849/610 2015-09-08 DOE, JANE -> ROE, RICHARD [SAMPLE ADDITION 5]
80 1991-000492 WD 563/813 1991-03-05 GARCIA, ANA -> DOE, JANE [SAMPLE ADDITION 5]
3 documents, more after id 80 (--after-id 80)Pass --after-id to get the next page. Then open one document by row id or UUID to see its full stored JSON:
tbase docs get sample-county-tx.titlebase 75Without an index, search scans the plant and says so. It stops at --limitmatches, so a search with few matches reads the whole plant. Build the index next.
Auto completes and land validations have their own commands:
tbase ac list sample-county-tx.titlebase --type addition
tbase lv list sample-county-tx.titlebase --addition "SAMPLE ADDITION 5"Build the index
The index lives in a folder beside the plant, sample-county-tx.titlebase.tbase/. The plant itself is never changed. Build it once; it is reused until the plant changes.
tbase index build sample-county-tx.titlebase
tbase index status sample-county-tx.titlebaseWith the index, search adds filed dates, grantor and grantee, lot and block, and book and page, and sorts by any column. --count adds the total.
tbase docs search sample-county-tx.titlebase --addition "SAMPLE ADDITION 5" --lot 4 --sort filed_date --direction desc --limit 3 --count 142 2026-000982 WD 727/573 2026-07-16 DOE, JANE -> GARCIA, ANA [SAMPLE ADDITION 5]
949 2026-001815 MTG 1004/361 2026-05-28 NGUYEN, KIM -> SMITH, ALEX [SAMPLE ADDITION 5]
1558 2022-000359 DT 519/010 2022-07-17 DOE, JANE -> SMITH, ALEX [SAMPLE ADDITION 5]
3 documents
31 matches in all
more: --cursor '{"sort":"filed_date","direction":"desc","key":"2022-07-17","id":1558}'
(indexed: answered from the sidecar index sample-county-tx.titlebase.tbase/index.db)Sorted results page with --cursor. Party filters can match a prefix or anywhere in the name with --party-match contains.
Edit, undo and save
Edits never touch the plant file. Each write is one journaled run in the same folder beside the plant, and it tells you how to undo it.
tbase docs update sample-county-tx.titlebase 75 --set 'grantees.0.nameFirst=RICHARD A'updated document 07e58eaf-5e22-04da-6941-01d32e8b3ec8 (row 75): /grantees/0/nameFirst
run 1, op 1
undo: tbase changes undo sample-county-tx.titlebase --run 1--set takes a dotted path or a JSON Pointer. The value is JSON when it parses and text otherwise. --remove clears a field. Edited rows keep their shape and PropertySync style. Auto completes and land validations have the samecreate, update and delete commands.
tbase changes list sample-county-tx.titlebase # what changed, per table
tbase undo sample-county-tx.titlebase # undo the newest run; also tbase redo
tbase changes revert sample-county-tx.titlebase --row 75When you are happy, save a new file, or save in place and keep a backup:
tbase save sample-county-tx.titlebase --out sample-county-tx-edited.titlebase
tbase save sample-county-tx.titlebase --in-placesaved sample-county-tx-edited.titlebase
documents 2400 rows: 2399 unchanged, 1 updated, 0 deleted, 0 created
landvalidations 4 rows: 4 unchanged, 0 updated, 0 deleted, 0 created
autocompletes 11 rows: 11 unchanged, 0 updated, 0 deleted, 0 created
verified trueSave writes a new file and checks it by reopening it. Untouched rows stay byte-identical. To send only what changed, export a change batch: a PropertySync batch with documents, auto completes, land validations and deletions.
tbase changes export sample-county-tx.titlebase --out ./batchesOnly one process writes to a plant at a time. A second writer gets a locked error.
JSON output
Add --json to any command. You get one JSON document on stdout and nothing else. Errors exit with status 1 and print an error object. No command ever prompts.
tbase --json file info sample-county-tx.titlebase{
"file": "sample-county-tx.titlebase",
"bytes": 4943872,
"page_size": 4096,
"rows": { "documents": 2400, "landvalidations": 4, "autocompletes": 11 },
"rows_are": "highest_id",
"extra_tables": []
}{ "error": { "code": "not_found", "message": "not found: document 99999" } }Every command's input and output is described by a JSON Schema. tbase commands --json prints them all.
Prove the round trip
check roundtrip parses every row and writes it back with titlebase's own writers, then counts the rows that come back byte-identical. It never modifies the file.
tbase check roundtrip sample-county-tx.titlebase
tbase check roundtrip sample-county-tx.titlebase --copy-to /tmp/copy.titlebaseWith --copy-to it also writes a whole new file and compares every row and the schema. On eight real plants, up to 6.3 million documents, every row came back identical.
Connect an agent
Register titlebase with Claude Code, or any MCP client, and your agent gets every command as a tool:
claude mcp add titlebase -- tbase mcpSee MCP server for other clients and for binding the server to one plant.