Skip to main content

gracefall

Fallback-first graphics for terminals. One byte stream, two renderings.

Every chart gracefall emits is wrapped in an OSC 4700 envelope carrying the underlying data, with generated unicode fallback text as the envelope's visible body. Terminals that don't know the protocol silently swallow the envelope and show the fallback, which is already a real visualization. A terminal that implements OSC 4700 re-renders the same cells as smooth, theme-aware vector graphics.

the same bytes in a plain terminal and in an implementing terminal

The left panel is what gracefall demo shows in every terminal on earth today, including macOS Terminal.app over SSH inside tmux. The right panel is the same bytes in a terminal that implements the protocol. Nothing else in the terminal ecosystem has this property: sixel prints garbage on a miss, kitty graphics needs a query round trip, and both lose selection, grep, scrollback, and screen readers. Here the fallback IS the text, so all of that keeps working by construction.

gracefall running in a terminal with no graphics support

That recording is a plain xterm-256color, so every chart in it is the fallback text. The envelopes are being emitted the whole time and the terminal is silently swallowing them, which is the entire design: emitting is safe blind.

Install

uv tool install gracefall     # or: pipx install gracefall

Zero dependencies, pure stdlib Python 3.9+. gfl is installed as a short alias for gracefall.

Use

seq 1 20 | gracefall spark
gracefall meter 62% -c amber
gracefall flow build:done test:done canary:active prod:pending
gracefall dist --bins 20 < latencies.txt
paste xs.txt ys.txt | gracefall scatter
gracefall demo

Pipe-safety is automatic: envelopes are emitted only when stdout is a tty, so gracefall spark ... | less and shell captures get pure fallback. Use --force-osc to save a stream and --no-osc to strip unconditionally.

gracefall demo --force-osc > examples/inference.gfall
cat examples/inference.gfall        # safe in any terminal, try it
grep "kv cache" examples/inference.gfall
gracefall render examples/inference.gfall -o enhanced.svg
gracefall render examples/inference.gfall --plain -o plain.svg

render is the reference renderer: executable semantics for terminal authors, and the thing CI uses to verify the emitter.

Seeing the smooth rendering today

No terminal implements OSC 4700 yet, so gfl view stands in for one. It works out where each span's cells landed, rasterizes the span, and places the image over exactly those cells using the kitty graphics protocol, which Ghostty, kitty, and WezTerm already speak:

uv tool install "gracefall[view]"     # or: pipx install "gracefall[view]"
gracefall demo --force-osc | gfl view

gfl view --watch 'some command' re-runs the command on an interval and repaints in place, and gracefall render file.gfall --png composes the same picture to a PNG without needing a terminal at all, which is how the image above is generated.

In a terminal without graphics support the same command prints the fallback text unchanged and one line on stderr saying why. Inside tmux it does the same, because tmux drops the graphics sequences unless you run tmux set -g allow-passthrough on. The geometry comes from the same module the SVG renderer uses, so the shim cannot drift from the reference rendering. Notes on how it works, and its limits under tmux and scrollback, are in docs/view-notes.md.

As a library:

from gracefall import spark, meter, flow
print("p99  " + spark([92, 88, 84, 90, 97, 84], color="blue") + "  84ms")

The protocol in 30 seconds

ESC ] 4700 ; t=spark ; d=1,4,2,8 ; c=blue ST  ▁▄▂█  ESC ] 4700 ; ST

Open envelope with data, visible fallback, empty envelope to close. The span's cells are wherever the fallback lands, so there is no size negotiation and no capability query. Payloads are data, never pixels and never drawing commands, so the terminal owns rendering and can adapt it to theme, font size, and DPI. Full details, including the four design laws and the prior-art delta, are in SPEC.md.

Status

  • Emitter and CLI: working, v0.1
  • Reference renderer: working (SVG and PNG out)
  • gfl view, the kitty-graphics shim: working, verified in Ghostty and kitty
  • Terminals implementing OSC 4700 natively: none yet, and that is the honest state of a young protocol

If you maintain a terminal and want the first implementation, the renderer module is ~300 lines of executable semantics and the type set is six declarative primitives. Open an issue; the meter type alone is an afternoon.

Shell integration

shell/gracefall.zsh provides completions. Any zsh plugin manager can load it straight from this repo once published:

zinit light PouyanJay/gracefall

Changelog

CHANGELOG.md.

License

Code MIT. The specification text in SPEC.md is CC0 so implementations can copy it freely.

Metadata

Release files for gracefall 0.2.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 gracefall 0.2.0
File Size Uploaded
gracefall-0.2.0.tar.gz 651.0 kB Details

Built distribution (wheel)

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

Total release size: 683.1 kB

Release files / gracefall-0.2.0.tar.gz

Download URL gracefall-0.2.0.tar.gz
Size 651.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e324ef95df88e2fcfebf9b3a19b5d9e6cfaac7f9a6cde8ee60d75b64a87cef9d
BLAKE2b-256 checksum
How to use checksums
281e3bcf3209680545b3cedb4fd9f433e666ce54b9fa103fcd0b4a9c182a9c49
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / gracefall-0.2.0-py3-none-any.whl

Download URL gracefall-0.2.0-py3-none-any.whl
Size 32.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ec00bf733f6d21112c77520381e501663318ea4fa433252fffb739c161ff078d
BLAKE2b-256 checksum
How to use checksums
1e828fe0d6e64741ed39f51164af23b14f90eb2322af2911c0463916b4c17b62
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

0.4.0

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

This release

0.2.0 This release

2 release files

0.1.1

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