Skip to main content

A transparent, read-only SQL query layer over Open Knowledge Format (OKF) bundles.

Project description

readb

A transparent, read-only SQL query layer over an Open Knowledge Format (OKF) bundle — a directory of markdown files with YAML frontmatter — so an agent or a human can run real SQL against the wiki with no explicit database-creation step.

readb loads a bundle into an embedded DuckDB engine and lets DuckDB execute the SQL. There is no custom SQL parser or query planner, and the source files are never modified.

Status: MVP implemented. Bundle loading, type inference, the library API, and the CLI all work; the 12 acceptance criteria in docs/design-brief.md are covered by tests. Not yet built (left as clean seams): persistent on-disk index, git-aware incremental rebuild, and write-back — all explicit non-goals for this MVP.

Install

uv sync

Usage

Library:

import readb

db = readb.open("./path/to/bundle")          # builds an in-memory DuckDB; no files written
rows = db.sql("SELECT * FROM __DOCUMENTS WHERE type = 'Metric'")

CLI:

readb query "SELECT * FROM __DOCUMENTS" --bundle ./path       # results as a table
readb query "SELECT * FROM __DOCUMENTS" --bundle ./path --format json   # or csv | tsv | raw
readb schema --bundle ./path                                  # detected types, tables, columns
readb show --bundle ./path some-concept                       # a concept's body, by name

Concepts are addressed wiki-style: a simple file name (some-concept) when it is unique in the bundle, or the full path (sub/some-concept.md) — always unambiguous — when it is not. An ambiguous bare name is always a hard error listing the clashing paths — never a silent first match. Names are filenames: __name is immutable and filename-derived, and a producer name: frontmatter key is just an ordinary data column — it affects neither __name nor addressing.

readb init: skip --bundle

--bundle may be omitted once you register your bundles (the git model — a directory is a bundle because you said so once):

readb init tasks docs/adr    # in the project root: writes .readb/config.toml (commit it)
cd tasks && readb query "SELECT count(*) FROM task"   # bundle resolved by walking up

Commands without --bundle walk up from the cwd to the nearest .readb/ registry, then pick the declared bundle containing the cwd (innermost wins), else the sole declared bundle, else the config's optional default_bundle. Genuine ambiguity — e.g. the root of a repo declaring several bundles, no default — is a hard error listing the choices, never a guess; a directory never silently becomes a bundle. Explicit --bundle <dir> always works on any directory, initialized or not, and never consults the registry. Re-running init merges new dirs and never removes. Besides the config, .readb/ is reserved for readb's future persistent index — it is never read as bundle content. readb only addresses files inside the bundle root: a ../ path or a symlink that resolves outside the bundle is not supported and is refused with an explicit error (by name and by path alike). --format raw prints values verbatim, so readb query "SELECT __raw FROM task WHERE __name = 'x'" --format raw is exactly cat.

Tables and views

Name Rows
__DOCUMENTS one per concept (the six reserved OKF fields + the virtual fields below)
per-type tables one per detected type; columns are reserved fields + the union of producer keys across docs of that type
__INDEXES one per reserved index.md file; columns are the union of their frontmatter fields
__LOG one per reserved log.md file (created only if any exist)
__UNKNOWNTYPE one per non-conformant concept (no / non-string / empty-normalized type)
__TAGS normalized (concept_path, tag) view for join-style tag filtering

Every table also carries four virtual columns: __path (bundle-relative path, with .md — the guaranteed-unique key), __name (the simple file name, no directories or .md; wiki-style, assumed unique but not guaranteed), __body (the markdown body, frontmatter stripped), and __raw (the byte-exact file text as on disk, frontmatter included).

Type inference

Each column's type is inferred once at load time as the narrowest DuckDB type that losslessly holds every observed value (int+floatDOUBLE; a scalar alongside a list → a LIST; maps with a consistent key set → a STRUCT). Anything that doesn't reduce to a single engine type is stored as a JSON column — nothing is dropped, and producer intent is never guessed (strings are never split or parsed). The reserved tags field is always a LIST. Run readb schema to see the inferred type of every column.

Development

uv sync              # install deps + dev tools
uv run pytest        # run tests
uv run ruff check    # lint
uv run ruff format   # format

License

Apache 2.0 © 2026 Stanislav Lukyanov

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

readb-0.1.0.tar.gz (109.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

readb-0.1.0-py3-none-any.whl (32.2 kB view details)

Uploaded Python 3

File details

Details for the file readb-0.1.0.tar.gz.

File metadata

  • Download URL: readb-0.1.0.tar.gz
  • Upload date:
  • Size: 109.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for readb-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6e47b84fc6ffb6f351863ec95b7e23f41d53a97886dca79073ce50176d11ba03
MD5 8c318a46b259d398ecbabb7123bf05a0
BLAKE2b-256 869ba272cb1cf47655e04aeecf697eb9c69cd9c5c24750c72c191afb7a9d1e8b

See more details on using hashes here.

File details

Details for the file readb-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: readb-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 32.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for readb-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c888faac67db7369c8c8a59879434ab1e09141640b71f2442fbefcf9939d9d52
MD5 a528ced97a22dd1db4629df00853815c
BLAKE2b-256 3b9f2eba3ba118ee6b4dccbd6759e8f8319cb03414b3f41aebdbb7fed9895e7c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page