Skip to main content

File-native model and experiment registry

Project description

Koobi project icon

Koobi

File-native model and experiment registry for local workflows.

Koobi stores experiment metadata as plain Markdown cards, builds a disposable DuckDB index, and serves an interactive Marimo UI for browsing, filtering, visualizing, and editing cards. The source of truth is always your files.

Why Koobi

Most experiment trackers assume a hosted service and database-backed runs. Koobi is designed for local-first users who want:

  • readable, versionable records in Git
  • zero-server operation
  • domain-agnostic metrics and parameters
  • workflows friendly to both humans and coding agents

Current MVP Capabilities

  • Markdown card parsing and serialization with preserved body/key ordering
  • additive card updates (only targeted fields are rewritten)
  • DuckDB index build with:
    • cards table (metadata + body)
    • measures table (long-format metrics)
    • series_registry table (series pointers)
  • Marimo app with:
    • project/status/search filters
    • model table view
    • card detail view (metrics/params/tags/body)
    • edit form (name/status/tags/body) with write-back
    • one measure bar chart
  • Execution model (Mode B) — optionally let Koobi run an experiment instead of just recording it:
    • one function registry with component / series / measure kinds; functions live in your package and self-register on import (never embedded in cards)
    • components declared as cards (a model, a framework) backed by registered functions, composed into a typed-port dataflow
    • koobi run <experiment> resolves the components, runs them in dependency order, computes the declared measures, persists a result series, and stamps provenance — writing the same card a human would have authored by hand
    • opt-in input-hash caching (off by default, so research runs always re-execute)
    • a finance pack providing Sharpe / Calmar / max-drawdown measures
  • CLI commands:
    • koobi init
    • koobi new
    • koobi index
    • koobi run
    • koobi ui

Architecture Overview

