vccs
Composable charting components for Vue 3, ported from Recharts
A content-addressed computation graph with an interactive notebook UI
Translation pending
DataPython · VueGitHub @bearing-researchOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
A content-addressed computation graph with a notebook UI
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Strata is a content-addressed computation graph with an interactive notebook UI.
Every cell output is a versioned artifact keyed by its provenance: source,
inputs, and environment. Strata reads each cell's AST to build the
dependency graph automatically, so re-running a notebook is mostly a series
of cache hits. Touch one cell and the cascade re-executes only the cells
that depend on it. Identical inputs produce the same artifact whether the
second run comes a minute later or a year later, on the same machine or a
different one.Read the full README ↗Strata is a notebook your coding agent can drive, and everything it computes stays.
Coding agents explore by writing throwaway scripts: python -c, files in
/tmp, invisible and gone by the next session. Point one at Strata and the
work lands in a notebook instead. Every result is cached by what produced it,
every cell records who wrote it, and the whole thing is open in your browser
while the agent works. Come back tomorrow and it is all still there, already
computed.
That holds because of what a cell is. Each one is keyed by its source, its inputs and its environment, so the expensive step an agent ran ten turns ago is a cache hit now, and the same inputs give the same result a year later on another machine. Change one cell and only the cells below it run again. Nothing is recomputed to prove a point.
It is a good notebook for a person, too. Ask a model a question in a prompt
cell and the answer is cached like any other result. Send the slow cell to a
GPU with one line. Read an S3 prefix as a local path. The notebook itself is
plain .py files plus a manifest, so a commit is a readable diff rather than
a wall of JSON.
Docs: bearing-research.github.io/strata
Install it as a one-command Claude Code plugin
(needs the strata CLI on PATH; uv tool install "strata-notebook[mcp,tui]"):
/plugin marketplace add bearing-research/strata
/plugin install strata-scratchpad@strata
A coding agent drives the notebook through the strata CLI; the browser on
the same session updates as it goes. Captured from a real run, not a mock-up.
Whether an agent reaches for it instead of a scratch script is measured rather
than assumed. evals/agent_notebook/ drives the real on-ramp and grades the
result: 9 transcript-backed tasks run in CI, and a scratchpad group probes
whether an un-primed session uses the notebook at all. See
Driving a notebook with a coding agent.
For an agent
/tmp script, so the snippet it ran ten turns ago is still there/mcp, and you can watch the agent work in the browser or the terminal while it doesstrata inspects, runs and authors a notebook with JSON output and stable exit codes, offline or against a live sessionstrata agent ./nb stands up the server, the session, the config and the viewer togetherWhy nothing runs twice
.py files plus a TOML manifest, so a diff shows the code that changedCell types
{{ variable }} interpolation from upstream, cached by template + inputs + model configpandas.DataFrame is a data.frame for the next cell# @loop max_iter=N carry=state iterates with an explicit carry, each step its own artifact{name: value} dict, or fan out with # @per_variant so adding a variant only runs the new oneCompute and data
# @worker gpu-fly dispatches a cell to a remote box; bring your own computepip install strata-pool): machines (Fly, Docker or RunPod) start on demand, are held for a tenant, hand out GPUs per cell, and stop when the work doesstrata-worker --connect dials out to a relay, so a machine with no open port serves cells# @fetch makes bytes from a URL an input, # @dataset makes a registry name one, both content-addressed# @output_dir ckpt gives a cell a folder whose files are stored as an output, kept even when the run fails, and handed to the next cell as a Path# @write_table readings lake:lab.readings append writes a variable into an Iceberg table when the run succeeds, and each snapshot names the result that made it# @mount data s3://bucket/prefix ro makes any S3, GCS or Azure prefix a local pathlib.PathTeams
strata artifact promote copies a result and the chain behind it into the team's store, from the notebook, the CLI or inside a cellPUT without closing a sessionSurfaces
strata watch renders a running notebook live in the terminal, read-only, over SSH or beside your editorstrata cell cancel, REST or MCP, and on Linux and macOS a cell stops when the server that started it does<iframe>, or export a self-contained snapshotpip install strata-client talks to the store from any pipeline or service, with no server installBoth paths below run in personal mode: single-user, writes enabled, no proxy auth. For multi-tenant or hosted deployments, see Deployment Modes.
# Docker. docker-compose.yml sets personal mode for you.
docker compose up -d --build
# Then open http://localhost:8765
# Or the prebuilt image (linux/amd64), published with each release.
docker run --rm -p 127.0.0.1:8765:8765 -v strata_state:/home/strata/.strata \
ghcr.io/bearing-research/strata:0.11.0
# Or install via uv (recommended). Puts the CLI on PATH in a uv-managed
# tool env. `pip install` is not supported; see Requirements below.
# The mcp and tui extras are what `strata agent` and `strata watch` need.
uv tool install "strata-notebook[mcp,tui]"
strata-notebook
# Then open http://localhost:8765
For the full inventory of installed commands (strata-notebook, strata,
strata-notebook-tui, strata-worker, python -m strata), see the
Commands reference.
Source builds (git clone + uv sync) are documented in
Installation.
uv 0.8 or newer, and nothing else. uv fetches a matching Python for you.
Strata runs only inside a uv-managed environment. It checks for the
uv = <version> marker uv writes to pyvenv.cfg, which uv tool install,
uv add and uv run all produce and a hand-rolled python -m venv does not.
The reason is that the notebook subsystem shells out to uv to manage
per-notebook .venv/ directories; failing at startup with a clear message
beats a confusing subprocess error later. Conda and pip-venv users install uv
and run uv tool install strata-notebook, which builds its own env and leaves
existing data and environments untouched.
Windows: uv tool install strata-notebook works directly.
Building Strata itself from a git clone also needs Node 26+ for the frontend. The PyPI wheel ships it prebuilt, so this applies only if you are modifying Strata. Source builds work on Windows via WSL2 or natively.
Most notebooks either re-run everything or cache only what you opt in to. Strata caches every cell by default. The artifact store deduplicates by provenance hash. If the code and inputs haven't changed, the result is served instantly.
First run: load data (10s) → clean (3s) → train (20s) → evaluate (1s) = 34s
Change model: load data (✓) → clean (✓) → train (20s) → evaluate (1s) = 21s
Re-run: load data (✓) → clean (✓) → train (✓) → evaluate (✓) = <1s
This is the architecture, not a layer on top of it. Every cell execution is a
materialize(inputs, transform, environment) → artifact operation, and the
cache is keyed on content rather than time, so it is correct by construction.
Even a leaf cell that only prints is cached: its console output is keyed
by the same provenance hash, so an unchanged re-run replays the output
instantly rather than executing again. That makes the notebook a good
scratchpad - a coding agent's exploratory snippets stop recomputing.
Cells that must always run (a side effect, a live API call, a fresh random
draw) opt out with # @nocache.
Each cell can declare which worker it runs on via a single annotation:
# @worker my-gpu
embeddings = model.encode(abstracts, batch_size=256)
You define workers in notebook.toml. Each one points at an HTTP
endpoint that implements the Strata executor protocol. A worker can be
a GPU box on RunPod, a DataFusion cluster on Fly, a beefy EC2 instance,
or anything else that speaks HTTP. The notebook routes the cell to the
declared worker at execution time, and the UI shows a live
dispatching → my-gpu badge while it runs.
No deployment code, no infrastructure glue. Bring your own compute, one annotation per cell.
Every piece of per-cell metadata is a comment directive in the cell's source. The source is the single canonical place for cell config: annotations always win over any stored defaults.
# @name Extract embeddings
# @worker gpu-fly
# @timeout 600
# @env MODEL_PATH=/models/bge-large
# @mount dataset s3://corpus/2024-q4 ro
embeddings = model.encode(dataset / "abstracts.jsonl")
Diagnostics fire on open, reload, and after an edit settles, for example
worker_unknown, mount_uri_unsupported, mount_shadows_notebook,
timeout_not_numeric, env_malformed. They surface as a pill in the
cell header and log structured warnings for headless runs.
Mounts bind a remote URI to a local path inside the cell. Supported
schemes: file://, s3://, gs://, az://. Credentials flow through
fsspec options: set anon = true for public buckets, or drop it to
use the standard credential chain.
[[mounts]]
name = "taxi_zones"
uri = "s3://nyc-tlc/misc"
mode = "ro"
options = { anon = true }
Inside the cell, taxi_zones is a pathlib.Path. Strata copies the
remote prefix to a local cache before the cell runs, shared by every
notebook on the machine, and when the prefix changes it downloads only the
new or changed files. The copy runs in Strata's own environment, so install the extra for the scheme there: s3, gcs or
azure (for example uv tool install "strata-notebook[s3]").
| Example | What it shows |
|---|---|
| pandas_basics | Linear DataFrame chain, caching, staleness propagation, per-cell unit tests |
| iris_classification | End-to-end ML, DAG branching, mixed output types |
| titanic_ml | Feature engineering + model comparison |
| s3_mount | Reading a public S3 bucket via a mount |
| arxiv_classifier | Distributed execution via @worker + Modal GPU + Fly cluster |
| markdown_showcase | Markdown cells, dynamic Markdown(...) outputs, security cases |
| library_cells | Cross-cell library code: pure module cells, mixed runtime+library cells, the limits |
| news_alpha_trader | Multi-stage trading pipeline with prompt cells and structured LLM outputs |
| review_triage | Prompt cell with # @output_schema - structured, schema-validated LLM output |
| r_mtcars_analysis |
Materialization, the artifact store, the DAG, caching and headless run are settled and covered by tests. Three surfaces are not:
notebook.toml, .strata/runtime.json and the artifact
cache layout may change between minor versions. Depend on the Python API,
not the file shapes.Strata's HTTP API exposes the materialization layer directly,
driveable from Python via StrataClient. Useful for direct table
scans, custom transforms, and headless workflows; the notebook
executor is a separate pipeline that writes to the same artifact
store. The client talks to a running Strata server, so this workflow
has two steps: start the server, then call it from your code.
# 1. Install + start the server (in a uv-managed env).
uv tool install strata-notebook
strata-notebook
# 2. In your own project, install the slim client - a separate package
# (httpx + pyarrow only, no server deps, plain pip is fine) - and
# point it at the running server:
pip install strata-client
from strata_client import StrataClient
client = StrataClient(base_url="http://localhost:8765")
artifact = client.materialize(
inputs=["file:///warehouse#db.events"],
transform={"executor": "scan@v1", "params": {"columns": ["id", "value"]}},
)
table = client.fetch(artifact.uri) # Arrow table, cached by provenance
A result never goes stale, but an unnamed one is a cache entry: the server
keeps it while it is used, and its retention sweep (in personal mode, 30 idle
days or a 20 GiB store cap) may collect it later, after which the same call
computes it again. Name it (name= on materialize) or pin it to keep it. See
retention.
The server provides: provenance-based deduplication, immutable versioned artifacts, lineage tracking, Iceberg table scanning with row-group caching, pluggable blob storage (local/S3/GCS/Azure), multi-tenancy, trusted-proxy auth, and an executor protocol for external compute.
┌─────────────────────────────────────────────┐
│ Notebook UI (Vue.js + WebSocket) │
│ cells, DAG view, workers │
└─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Notebook Backend (FastAPI) │
│ session, cascade, executor, prompt cells │
└─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Strata Core │
│ materialize, artifacts, lineage, dedupe │
└─────────────────────────────────────────────┘
The notebook is an orchestration layer over Core. It decides what to run next (cascade planning, staleness tracking). The cell harness is an executor. Core decides whether results already exist and persists them.
uv sync --all-extras # Install deps (matches CI)
uv run pytest # Run all tests
uv run pre-commit run --all-files # Lint + format
cd frontend && npm run dev # Frontend dev server (hot reload)
Apache 2.0
.venv/, locked and reproduciblestrata run ./my-notebook for CI and scheduled execution, same DAG and same cachePure-R notebook - mtcars regression with inline ggplot2 / base-graphics plots |
| r_lm_vs_sklearn | Cross-language R + Python - R lm() vs scikit-learn over shared Arrow data |
| sql_orders_report | SQL cells over a local SQLite warehouse, mixing SQL / Python / markdown |
| widget_playground | Widget cell (control panel) driving a downstream cell, with # @live reactivity |
| model_variants | Variant groups - alternative training cells sharing one DAG slot (switch mode) |
| model_variants_sweep | Variant sweep mode - run every variant and compare them in one downstream cell |
| loop_hill_climb | # @loop / # @loop_until iteration with carry and per-iteration artifacts |
| data_viewer | Interactive data viewer - page / sort / filter / search the full cached artifact |
| agent_demo | A coding agent builds the notebook live; only the eval re-runs when the model caches |