The dl binary is the command-line front end. It has commands for loading facts, querying relations, publishing snapshots, and the search tier (full-text + semantic). The database directory defaults to dl-test-db and can be set with -d <dir>. Command values that parse as bare integers are stored raw as u32; anything else is interned to a string symbol id.
dl [-d <dir>] load <csv> --rel <name> dl [-d <dir>] lookup <rel> <val> [<val> ...] dl [-d <dir>] prefix <rel> [<val> ...] dl [-d <dir>] query '<rule>' | <file.dl> <goal-rel> dl [-d <dir>] qmagic '<rule>' | <file.dl> <goal-rel> [-a <adorn>] <val> [<val> ...] dl [-d <dir>] publish dl [-d <dir>] bound <rel> <val> [<val> ...] dl [-d <dir>] pattern <rel> '<regex>' dl [-d <dir>] search '<terms>' [--top N] [--version N] dl [-d <dir>] vsearch '<query>' [--k N] [--radius R] [--version V] [--sig <hex>] [--ivec <hex>] dl [-d <dir>] vhybrid '<terms>' '<query>' [--k N] [--radius R] [--version V] dl [-d <dir>] versions
Load facts from a headerless CSV file into a relation (arity 1–8).
$ ./dl -d /tmp/db load edges.csv --rel edge Loaded 5 facts into edge
The relation’s arity is inferred from the first non-empty CSV row. Values: quoted strings are interned; bare integers are stored raw as u32.
Exact lookup of a fact by its full column values. Prints found or not found.
$ ./dl -d /tmp/db lookup edge 1 2 found $ ./dl -d /tmp/db lookup edge 9 9 not found
Bind the leading columns to the given values and enumerate every matching complete tuple.
# all tuples $ ./dl -d /tmp/db prefix edge 1 2 1 3 2 3 2 4 3 5 # tuples with leading column == 2 $ ./dl -d /tmp/db prefix edge 2 2 3 2 4
With no bound values, this lists the whole relation.
Parse, compile, and run a Datalog rule in one step, then stream the goal relation’s tuples. The rule source may be a quoted inline string or a .dl file path; the goal is the relation to print.
$ ./dl -d /tmp/db query \
'tc(X,Y) :- edge(X,Y). tc(X,Y) :- edge(X,Z), tc(Z,Y).' tc
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 5Internally this loads the rules, publishes a snapshot (running the VM if the fixpoint is dirty), then queries the goal relation.
Magic-sets bound query: evaluates a scoped fixpoint seeded by the bound values, materialising only the reachable IDB slice. The result is byte-for-byte identical to dl_query_bound over the fully materialized goal.
# leading-prefix form: bind the first k args
$ ./dl -d /tmp/db qmagic \
'tc(X,Y) :- edge(X,Y). tc(X,Y) :- edge(X,Z), tc(Z,Y).' tc 1
# arbitrary-adornment form: -a <adorn> binds named positions
$ ./dl -d /tmp/db qmagic \
'tc(X,Y) :- edge(X,Y). tc(X,Y) :- edge(X,Z), tc(Z,Y).' tc -a "bf" 1The optional -a <adorn> is a string of exactly goal-arity characters, each b (bound) or f (free); vals are packed left-to-right in the order of the b positions. Programs using negation, aggregates, or cross-predicate mutual recursion are rejected with a diagnostic.
The CLI exposes the snapshot timeline directly. publish writes an immutable, versioned snapshot; versions lists the history; bound reads the current snapshot view; and the search tier accepts --version N to query as-of a past snapshot. Together these make time-traveling queries a first-class CLI capability.
# Record a point-in-time, then inspect the history. $ ./dl -d /tmp/db publish Snapshot published. $ ./dl -d /tmp/db versions 1 2 3 # Search as-of a past snapshot (full-text + semantic). $ ./dl -d /tmp/db search 'gpu rental' --top 10 --version 2 $ ./dl -d /tmp/db vsearch 'GPU rental' --k 10 --version 2
See the time-travel guide for the full as-of API.
Atomically publish a versioned snapshot of the database — the write side of time travel.
$ ./dl -d /tmp/db publish Snapshot published.
After publishing, query reads from mmap instead of running the VM.
Bound query (snapshot path): bind leading columns and enumerate via the snapshot view.
$ ./dl -d /tmp/db bound edge 1 1 2 1 3
Enumerate all tuples whose full key matches a regex.
$ ./dl -d /tmp/db pattern edge '(a|b).*'
A bad pattern is a loud error.
Full-text search over the __postings__ index: AND-intersect the tokenized terms and rank by co-occurrence. --version N queries the index as-of a published snapshot (0 = live).
$ ./dl -d /tmp/db search 'gpu rental' --top 10 $ ./dl -d /tmp/db search 'gpu rental' --top 10 --version 3
Semantic vector search: embed the query with the bge-small model (via the dl-embed tool), retrieve MIH candidates from the __sig*__ postings, and re-rank by in-store int8 cosine. Accepts --sig/--ivec hex for a programmatic path that needs no model, and --version V to search as-of a snapshot.
$ ./dl -d /tmp/db vsearch 'affordable GPU rental' --k 10
See the vector-search page for the full semantic tier.
Lexical ∩ semantic hybrid: intersect search results with vsearch candidates, then re-rank the intersection.
$ ./dl -d /tmp/db vhybrid 'gpu rental' 'affordable GPU rental' --k 10
List the published snapshot versions (ascending) — the timeline.
$ ./dl -d /tmp/db versions
The top-down / QSQ path (dl_query_topdown / dl_query_topdown_adorn) is available only through the C API — there is no topdown CLI subcommand. Likewise, order-statistics (rank / select / range / count) are C-API only. The semantic search tier relies on the dl-embed companion tool (built with make dl-embed) for query-time embedding.