Skip to main content

Historybook: Storybook-like inspection for Python pipelines

image PyPI - Downloads image image

Storybook for Python. Inspect every pipeline in your project on a single page.

Historybook is a thin Streamlit app that walks your repo, finds all history files, and aggregates them behind a searchable sidebar menu. Each "history" is just a function you decorate — when the user picks it from the menu, Historybook runs the function and renders whatever Streamlit output it produces.

Why

Visual testing for backend pipelines without spinning up an API server and a JS frontend. If you just want to poke at a pipeline — step through stages, swap inputs, see intermediate outputs — a full web stack is overkill. Write a function, decorate it, run historybook.

Good fits:

  • Step-by-step visualisation of multi-stage pipelines (OCR, ETL, ML inference, data cleaning).
  • Inspecting intermediate artefacts (images, DataFrames, JSON) during development.
  • LLM / agent output inspection. Calls are expensive, outputs are open-ended, and assertion-style unit tests don't catch things like "the explanation is technically correct but phrased weirdly." Historybook gives you a quick human-in-the-loop surface: render the prompt, response, tool-calls, token/cost metrics side-by-side and eyeball quality across prompt/model variants.
  • Demoing internal tools to teammates without deploying anything.

Install

pip install historybook          # or: uv add --dev historybook

Historybook is a development tool, so prefer uv add --dev (or pip install into a dev-only env) — there's no reason to ship it as a runtime dependency.

Quick start

1. Add [tool.historybook] to your pyproject.toml:

[tool.historybook]
roots = ["."]                    # directories to scan (relative to pyproject.toml)

[tool.historybook.theme]
primaryColor = "#2563eb"         # optional

2. Write a history file. Any file matching *_histories.py or *.histories.py anywhere under roots is auto-discovered.

# src/myproject/ocr.histories.py
import streamlit as st
from historybook import component, history

@component("OCR Pipeline", tags=["ocr"])
class OcrPipeline:
    @history("Single Page")
    def single_page(self):
        st.image("samples/page1.png")
        st.json({"confidence": 0.97, "lang": "en"})

    @history("Multi Page")
    def multi_page(self):
        for i in range(3):
            st.image(f"samples/page{i}.png")

3. Launch the app from anywhere inside the repo:

historybook

A Streamlit page opens with a sidebar grouped by tag → component → history. Type in the search box to filter; click any history to run it in the main pane.

Discovery rules

  • Historybook walks up from the cwd to find pyproject.toml, then scans each directory listed in [tool.historybook].roots.
  • It rglobs for *_histories.py and *.histories.py.
  • Optional per-project setup lives in .historybook/main.py (like Storybook's .storybook/main.ts). It runs once in the parent process before Streamlit starts — good for setting env vars that Streamlit must inherit.

Pipeline diagram component

Historybook ships with a Mermaid-based pipeline diagram helper with live status updates — useful for visualising DAGs while they execute.

import streamlit as st
from historybook import component, history
from historybook.components import pipeline_diagram

@component("Document Pipeline", tags=["ocr"])
class DocPipeline:
    @history("Linear flow")
    def linear(self):
        diagram = pipeline_diagram(
            steps=["Input", "Rotate", "X-Cut", "Y-Cut", "Output"],
            statuses={"Input": "done", "Rotate": "running"},
        )
        if st.button("Next step"):
            diagram.update({"Input": "done", "Rotate": "done", "X-Cut": "running"})

    @history("DAG with parallel paths")
    def dag(self):
        pipeline_diagram(
            edges=[
                ("Input", "Rotate"),
                ("Rotate", "X-Cut"),
                ("X-Cut", "Y-Cut Page 1"),
                ("X-Cut", "Y-Cut Page 2"),
                ("Y-Cut Page 1", "Grade"),
                ("Y-Cut Page 2", "Grade"),
            ],
            statuses={"Input": "done", "Rotate": "running"},
            icons={"Input": "📄", "Grade": "🎯"},
            direction="LR",      # or "TD"
        )

Statuses: "waiting" (default), "running" (pulsing blue), "done" (green with ✓), "error" (red with ✗). Running edges get an animated dashed stroke. Call diagram.update(new_statuses) to re-render in place.

Excluding history files from other tools

History files are executed by Historybook, not imported by your app — so they're usually noise for linters, type checkers, test runners, and package builds. Suggested pyproject.toml snippets:

# pytest — skip collection (including --doctest-modules)
[tool.pytest.ini_options]
addopts = "--ignore-glob=**/*_histories.py --ignore-glob=**/*.histories.py"

# pyright / basedpyright — skip type checking
[tool.pyright]
ignore = ["**/*_histories.py", "**/*.histories.py"]

# ruff — skip linting
[tool.ruff]
extend-exclude = ["**/*_histories.py", "**/*.histories.py"]

# hatchling — don't ship history files in the wheel/sdist
[tool.hatch.build]
exclude = ["**/*_histories.py", "**/*.histories.py"]

Notes:

  • pytest: --ignore-glob is the canonical escape hatch; for finer control, use collect_ignore_glob in a conftest.py.
  • pyright: prefer ignore over exclude — exclude replaces pyright's default exclude list (node_modules, __pycache__, etc.), ignore adds to it.
  • ruff: extend-exclude preserves ruff's defaults (.git, .venv, …); plain exclude replaces them.
  • hatchling: patterns are gitignore-style. If you set packages/include explicitly, also exclude there.

API reference

from historybook import component, history
  • @component(name: str, *, tags: list[str] | None = None) — class decorator. Registers the class as a component grouped under the given tag(s) in the sidebar.
  • @history(name: str) — method decorator. Marks a method on a @component class as a selectable history. The method takes self only and renders with Streamlit calls.
from historybook.components import pipeline_diagram
  • pipeline_diagram(*, steps=..., edges=..., statuses=..., icons=..., direction="LR", height=150) — Mermaid flowchart. Pass steps (linear) or edges (DAG), not both. Returns a PipelineDiagram with an update(statuses) method.

CLI

historybook                      # run from anywhere inside the repo
historybook --root path/to/dir   # override the scan root

Metadata

Release files for historybook 0.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for historybook 0.0.3
File Size Uploaded Provenance
historybook-0.0.3.tar.gz 15.8 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for historybook 0.0.3
File Interpreter ABI Platform
historybook-0.0.3-py3-none-any.whl Python 3 none any Details

Total release size: 32.2 kB

Release files / historybook-0.0.3.tar.gz

Download URL historybook-0.0.3.tar.gz
Size 15.8 kB
Tags Source
SHA-256 checksum
How to use checksums
be75e48b00e2aeed26bbd7315d9ebe330683e25190b5d58e97ed91bcfe342dc7
BLAKE2b-256 checksum
How to use checksums
c94c67978a5a91fc8d61f8b4f46de3c08d7a68400980fe8d7a06b5c8319a88ab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / historybook-0.0.3-py3-none-any.whl

Download URL historybook-0.0.3-py3-none-any.whl
Size 16.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9c7fc2e009161c599a26543654c138b72004dd1ff8c97ecf64ecfb2551acc58b
BLAKE2b-256 checksum
How to use checksums
0c3f41e74853cd481ebc22ad0a4cae9833f53a20b392ea937003caa1e454c36d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for historybook 0.0.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page