Metadata-Version: 2.4
Name: graphtty
Version: 0.0.2
Summary: Render directed graphs as ASCII/Unicode art for console output
Project-URL: Repository, https://github.com/cristipufu/graphtty
Maintainer-email: Cristian Pufu <cristian.pufu@uipath.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Build Tools
Requires-Python: >=3.11
Requires-Dist: grandalf==0.8
Requires-Dist: pydantic>=2.0
Description-Content-Type: text/markdown

# graphtty

[![PyPI downloads](https://img.shields.io/pypi/dm/graphtty.svg)](https://pypi.org/project/graphtty/)
[![PyPI - Version](https://img.shields.io/pypi/v/graphtty)](https://img.shields.io/pypi/v/graphtty)
[![Python versions](https://img.shields.io/pypi/pyversions/graphtty.svg)](https://pypi.org/project/graphtty/)

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

## Installation

```bash
pip install graphtty
```

## Screenshots

### React Agent (monokai theme)

![React Agent](https://raw.githubusercontent.com/cristipufu/graphtty/main/screenshots/react-agent.png)

### Deep Agent (ocean theme)

![Deep Agent](https://raw.githubusercontent.com/cristipufu/graphtty/main/screenshots/deep-agent.png)

### Workflow Agent (forest theme)

![Workflow Agent](https://raw.githubusercontent.com/cristipufu/graphtty/main/screenshots/workflow-agent.png)

### Supervisor Agent (dracula theme)

![Supervisor Agent](https://raw.githubusercontent.com/cristipufu/graphtty/main/screenshots/supervisor-agent.png)

## CLI

Render any graph JSON file straight from the terminal:

```bash
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

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

```bash
graphtty graph.json --theme monokai
graphtty graph.json --theme ocean
graphtty graph.json --theme forest
graphtty graph.json --theme dracula
graphtty graph.json                   # default (no color)
```

List all available themes:

```bash
graphtty --list-themes
```

## Python API

### Simple linear chain

```python
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

```python
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

```python
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

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

print(render(graph))
```

### Themes (Python API)

```python
from graphtty import render, RenderOptions, get_theme

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

### Render options

```python
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:

```json
{
  "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

```bash
uv run pytest tests/ -v
```

## Acknowledgements

Built with :heart: on top of [grandalf](https://github.com/bdcht/grandalf), a Python library for graph layout using the Sugiyama algorithm.
