Persistent memory for data exploration

Help your agent learn the data.

qdo is a deterministic CLI for discovering un-modeled data, recording what an investigation learns, and feeding that knowledge into every investigation that follows—for you, your team, and your coding agent.

The product is the loop

Each investigation should make the next one better.

The commands look familiar. Their combined effect is not: a fact discovered today becomes context, a quality rule, and a portable team artifact tomorrow.

Discover

Find the real shape

catalog finds tables. context returns schema, useful statistics, sample values, and existing knowledge in one call.

Capture

Record one fact

values --write-metadata can turn the observed values of a status column into provenance-tracked YAML.

Reuse

Make facts active

Later context calls surface the values automatically. quality treats inferred values as observations until a human approves them as a constraint.

Hand off

Move understanding

report table creates human-readable HTML. bundle export carries metadata and column sets to another project.

Why another data tool?

Schema is necessary. It is not enough.

Imagine asking an agent for monthly revenue. A sample shows four order statuses, so the agent excludes cancelled. The query is valid, plausible—and silently includes rare test orders that the sample missed.

Without accumulated context

A reasonable guess becomes a wrong report

  • The sample omits a rare but meaningful value.
  • The agent guesses what unit_price represents.
  • The query runs successfully, so the mistake is easy to miss.
With qdo metadata

Prior learning changes the next answer

  • valid_values includes test, even when a row sample does not.
  • A description says unit_price is the purchase-time price.
  • The agent can assert that excluded rows exist before publishing the result.

This is the mechanism qdo is built to provide, not a claim that the benchmark is already won. The project plan explicitly calls for a comparative hallucination benchmark before claiming qdo outperforms prose notes.

Start small: one table, one fact

Ignore most features for the first few sessions.

The goal is not to learn qdo. The goal is to feel the compounding loop once. Use a SQLite file, focus on one useful table, and record one string column with 1–19 distinct values.

1

Discover

Find a table connected to a real question.

2

Understand

Read one combined context response before writing SQL.

3

Capture

Choose one enum-like column such as status, region, or type.

4

Read it back

Run quality and context again. Notice that the file is now part of the tool's behavior.

5

Answer

Only now write the query that motivated the exploration.

From a source checkout (0.2.0 is prepared but not yet on PyPI)

git clone https://github.com/curtisalexander/querido.git ~/src/querido
uv tool install ~/src/querido
cd /path/to/your/data-project

# Substitute your database, table, column, and question
qdo catalog -c ./data.db
qdo context -c ./data.db -t orders
qdo values -c ./data.db -t orders -C status --write-metadata
qdo quality -c ./data.db -t orders
qdo context -c ./data.db -t orders
qdo query -c ./data.db --sql \
  "select status, count(*) from orders group by status"

The durable fact is ordinary YAML

columns:
  - name: status
    valid_values:
      value: [cancelled, delivered, pending, shipped]
      source: values
      confidence: 0.8
      written_at: 2026-07-25T12:00:00+00:00
      author: your-name

qdo writes under .qdo/metadata/. Automated writes keep provenance, do not replace human-authored fields by default, and can be reviewed or reversed with qdo metadata undo. If the command writes zero fields, choose a smaller string enum: qdo deliberately does not infer an allowed set from truncated, non-string, or 20+-value results.

Working with a coding agent

Give the agent a workflow, not a feature catalog.

Humans and agents use the same CLI. JSON output makes results parseable; deterministic next_steps provide a map; plain files make every captured fact reviewable in Git.

01 · ORIENT

Install the project instructions

Run qdo agent install skill in the project where the agent works. The provider-neutral skill teaches the preferred routes and output contract.

02 · CONSTRAIN

Name the question and the boundary

Ask the agent to investigate one table or business question, use qdo before inventing identifiers, and avoid metadata writes until it has evidence.

03 · INSPECT

Start with context

For agents, add -f json. The response separates command-specific data from provenance and suggested next actions.

04 · CONFIRM

Record only verified learning

Let deterministic scans write machine-derived facts. Ask before adding business descriptions, ownership, PII labels, or interpretive notes.

05 · TEST

Turn assumptions into checks

Use assert for the assumptions behind an answer and quality for constraints that should remain true.

06 · HAND OFF

Leave the project warmer

Review the YAML diff, create a report for people, or export a bundle so another project can begin with the same knowledge.

A useful first prompt

Use qdo to investigate the orders table before writing SQL.
Start with structured context, follow only next steps that answer the question,
and verify every table, column, join, and filter value rather than guessing.
Do not write business metadata without asking me. If you discover a deterministic
fact worth preserving, propose the metadata change and show me the diff.
Finish with the answer, the assumptions you checked, and what the next session
will inherit.

The external API

The CLI and file formats are the contract.

qdo is CLI-first. It ships type annotations for contributors, but querido.core, querido.connectors, and querido.output are internal modules—not a supported Python embedding API.

Successful scans

Command-specific data stays inside a stable agent-facing envelope. Results go to stdout; progress goes to stderr.

