Skip to main content

fletchr-studio

The flowgraph engine behind the fletchr studio GUI: a graph document model for source → transformer → sink flowgraphs, a block palette built by introspecting the live fletchr registries, graph validation, and Python code generation with round-trip reopen.

The package also ships the studio itself: a FastAPI host (fletchr_studio.server) serving a React Flow canvas UI, with sessions, sampled/full graph runs, and per-node table previews. See docs/design/studio.md at the workspace root for the design record and phased plan.

Running the GUI

fletchr-studio            # serves http://127.0.0.1:8410

Drag blocks from the palette, connect them (incompatible ports are rejected), configure params in the inspector, then Preview Run — sources are sampled and sinks are skipped, so a preview never overwrites real outputs. Click any node to see its table preview. Full Run executes everything, sinks included. Generate shows the emitted script; Save writes it; Open reopens a generated .py (hand edits are flagged as drift).

Rebranding for meta-packages

A downstream protocol wrapper can present the studio as its own tool. Ship a console script that launches it with a Branding:

# acme_decoder/studio.py
import acme_decoder.plugins  # noqa: F401 - registers blocks via entry points
from fletchr_studio import Branding
from fletchr_studio.server import main


def cli() -> None:
    main(branding=Branding(name="ACME Decoder Studio", favicon="path/to/icon.svg"))
[project.scripts]
acme-studio = "acme_decoder.studio:cli"

The name flows into the browser tab, the top bar, and the FastAPI title; the favicon replaces the default. Generated scripts still record fletchr-studio <version> as their generator — that's provenance, not presentation. The wrapper's transformers, readers, and writers appear in the palette automatically via the normal entry-point plugin discovery.

The canvas bundle builds into src/fletchr_studio/static/ and ships in both the wheel and the sdist. Packaging is guarded by hatch-jupyter-builder: building a dist with the bundle already present needs no Node (skip-if-exists); with the bundle missing it runs npm install + npm run build itself; and with neither bundle nor Node the build fails rather than producing a headless dist (ensured-targets). Editable installs only warn, so Python-only contributors without Node get a working headless dev server. Escape hatch for deliberate headless builds: SKIP_JUPYTER_BUILDER=1.

To rebuild the bundle by hand you need Node 18+:

cd frontend
npm install
npm run build     # type-checks and outputs to ../src/fletchr_studio/static
npm run dev       # dev server with /api proxied to a running fletchr-studio

What it does

from fletchr_studio import GraphDoc, generate_code, load_graph

doc = GraphDoc()
doc.add_node("capture", "source", "read_file", path="capture.arrow")
doc.add_node("sel", "transform", "Subframe", columns="1-32")
doc.add_node("inv", "transform", "BitInvert")
doc.add_node("out", "sink", "write_file", path="frames.parquet")
doc.add_edge("capture", "sel")
doc.add_edge("sel", "inv")
doc.add_edge("inv", "out")

code = generate_code(doc)

generate_code validates the graph (unknown blocks, port type mismatches, cycles, missing params — reusing the same subclass-aware compatibility rules Pipeline enforces) and emits a plain Python script depending only on the fletchr packages:

"""Flowgraph generated by fletchr-studio 0.1.0."""

import argparse

from fletchr_core import read_file, write_file
from fletchr_core.transform import BitInvert, Subframe


def main(capture_path='capture.arrow', out_path='frames.parquet'):
    capture = read_file(capture_path)
    inv = (Subframe(columns='1-32') | BitInvert())(capture)
    write_file(out_path, inv)


def _cli():
    parser = argparse.ArgumentParser(description="Flowgraph generated by fletchr-studio.")
    parser.add_argument("--capture", dest="capture_path", default='capture.arrow', help="source 'capture' path")
    parser.add_argument("--out", dest="out_path", default='frames.parquet', help="sink 'out' path")
    main(**vars(parser.parse_args()))


if __name__ == "__main__":
    _cli()


__fletchr_graph__ = {...}

Source and sink paths are lifted into main()'s signature and an argparse CLI, so the artifact is parameterizable without editing: python flow.py --capture other.bits, or import it and call main(capture_path=...) from a loop.

The embedded __fletchr_graph__ literal is the graph document — load_graph("flow.py") reopens it, and a stored SHA-256 of the code section detects hand edits (drift) without parsing arbitrary Python. Linear chains compile to | pipelines; fan-out becomes named intermediates; merge blocks (stack, merge) compile to plain calls.

The palette (build_palette()) discovers every registered transformer — including plugin-contributed ones — plus file source/sink blocks and the merge blocks, with parameter schemas introspected from attrs fields or __init__ signatures and port types from apply annotations.

Metadata

Release files for fletchr-studio 0.6.0

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

Source distribution (sdist)

Source distribution for fletchr-studio 0.6.0
File Size Uploaded
fletchr_studio-0.6.0.tar.gz 218.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fletchr-studio 0.6.0
File Interpreter ABI Platform
fletchr_studio-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 379.8 kB

Release files / fletchr_studio-0.6.0.tar.gz

Download URL fletchr_studio-0.6.0.tar.gz
Size 218.4 kB
Tags Source
SHA-256 checksum
How to use checksums
72e870632e2244e05a92c056a84d02260aecfd80ab038489d80c40b8f7c7a959
BLAKE2b-256 checksum
How to use checksums
bc0db967289699dadf590b25f3fc12c4023e5cb404d1ef5991d8dffac2b6030a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","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 / fletchr_studio-0.6.0-py3-none-any.whl

Download URL fletchr_studio-0.6.0-py3-none-any.whl
Size 161.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a312eaf19c3577aa0948068dbd7255f32f92f338bdee25450303c791df6e1595
BLAKE2b-256 checksum
How to use checksums
3a81a2ffe6c99f8430d216e98ebdf5aee37bfaea2f75f23514cbf2d166ae1332
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","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 history Release notifications | RSS feed

This release

0.6.0 This release

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

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