Skip to main content

Render directed graphs as ASCII/Unicode art for console output

Project description

graphtty

PyPI downloads PyPI - Version Python versions

Render directed graphs as ASCII/Unicode art for console output.

Installation

pip install graphtty

Screenshots

React Agent (monokai theme)

React Agent

Deep Agent (ocean theme)

Deep Agent

Workflow Agent (forest theme)

Workflow Agent

Supervisor Agent (dracula theme)

Supervisor Agent

CLI

Render any graph JSON file straight from the terminal:

graphtty graph.json
graphtty graph.json --theme monokai
graphtty graph.json --ascii
graphtty graph.json --no-types

Options

usage: graphtty [-h] [-t THEME] [--ascii] [--no-types] [--list-themes] [file]

positional arguments:
  file                  Path to a graph JSON file

options:
  -h, --help            show this help message and exit
  -t THEME, --theme THEME
                        Color theme (use --list-themes to see options)
  --ascii               Use plain ASCII instead of Unicode box-drawing characters
  --no-types            Hide node type labels
  --list-themes         List available themes and exit

Themes

Ten built-in color themes that style nodes by type:

graphtty graph.json --theme monokai
graphtty graph.json --theme ocean
graphtty graph.json --theme forest
graphtty graph.json --theme dracula
graphtty graph.json --theme solarized
graphtty graph.json --theme nord
graphtty graph.json --theme catppuccin
graphtty graph.json --theme gruvbox
graphtty graph.json --theme tokyo-night
graphtty graph.json                     # default (no color)

List all available themes:

graphtty --list-themes

Python API

Simple linear chain

from graphtty import AsciiGraph, AsciiNode, AsciiEdge, render

graph = AsciiGraph(
    nodes=[
        AsciiNode(id="a", name="Start", type="entry"),
        AsciiNode(id="b", name="Process", type="tool"),
        AsciiNode(id="c", name="End", type="exit"),
    ],
    edges=[
        AsciiEdge(source="a", target="b"),
        AsciiEdge(source="b", target="c"),
    ],
)

print(render(graph))
  ┌ entry ──┐
  │  Start  │
  └────┬────┘
       │
       ▼
  ┌ tool ───┐
  │ Process │
  └─────┬───┘
        │
        ▼
   ┌ exit ──┐
   │  End   │
   └────────┘

Branching with edge labels

graph = AsciiGraph(
    nodes=[
        AsciiNode(id="start", name="User Input", type="entry"),
        AsciiNode(id="router", name="Router", type="condition"),
        AsciiNode(id="search", name="Web Search", type="tool"),
        AsciiNode(id="calc", name="Calculator", type="tool"),
        AsciiNode(id="respond", name="Respond", type="model"),
    ],
    edges=[
        AsciiEdge(source="start", target="router"),
        AsciiEdge(source="router", target="search", label="search"),
        AsciiEdge(source="router", target="calc", label="calc"),
        AsciiEdge(source="search", target="respond"),
        AsciiEdge(source="calc", target="respond"),
    ],
)

print(render(graph))
           ┌ entry ─────┐
           │ User Input │
           └─────┬──────┘
                 │
                 ▼
          ┌ condition ──┐
          │   Router    │
          └──────┬──────┘
         ┌search─└──calc───┐
         ▼                 ▼
  ┌ tool ──────┐    ┌ tool ──────┐
  │ Web Search │    │ Calculator │
  └──────┬─────┘    └──────┬─────┘
         └───────┌─────────┘
                 ▼
            ┌ model ──┐
            │ Respond │
            └─────────┘

Nested subgraphs

sub = AsciiGraph(
    nodes=[
        AsciiNode(id="s1", name="Fetch Data", type="tool"),
        AsciiNode(id="s2", name="Transform", type="action"),
    ],
    edges=[AsciiEdge(source="s1", target="s2")],
)

graph = AsciiGraph(
    nodes=[
        AsciiNode(id="a", name="Start", type="entry"),
        AsciiNode(id="b", name="ETL Pipeline", type="subgraph", subgraph=sub),
        AsciiNode(id="c", name="Done", type="exit"),
    ],
    edges=[
        AsciiEdge(source="a", target="b"),
        AsciiEdge(source="b", target="c"),
    ],
)

print(render(graph))
     ┌ entry ──┐
     │  Start  │
     └─────┬───┘
           │
           ▼
  ┌ subgraph ──────┐
  │  ETL Pipeline  │
  │ ┌ tool ──────┐ │
  │ │ Fetch Data │ │
  │ └──────┬─────┘ │
  │        │       │
  │        ▼       │
  │  ┌ action ───┐ │
  │  │ Transform │ │
  │  └───────────┘ │
  └────────┬───────┘
           │
           ▼
      ┌ exit ──┐
      │  Done  │
      └────────┘

Node descriptions

graph = AsciiGraph(
    nodes=[
        AsciiNode(id="a", name="LLM", type="model", description="gpt-4o"),
    ],
)

print(render(graph))

Themes (Python API)

from graphtty import render, RenderOptions, get_theme

options = RenderOptions(theme=get_theme("monokai"))
print(render(graph, options))

Render options

from graphtty import RenderOptions

options = RenderOptions(
    use_unicode=True,   # Use Unicode box-drawing characters (default: True)
    show_types=True,    # Show node types in box borders (default: True)
    padding=2,          # Padding around the diagram (default: 2)
)

print(render(graph, options))

JSON format

graphtty reads a simple JSON format:

{
  "nodes": [
    { "id": "a", "name": "Start", "type": "entry" },
    { "id": "b", "name": "Process", "type": "tool", "description": "optional detail" },
    { "id": "c", "name": "End", "type": "exit" }
  ],
  "edges": [
    { "source": "a", "target": "b", "label": "optional" },
    { "source": "b", "target": "c" }
  ]
}

Testing

uv run pytest tests/ -v

Acknowledgements

Built with :heart: on top of grandalf, a Python library for graph layout using the Sugiyama algorithm.

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

graphtty-0.0.3.tar.gz (188.1 kB view details)

Uploaded Source

Built Distribution

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

graphtty-0.0.3-py3-none-any.whl (16.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: graphtty-0.0.3.tar.gz
  • Upload date:
  • Size: 188.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for graphtty-0.0.3.tar.gz
Algorithm Hash digest
SHA256 421cb659ab8a7a181944bbede4325a91745cce85da19875ae303bdf7d0e15772
MD5 d88a3d3b84feb5163fc1d27a302eff60
BLAKE2b-256 f36babf197b42386656b4259b1aba8b4c49c84bcd7d2a4947be55c6554fc8e56

See more details on using hashes here.

Provenance

The following attestation bundles were made for graphtty-0.0.3.tar.gz:

Publisher: cd.yml on cristipufu/graphtty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: graphtty-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 16.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for graphtty-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 d23d0c28b87ab0e8f69d31d7ae1a02bd13e6a7e75322b7855036fa08d633423e
MD5 cea3e155a7f459ab0f6d8e2ebed51bfe
BLAKE2b-256 fa2f8db54def42a4d769c95e2e35c78a1d69dfab1fcf14e744a3bfe0618ccc6e

See more details on using hashes here.

Provenance

The following attestation bundles were made for graphtty-0.0.3-py3-none-any.whl:

Publisher: cd.yml on cristipufu/graphtty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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