{
  "command": "context",
  "data": { "table": "orders", "columns": [] },
  "next_steps": [
    { "cmd": "qdo values ...", "why": "..." }
  ],
  "meta": {
    "connection": "./data.db",
    "table": "orders",
    "generated_at": "...",
    "qdo_version": "0.2.0"
  }
}

Structured failures

Failures use a distinct object. Documented or contract-tested codes and try_next records receive compatibility treatment; message wording does not.

{
  "error": true,
  "code": "TABLE_NOT_FOUND",
  "message": "...",
  "try_next": [
    { "cmd": "qdo catalog ...", "why": "..." }
  ]
}
MetadataRemember factsVersioned YAML under .qdo/metadata/; merged into later scans and quality checks.
Sessions · experimentalRecord investigationsOpt-in append-only JSONL plus captured stdout under .qdo/sessions/; useful for review, replay, and SQL reuse.
BundlesShare knowledgeDirectories or ZIP archives containing metadata and optional column sets—never data, sessions, or workflows.
WorkflowsRepeat proceduresStrict YAML that orchestrates public qdo commands as subprocesses. Experimental until real projects stabilize the contract.
ConfigName connectionsVersioned TOML in the platform config directory; SQLite files can be used directly without setup.

Where functionality lives

A composition layer over deterministic operations.

The source tree follows the journey from argv to a database engine and back to a human or machine result. The boundaries matter more than the number of commands.

cli/

Typer commands, option resolution, friendly errors, connector lifecycles, progress, and output selection. This is the application composition boundary.

core/

Backend-neutral operations and product policy: context, quality, query safety, metadata rules, sessions, bundles, and experimental workflows.

connectors/

The context-managed connector protocol plus SQLite, DuckDB, and Snowflake adapters. Driver errors are translated at this boundary.

sql/

Jinja rendering and dialect-specific .sql templates. Identifiers are validated before interpolation; values use driver parameters.

output/

The JSON envelope and human renderers for rich terminal output, CSV, YAML, Markdown, HTML, and single-file reports.

integrations/

The provider-neutral coding-agent skill and workflow guidance, packaged into the wheel so agents can learn qdo outside this repository.

config.py / cache.py

Versioned connection, column-set, and local-cache persistence. This infrastructure does not own exploration policy or presentation.

Supported outside the package

Stable core command names and documented options; JSON success envelopes; documented or contract-tested error codes and recovery records; versioned metadata, config, and bundle formats; querido.__version__. Experimental session and workflow contracts have no compatibility promise.

Free to evolve internally

Importable core functions, connector implementations, renderer registries, module names, and signatures. If embedding demand appears, the intended answer is a small explicit querido.api facade.

Reveal more only when needed

Choose the next feature by the gap in your understanding.

After the one-table loop feels natural, expand by outcome. Workflows and the TUI can wait.

Need exact filter values?

Enumerate a low-cardinality column instead of relying on a sample.

qdo values

Need data health?

Check stored constraints and inspect null, cardinality, and shape signals.

qdo quality

Need deeper statistics?

Profile only when context leaves a specific numerical question unanswered.

qdo profile

Need a join path?

Discover likely keys, then validate their cardinality before trusting the join.

qdo joins

Need a human hand-off?

Create a single-file HTML summary of a table or recorded session.

qdo report table

Need a team hand-off?

Export portable metadata and column sets; inspect or diff before importing.

qdo bundle export

Need to test session recording?

Explicitly opt into the unstable CLI trail and its structured results.

QDO_EXPERIMENTAL=1 QDO_SESSION=name

Testing repeated procedures?

Explicitly opt into the unstable declarative workflow surface.

QDO_EXPERIMENTAL=1 qdo workflow run NAME

Need backend depth?

Add DuckDB/Parquet, Snowflake, or the Textual TUI without burdening the base install.

querido[duckdb] · querido[snowflake] · querido[tui]

Trust boundaries and sharp edges

Opinionated by design.

These constraints keep qdo understandable, deterministic, and cheap to adopt—but contributors and agents should know where the edges are.

What qdo protects

  • Core database access is read-only by default.
  • Identifiers are validated at both CLI and SQL-construction boundaries.
  • Automated metadata writes retain source, confidence, author, and timestamp.
  • Human-authored metadata is not automatically overwritten.
  • Optional backends and the TUI load only when used.

What to keep in mind

  • Names requiring SQL quoting—spaces, hyphens, dollar signs, or Unicode—are intentionally unsupported; alias them in a view.
  • The machine success envelope and structured error object are different contracts.
  • Bundles transfer knowledge, not rows or database backups.
  • Sessions and workflows require QDO_EXPERIMENTAL=1 and carry no compatibility promise.
  • The comparative “qdo beats notes” benchmark is planned, not completed.
qdo explore showing an orders table and selected-column context in a side panel
An optional interactive view of the same model: data beside accumulated column context. Open the generated orders hand-off report for the core shareable artifact.

A good first milestone

Make one future session measurably less ignorant.

Pick one table. Capture one verified fact. Read it back. Use it in an answer. Then decide whether the next useful move is deeper analysis, a check, a report, or a bundle—not another tour of features.