cards/*.md  -->  index.duckdb  -->  Marimo app
   ^                                  |
   |---------- edit/write-back -------|
  • Cards are authoritative.
  • Index is derived and disposable.
  • UI reads from index and writes edits back to cards.

Koobi works two ways over one data model: you can record results yourself (Mode A), or declare runnable components and let koobi run produce the card (Mode B). Either way the card is the contract; execution is just an optional producer of it. The engine stays domain-free — it wires named ports and runs functions; finance knowledge (the Sharpe formula, date slicing) lives only in packs and your own project code.

experiment card  -->  resolve components  -->  run in dependency order  -->  measures + series  -->  write card back  -->  reindex
   (model + framework, by typed ports)                                          (provenance stamped)

Installation

Install into any project or environment directly from Git:

pip install git+https://github.com/blu3c0ral/koobi.git

This installs the koobi command and the importable koobi package.

For local development on Koobi itself, install editable with dev extras:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"

Quickstart

Koobi discovers its configuration automatically: every command searches the current directory and its parents for a koobi.toml. Work from inside your workspace and no --config flag is needed.

1) Create (or enter) a workspace

koobi init --path my-registry
cd my-registry

Or use the bundled demo workspace:

python examples/local_example_to_cards.py --overwrite
cd examples/local

2) Build the index

koobi index

3) Launch the UI

koobi ui

The UI opens at http://localhost:2718.

Running from outside the workspace

If you prefer not to cd, point Koobi at the config explicitly or via an environment variable (precedence: --config > KOOBI_CONFIG > current dir):

koobi ui --config examples/local/koobi.toml
# or
export KOOBI_CONFIG=examples/local/koobi.toml
koobi ui

CLI Reference

Initialize a new workspace:

koobi init --path /path/to/workspace

Create a new card (run from inside the workspace):

koobi new demo_project.my_model

Rebuild index:

koobi index

Run an experiment (Mode B):

koobi run my_project.exp_001          # --force to ignore the cache

Run UI:

koobi ui

Running Experiments (Mode B)

An experiment is a composition of components — e.g. a model and an entry/exit framework. You declare each as a card backed by a registered function, then declare an experiment card that wires them together; koobi run executes the graph and fills in the results.

Point config at your function module and any datasets (a name → loader binding — the engine only sees the name; your loader gives it meaning):

# koobi.toml
[koobi]
function_modules = ["my_project.koobi_functions"]   # imported to register runners/measures
cache = false                                        # opt-in; default off

[datasets.prices]
loader = "my_project.koobi_functions:load_prices"
params = { universe = "16etf" }

[display]
packs = ["finance"]                                  # Sharpe / Calmar / max-drawdown

Register the functions in your own package (never code in cards):

# my_project/koobi_functions.py
from koobi import registry

@registry.component("my_project.model", produces="predictions")
def run_model(ctx):
    return predict(ctx.artifact("model"), ctx.data("prices"))   # resources pulled in

@registry.component("my_project.framework", needs=["predictions"], produces="equity_curve")
def run_framework(ctx):
    return backtest(ctx.get("predictions"), ctx.data("prices"), **ctx.params)

Declare the cards. needs/produces list ports only (the node-to-node dataflow); external inputs like prices are pulled via ctx.data, not wired as ports:

# model card — produces a "predictions" port
id: my_project.model
type: model
runner: my_project.model
produces: predictions
# framework card — consumes "predictions", produces "equity_curve"
id: my_project.framework
type: framework
runner: my_project.framework
needs: [predictions]
produces: equity_curve
# experiment card — composes the two by role and pins params
id: my_project.exp_001
type: experiment
components:
  model: my_project.model
  framework: my_project.framework
params: { entry_threshold: 0.025 }
measures: [sharpe, calmar, max_drawdown]

Then koobi run my_project.exp_001 writes metrics, a result series, and a provenance block back into the experiment card. See docs/technical_design.md §16 for the full model.

Use as a Library

Koobi's core is importable, so other projects and coding agents can read, query, and write cards programmatically:

from koobi import load_config, build, connect, query_cards
from koobi import Card, load_card, save_card

# Resolve config by searching upward from a path (file or directory)
cfg = load_config("path/to/workspace")

# Build the disposable DuckDB index from the Markdown cards
build(cfg)

# Query cards joined with wide-format measures
con = connect(cfg)
df = query_cards(con, project="demo_project", status="candidate")

# Read, mutate, and write back a single card (only targeted fields change)
card = load_card("path/to/workspace/cards/demo_project.my_model.md")
card.status = "promoted"
save_card(card, fields=["status"])

The execution engine is importable too:

from koobi import load_config, bootstrap, resolve_card, run_experiment

cfg = load_config("path/to/workspace")
bootstrap(cfg)                                   # load packs + import function_modules
exp = resolve_card(cfg, "my_project.exp_001")
run_experiment(exp, cfg, ran_at="2026-06-26T00:00:00")   # writes results back to the card

The full public API is exported from the top-level koobi package; see koobi.__all__.

Repository Layout

src/koobi/                  # core package (schema, cards, config, index, charts, app, cli)
src/koobi/engine.py         # execution engine (run_experiment, Context, toposort)
src/koobi/registry.py       # component/series/measure function registry + bootstrap
src/koobi/packs/            # domain packs (finance: Sharpe/Calmar/max-drawdown)
tests/                      # unit tests
examples/local/             # self-contained demo workspace
examples/local_example_to_cards.py
docs/                       # product, technical, and future feature docs

Development

Run tests:

pytest

Recommended pre-PR checklist:

  • run pytest
  • regenerate local example cards if example inputs changed
  • verify koobi index and koobi ui against examples/local/koobi.toml

Documentation

Status

Phase 0 (the file-native registry) is built, reviewed, and stable. The §16 B1 execution slice — koobi run composing a model + framework experiment — is now implemented and tested. Next: card types (framework/strategy) as first-class declared types, then parameter sweeps and the measure-vs-parameter dashboards. See docs/status.md.

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

koobi-0.0.3.tar.gz (46.2 kB view details)

Uploaded Source

Built Distribution

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

koobi-0.0.3-py3-none-any.whl (33.3 kB view details)

Uploaded Python 3

File details

Details for the file koobi-0.0.3.tar.gz.

File metadata

  • Download URL: koobi-0.0.3.tar.gz
  • Upload date:
  • Size: 46.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for koobi-0.0.3.tar.gz
Algorithm Hash digest
SHA256 64d9c6dc1d4e45768dc3e3150a2e1e88c0cdebb48d7188311ff80645340a0743
MD5 07902e9e6f7141d806558998828cb132
BLAKE2b-256 308e8e692782368dfa9ba940ad257f643c0d3525eeac22aff415a19e31e18d2c

See more details on using hashes here.

File details

Details for the file koobi-0.0.3-py3-none-any.whl.

File metadata

  • Download URL: koobi-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 33.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for koobi-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 02bc29e54740c39fb535e17917d834c2eb4b643eac567109f244f58975e28c85
MD5 3c6cbdda6675fa3aa8c35c33ec9b929f
BLAKE2b-256 63d7da530fe9c1652f9f6f9b62eac95cb17a900bbc886158f1251f514fd9ff3c

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