streamdown


Namestreamdown JSON
Version 0.34.0 PyPI version JSON
download
home_pageNone
SummaryA streaming markdown renderer for modern terminals with syntax highlighting
upload_time2025-07-25 21:48:10
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords cli markdown renderer syntax-highlighting terminal
VCS
bugtrack_url
requirements pygments pylatexenc appdirs term-image wcwidth toml
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <p align="center">
<img src=https://github.com/user-attachments/assets/0468eac0-2a00-4e98-82ca-09e6ac679357/>
<br/>
<a href=https://pypi.org/project/streamdown><img src=https://badge.fury.io/py/streamdown.svg/></a>
<br/><strong>Terminal streaming markdown that rocks</strong>

</p>


Streamdown works with any streaming markdown such as [simonw's llm](https://github.com/simonw/llm) or even something basic like curl. 

It's designed for compatibility with the wide variety of markdown from various LLM models. 

It supports standard piping and files as arguments like any normal pager but can also run as a wrapper so you retain full keyboard interactivity. Arrow keys, control, alt, all still work.
```bash
$ pip install streamdown
```
![Streamdown is Amazing](https://github.com/user-attachments/assets/268cb340-78cc-4df0-a773-c5ac95eceeeb)

## Fast and Realtime.
Watch Streamdown run over a FIFO pipe through `tee` in tmux on an M4 using BitNet.  This is run straight. No clever unbuffering tricks. You can see the unstructured content on the right and the realtime Streamdown render on the left.

[bitnet.webm](https://github.com/user-attachments/assets/62eb625e-82c4-462d-9991-ed681d6fbcd0)


### Provides clean copyable code for long code lines
Other renderers inject line breaks when copying code that wraps around. Streamdown's better and now you are too!

Set `PrettyBroken` and `PrettyPad` to False in your toml (see below) to make Streamdown ensure code is always cleanly mouse copyable
![Handle That Mandle](https://github.com/user-attachments/assets/a27aa70c-f691-4796-84f0-c2eb18c7de23)


### Supports images
Here's kitty and alacritty. 
![doggie](https://github.com/user-attachments/assets/81c43983-68cd-40c1-b1d5-aa3a52004504)

### Hyperlinks (OSC 8) and Clipboard (OSC 52)
The optional `Clipboard` feature puts the final codeblock into your clipboard. See below for details.

[links.webm](https://github.com/user-attachments/assets/a5f71791-7c58-4183-ad3b-309f470c08a3)

### As well as everything else...
Here's the `Savebrace` feature with `screen-query` and `sq-picker` from [llmehelp](https://github.com/kristopolous/llmehelp). You can have an ongoing conversation in tmux with your terminal session. Then use popups and fzf to insert command or coding blocks all with a keystroke.

This allows you to interactively debug  in a way that the agent doesn't just wander off doing silly things.

It takes about 2 minutes to set up and about 0.2s to use. Fast, fluid and free.
![screenquery](https://github.com/user-attachments/assets/517be4fe-6962-4e4c-b2f2-563471bc48d0)

### ...even CJK 
Compare how streamdown wraps and spaces this tabular Chinese description of programming languages to other leading markdown renderers.

Only one generates the text without truncation. 很美!
![cjk](https://github.com/user-attachments/assets/cae485d7-c478-4836-9732-d9fa49e13bc9)

### Colors are highly (and quickly) configurable for people who care a lot, or just a little.
![configurable](https://github.com/user-attachments/assets/19ca2ec9-8ea1-4a79-87ca-8352789269fe)

### Has a [Plugin](https://github.com/kristopolous/Streamdown/tree/main/streamdown/plugins) system to extend the parser and renderers.
For instance, here is the [latex plugin](https://github.com/kristopolous/Streamdown/blob/main/streamdown/plugins/latex.py) doing math inside a table:
![calc](https://github.com/user-attachments/assets/0b0027ca-8ef0-4b4a-b4ae-e36ff623a683)



It is designed for AI and can be used to do parser based sophisticated pipelines and routing, cracking open various monolithic AI solutions to permit them to integrate. Think of it as output level routing at the semantic level.

You can also just use it like a normal person.
## Configuration 

The location it's stored is platform specific and can be seen with the `-h` flag. If this file does not exist upon first run, it will be created with default values. 

Here are the sections:

**`[style]`**

Defines the base Hue (H), Saturation (S), and Value (V) from which all other palette colors are derived. This can also be specified at runtime via command line arguments. See below! 

The default values are [at the beginning of the source](https://github.com/kristopolous/Streamdown/blob/main/streamdown/sd.py#L33).

*   `HSV`: [ 0.0 - 1.0, 0.0 - 1.0, 0.0 - 1.0 ] 
*   `Dark`: Multipliers for background elements, code blocks. 
*   `Grey`: Multipliers for blockquote and thinkblock. 
*   `Mid`: Multipliers for inline code backgrounds, table headers. 
*   `Symbol`: Multipliers for list bullets, horizontal rules, links. 
*   `Head`: Multipliers for level 3 headers. 
*   `Bright`: Multipliers for level 2 headers. 
*   `Margin` (integer, default: `2`): The left and right indent for the output. 
*   `Width` (integer, default: `0`): Along with the `Margin`, `Width` specifies the base width of the content, which when set to 0, means use the terminal width. See [#6](https://github.com/kristopolous/Streamdown/issues/6) for more details
*   `PrettyPad` (boolean, default: `true`): Uses a unicode vertical pad trick to add a half height background to code blocks. This makes copy/paste have artifacts. See [#2](https://github.com/kristopolous/Streamdown/issues/2). I like it on. But that's just me
*   `PrettyBroken` (boolean, default: `true`): This will break the copy/paste assurance above. The output is much prettier, but it's also broken. So it's pretty broken. Works nicely with PrettyPad.
*   `ListIndent` (integer, default: `2`): This is the recursive indent for the list styles.
*   `Syntax` (string, default `native`): This is the syntax [highlighting theme which come via pygments](https://pygments.org/styles/).

Example:
```toml
[style]
PrettyPad = true
PrettyBroken = true
HSV = [0.7, 0.5, 0.5]
Dark = { H = 1.0, S = 1.2, V = 0.25 } # Make dark elements less saturated and darker
Symbol = { H = 1.0, S = 1.8, V = 1.8 } # Make symbols more vibrant
```

**`[features]`**

Controls optional features:

*   `CodeSpaces` (boolean, default: `true`): Enables detection of code blocks indented with 4 spaces. Set to `false` to disable this detection method (triple-backtick blocks still work).
*   `Clipboard` (boolean, default: `true`): Enables copying the last code block encountered to the system clipboard using OSC 52 escape sequences upon exit. Set to `false` to disable.
*   `Logging` (boolean, default: `false`): Enables logging to tmpdir (/tmp/sd) of the raw markdown for debugging and bug reporting. The logging uses an emoji as a record separator so the actual streaming delays can be simulated and replayed. If you use the `filename` based invocation, that is to say, `sd <filename>`, this type of logging is always off.
*   `Savebrace` (boolean, default: `true`): Saves the code blocks of a conversation to the append file `$TMP/sd/$UID/savebrace` so you can `fzf` or whatever you want through it. See how it's used in DAY50's [sidechat](https://github.com/day50-dev/sidechat).

Example:
```toml
[features]
CodeSpaces = false
Clipboard = false
```

## Command Line
The most exciting feature here is `--exec` with it you can do full readline support like this:

```shell
$ sd --exec "llm chat"
```

And now you have all your readline stuff. It's pretty great. (Also see the DAY50 shellwrap project.)

It's also worth noting that things like the `-c` aren't "broken" with regard to file input. You can do something like this:

```shell
$ sd -c <(echo "[style]\nMargin=10") 
```

To override the margin.

```shell
usage: sd [-h] [-l LOGLEVEL] [-b BASE] [-c CONFIG] [-w WIDTH] [-e EXEC]
          [-s SCRAPE] [filenameList ...]

Streamdown is a streaming markdown renderer for modern terminals.
https://github.com/day50-dev/Streamdown

paths:
  config                /home/chris/.config/streamdown/config.toml
  logs                  /tmp/sd/1000

positional arguments:
  filenameList          Input file to process (also takes stdin)

optional arguments:
  -h, --help            show this help message and exit
  -l LOGLEVEL, --loglevel LOGLEVEL
                        Set the logging level
  -b BASE, --base BASE  Set the hsv base: h,s,v
  -c CONFIG, --config CONFIG
                        Use a custom config override
  -w WIDTH, --width WIDTH
                        Set the width WIDTH
  -e EXEC, --exec EXEC  Wrap a program EXEC for more 'proper' i/o handling
  -s SCRAPE, --scrape SCRAPE
                        Scrape code snippets to a directory SCRAPE
  -v, --version         Show version information
```

**Note**: Some features are not supported on some OSs. Please file a ticket if you need a feature on your platform that isn't working.

## Demo
Do this

    $ ./streamdown/sd.py tests/*md

## Install from source
After the git clone least one of these should work, hopefully. it's using the modern uv pip tool but is also backwards compatible to the `pip3 install -r requirements.txt` flow.

    $ pipx install -e .
    $ pip install -e .
    $ uv pip install -e . 

Explore the rest of [DAY50](https://github.com/day50-dev). Feel free to follow us, there's some exciting stuff coming.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "streamdown",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "cli, markdown, renderer, syntax-highlighting, terminal",
    "author": null,
    "author_email": "Chris McKenzie <kristopolous@yahoo.com>",
    "download_url": "https://files.pythonhosted.org/packages/50/aa/935f2ea83a36e89f04645a7b197288c7742cac902d14df75957b7c29ded0/streamdown-0.34.0.tar.gz",
    "platform": null,
    "description": "<p align=\"center\">\n<img src=https://github.com/user-attachments/assets/0468eac0-2a00-4e98-82ca-09e6ac679357/>\n<br/>\n<a href=https://pypi.org/project/streamdown><img src=https://badge.fury.io/py/streamdown.svg/></a>\n<br/><strong>Terminal streaming markdown that rocks</strong>\n\n</p>\n\n\nStreamdown works with any streaming markdown such as [simonw's llm](https://github.com/simonw/llm) or even something basic like curl. \n\nIt's designed for compatibility with the wide variety of markdown from various LLM models. \n\nIt supports standard piping and files as arguments like any normal pager but can also run as a wrapper so you retain full keyboard interactivity. Arrow keys, control, alt, all still work.\n```bash\n$ pip install streamdown\n```\n![Streamdown is Amazing](https://github.com/user-attachments/assets/268cb340-78cc-4df0-a773-c5ac95eceeeb)\n\n## Fast and Realtime.\nWatch Streamdown run over a FIFO pipe through `tee` in tmux on an M4 using BitNet.  This is run straight. No clever unbuffering tricks. You can see the unstructured content on the right and the realtime Streamdown render on the left.\n\n[bitnet.webm](https://github.com/user-attachments/assets/62eb625e-82c4-462d-9991-ed681d6fbcd0)\n\n\n### Provides clean copyable code for long code lines\nOther renderers inject line breaks when copying code that wraps around. Streamdown's better and now you are too!\n\nSet `PrettyBroken` and `PrettyPad` to False in your toml (see below) to make Streamdown ensure code is always cleanly mouse copyable\n![Handle That Mandle](https://github.com/user-attachments/assets/a27aa70c-f691-4796-84f0-c2eb18c7de23)\n\n\n### Supports images\nHere's kitty and alacritty. \n![doggie](https://github.com/user-attachments/assets/81c43983-68cd-40c1-b1d5-aa3a52004504)\n\n### Hyperlinks (OSC 8) and Clipboard (OSC 52)\nThe optional `Clipboard` feature puts the final codeblock into your clipboard. See below for details.\n\n[links.webm](https://github.com/user-attachments/assets/a5f71791-7c58-4183-ad3b-309f470c08a3)\n\n### As well as everything else...\nHere's the `Savebrace` feature with `screen-query` and `sq-picker` from [llmehelp](https://github.com/kristopolous/llmehelp). You can have an ongoing conversation in tmux with your terminal session. Then use popups and fzf to insert command or coding blocks all with a keystroke.\n\nThis allows you to interactively debug  in a way that the agent doesn't just wander off doing silly things.\n\nIt takes about 2 minutes to set up and about 0.2s to use. Fast, fluid and free.\n![screenquery](https://github.com/user-attachments/assets/517be4fe-6962-4e4c-b2f2-563471bc48d0)\n\n### ...even CJK \nCompare how streamdown wraps and spaces this tabular Chinese description of programming languages to other leading markdown renderers.\n\nOnly one generates the text without truncation. \u5f88\u7f8e\uff01\n![cjk](https://github.com/user-attachments/assets/cae485d7-c478-4836-9732-d9fa49e13bc9)\n\n### Colors are highly (and quickly) configurable for people who care a lot, or just a little.\n![configurable](https://github.com/user-attachments/assets/19ca2ec9-8ea1-4a79-87ca-8352789269fe)\n\n### Has a [Plugin](https://github.com/kristopolous/Streamdown/tree/main/streamdown/plugins) system to extend the parser and renderers.\nFor instance, here is the [latex plugin](https://github.com/kristopolous/Streamdown/blob/main/streamdown/plugins/latex.py) doing math inside a table:\n![calc](https://github.com/user-attachments/assets/0b0027ca-8ef0-4b4a-b4ae-e36ff623a683)\n\n\n\nIt is designed for AI and can be used to do parser based sophisticated pipelines and routing, cracking open various monolithic AI solutions to permit them to integrate. Think of it as output level routing at the semantic level.\n\nYou can also just use it like a normal person.\n## Configuration \n\nThe location it's stored is platform specific and can be seen with the `-h` flag. If this file does not exist upon first run, it will be created with default values. \n\nHere are the sections:\n\n**`[style]`**\n\nDefines the base Hue (H), Saturation (S), and Value (V) from which all other palette colors are derived. This can also be specified at runtime via command line arguments. See below! \n\nThe default values are [at the beginning of the source](https://github.com/kristopolous/Streamdown/blob/main/streamdown/sd.py#L33).\n\n*   `HSV`: [ 0.0 - 1.0, 0.0 - 1.0, 0.0 - 1.0 ] \n*   `Dark`: Multipliers for background elements, code blocks. \n*   `Grey`: Multipliers for blockquote and thinkblock. \n*   `Mid`: Multipliers for inline code backgrounds, table headers. \n*   `Symbol`: Multipliers for list bullets, horizontal rules, links. \n*   `Head`: Multipliers for level 3 headers. \n*   `Bright`: Multipliers for level 2 headers. \n*   `Margin` (integer, default: `2`): The left and right indent for the output. \n*   `Width` (integer, default: `0`): Along with the `Margin`, `Width` specifies the base width of the content, which when set to 0, means use the terminal width. See [#6](https://github.com/kristopolous/Streamdown/issues/6) for more details\n*   `PrettyPad` (boolean, default: `true`): Uses a unicode vertical pad trick to add a half height background to code blocks. This makes copy/paste have artifacts. See [#2](https://github.com/kristopolous/Streamdown/issues/2). I like it on. But that's just me\n*   `PrettyBroken` (boolean, default: `true`): This will break the copy/paste assurance above. The output is much prettier, but it's also broken. So it's pretty broken. Works nicely with PrettyPad.\n*   `ListIndent` (integer, default: `2`): This is the recursive indent for the list styles.\n*   `Syntax` (string, default `native`): This is the syntax [highlighting theme which come via pygments](https://pygments.org/styles/).\n\nExample:\n```toml\n[style]\nPrettyPad = true\nPrettyBroken = true\nHSV = [0.7, 0.5, 0.5]\nDark = { H = 1.0, S = 1.2, V = 0.25 } # Make dark elements less saturated and darker\nSymbol = { H = 1.0, S = 1.8, V = 1.8 } # Make symbols more vibrant\n```\n\n**`[features]`**\n\nControls optional features:\n\n*   `CodeSpaces` (boolean, default: `true`): Enables detection of code blocks indented with 4 spaces. Set to `false` to disable this detection method (triple-backtick blocks still work).\n*   `Clipboard` (boolean, default: `true`): Enables copying the last code block encountered to the system clipboard using OSC 52 escape sequences upon exit. Set to `false` to disable.\n*   `Logging` (boolean, default: `false`): Enables logging to tmpdir (/tmp/sd) of the raw markdown for debugging and bug reporting. The logging uses an emoji as a record separator so the actual streaming delays can be simulated and replayed. If you use the `filename` based invocation, that is to say, `sd <filename>`, this type of logging is always off.\n*   `Savebrace` (boolean, default: `true`): Saves the code blocks of a conversation to the append file `$TMP/sd/$UID/savebrace` so you can `fzf` or whatever you want through it. See how it's used in DAY50's [sidechat](https://github.com/day50-dev/sidechat).\n\nExample:\n```toml\n[features]\nCodeSpaces = false\nClipboard = false\n```\n\n## Command Line\nThe most exciting feature here is `--exec` with it you can do full readline support like this:\n\n```shell\n$ sd --exec \"llm chat\"\n```\n\nAnd now you have all your readline stuff. It's pretty great. (Also see the DAY50 shellwrap project.)\n\nIt's also worth noting that things like the `-c` aren't \"broken\" with regard to file input. You can do something like this:\n\n```shell\n$ sd -c <(echo \"[style]\\nMargin=10\") \n```\n\nTo override the margin.\n\n```shell\nusage: sd [-h] [-l LOGLEVEL] [-b BASE] [-c CONFIG] [-w WIDTH] [-e EXEC]\n          [-s SCRAPE] [filenameList ...]\n\nStreamdown is a streaming markdown renderer for modern terminals.\nhttps://github.com/day50-dev/Streamdown\n\npaths:\n  config                /home/chris/.config/streamdown/config.toml\n  logs                  /tmp/sd/1000\n\npositional arguments:\n  filenameList          Input file to process (also takes stdin)\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -l LOGLEVEL, --loglevel LOGLEVEL\n                        Set the logging level\n  -b BASE, --base BASE  Set the hsv base: h,s,v\n  -c CONFIG, --config CONFIG\n                        Use a custom config override\n  -w WIDTH, --width WIDTH\n                        Set the width WIDTH\n  -e EXEC, --exec EXEC  Wrap a program EXEC for more 'proper' i/o handling\n  -s SCRAPE, --scrape SCRAPE\n                        Scrape code snippets to a directory SCRAPE\n  -v, --version         Show version information\n```\n\n**Note**: Some features are not supported on some OSs. Please file a ticket if you need a feature on your platform that isn't working.\n\n## Demo\nDo this\n\n    $ ./streamdown/sd.py tests/*md\n\n## Install from source\nAfter the git clone least one of these should work, hopefully. it's using the modern uv pip tool but is also backwards compatible to the `pip3 install -r requirements.txt` flow.\n\n    $ pipx install -e .\n    $ pip install -e .\n    $ uv pip install -e . \n\nExplore the rest of [DAY50](https://github.com/day50-dev). Feel free to follow us, there's some exciting stuff coming.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A streaming markdown renderer for modern terminals with syntax highlighting",
    "version": "0.34.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/day50-dev/Streamdown/issues",
        "Homepage": "https://github.com/day50-dev/Streamdown"
    },
    "split_keywords": [
        "cli",
        " markdown",
        " renderer",
        " syntax-highlighting",
        " terminal"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f7718a7184f7ffda1e14e544a000ca31eb3509c226eb454491c0cd32c53ab179",
                "md5": "d674caccdc918cdfdcb3e96c67975c24",
                "sha256": "10752293199fabfde388cd5be67101105d8a8586c895457cb1ee9679ca9202e6"
            },
            "downloads": -1,
            "filename": "streamdown-0.34.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d674caccdc918cdfdcb3e96c67975c24",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 23711,
            "upload_time": "2025-07-25T21:48:08",
            "upload_time_iso_8601": "2025-07-25T21:48:08.419756Z",
            "url": "https://files.pythonhosted.org/packages/f7/71/8a7184f7ffda1e14e544a000ca31eb3509c226eb454491c0cd32c53ab179/streamdown-0.34.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "50aa935f2ea83a36e89f04645a7b197288c7742cac902d14df75957b7c29ded0",
                "md5": "ef157eb8cba6bea4e77135fa06b15a1e",
                "sha256": "4959fcfeb2436e6b373a484108f982bb52be1d5c8d1485fbc605559a39ac25d0"
            },
            "downloads": -1,
            "filename": "streamdown-0.34.0.tar.gz",
            "has_sig": false,
            "md5_digest": "ef157eb8cba6bea4e77135fa06b15a1e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 4306048,
            "upload_time": "2025-07-25T21:48:10",
            "upload_time_iso_8601": "2025-07-25T21:48:10.616190Z",
            "url": "https://files.pythonhosted.org/packages/50/aa/935f2ea83a36e89f04645a7b197288c7742cac902d14df75957b7c29ded0/streamdown-0.34.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-25 21:48:10",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "day50-dev",
    "github_project": "Streamdown",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "pygments",
            "specs": []
        },
        {
            "name": "pylatexenc",
            "specs": []
        },
        {
            "name": "appdirs",
            "specs": []
        },
        {
            "name": "term-image",
            "specs": []
        },
        {
            "name": "wcwidth",
            "specs": []
        },
        {
            "name": "toml",
            "specs": []
        }
    ],
    "lcname": "streamdown"
}
        
Elapsed time: 0.88611s