djot-fmt
Automatic formatter for djot markup files.
Overview
djot-fmt is a command-line tool that automatically formats djot files, focusing primarily on fixing common list formatting issues:
- Missing newlines between list items
- Incorrect indentation for nested lists
- Blank line spacing before nested content
Installation
go install github.com/KyleKing/djot-fmt@latest
Or from PyPI, which ships the same formatter as a shared library bound with ctypes:
uv tool install djot-fmt # or: pipx install djot-fmt
uvx djot-fmt file.dj # run without installing
The Python wheels carry a compiled library rather than a reimplementation, so output is byte-identical to the Go binary. Formatting runs in-process, which costs about 9 microseconds for a small document against roughly 3 milliseconds to spawn the CLI.
Python API
import djot_fmt
djot_fmt.format('- a\n- b\n') # '- a\n- b\n'
djot_fmt.format(source, wrap_sentences=False)
format raises djot_fmt.DjotFormatError on input the formatter rejects. Calls are
serialized internally because the underlying djot parser is not goroutine-safe.
The shared library is opened on the first call rather than at import, so a process
that imports djot_fmt and then forks stays safe. Calling into it before forking
does not, because the Go runtime does not survive fork() without exec(). Use the
spawn or forkserver start method with multiprocessing.
Usage
Basic Usage
# Format stdin to stdout
cat file.dj | djot-fmt
# Format file and write back
djot-fmt -w file.dj
# Format multiple files and write back
djot-fmt -w file1.dj file2.dj file3.dj
# Check if file is formatted (exit 1 if not)
djot-fmt -c file.dj
# Check multiple files
djot-fmt -c file1.dj file2.dj file3.dj
# Format to different file
djot-fmt -o output.dj input.dj
Batch Processing
# Format all .dj files in current directory
fd -e dj -x djot-fmt -w
# Format all .dj files in specific directory
fd -e dj . content/ -x djot-fmt -w
# Check formatting for all .dj files
fd -e dj -x djot-fmt -c
# Using find (alternative to fd)
find . -name "*.dj" -exec djot-fmt -w {} \;
Options
-w, --write- Write result to source file(s) instead of stdout-c, --check- Check if file(s) are formatted (exit 1 if not)-o, --output FILE- Write output to FILE instead of stdout (single input file only)-h, --help- Show help message-v, --version- Show version information
Validation Options
After formatting, djot-fmt renders both the input and the output to HTML and compares them. A difference means formatting changed what the document says, which is a bug in djot-fmt, so the run fails rather than writing the file.
--no-validate- Skip the check--from-md- Allow the list changes that formatting markdown as djot causes, and report each one that was waived. djot requires a blank line before a nested list where markdown does not, so inserting that line legitimately changes the parse. Nothing else is waived: losing a word, a block kind, or an<ol>start number still fails
SLW (Semantic Line Wrap) Options
--no-wrap-sentences- Disable semantic line wrapping--slw-markers TEXT- Characters that mark sentence endings (default: ".!?")--slw-wrap INTEGER- Maximum line width for wrapping (default: 88, set to 0 to disable)--slw-min-line INTEGER- Minimum line length before wrapping (default: 40, set to 0 for aggressive mode)
Development
This project uses mise for tool management and hk for git hooks.
Setup
# Install mise (if not already installed)
# See: https://mise.jdx.dev/getting-started.html
# Install project tools
mise install
# Install git hooks
hk install --mise
Common Commands
# Run all checks (linting, tests)
mise run ci
# Format code
mise run fmt
# Run tests
mise run test
# Build binary
mise run build
# Install locally
mise run install
Python bindings
# Build the wheel (compiles bindings/cshared with -buildmode=c-shared)
uv build --wheel
# Run the Python tests against the built wheel
uv run --isolated --with dist/*.whl --with pytest pytest bindings/python/tests
bindings/cshared/lib.go is the cgo boundary. Every exported function there recovers
from panics, because a panic crossing into C terminates the host process, which for a
Python caller means killing the interpreter. Strings allocated on the Go side are freed
through DjotFree.
Roadmap
Future enhancements under consideration:
- Support for all djot node types (ordered lists, tables, code blocks, etc.)
- Configurable formatting options (indentation width, line wrapping)
- Semantic line wrapping (similar to mdformat-slw)
- Code block formatting integration
License
MIT
Credits
Built using godjot for djot parsing and AST manipulation.
Metadata
Release files for djot-fmt 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| djot_fmt-0.2.0.tar.gz | 31.1 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| djot_fmt-0.2.0-py3-none-win_arm64.whl | Python 3 | none | Windows ARM64 | Details |
| djot_fmt-0.2.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| djot_fmt-0.2.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl | Python 3 | none | Linux glibc 2.28+ ARM64, Linux glibc 2.17+ ARM64 | Details |
| djot_fmt-0.2.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl | Python 3 | none | Linux glibc 2.5+ x86-64, Linux glibc 2.28+ x86-64 | Details |
| djot_fmt-0.2.0-py3-none-macosx_15_0_x86_64.whl | Python 3 | none | macOS 15.0+ x86-64 | Details |
| djot_fmt-0.2.0-py3-none-macosx_15_0_arm64.whl | Python 3 | none | macOS 15.0+ ARM64 | Details |
Total release size: 5.6 MB
Release files / djot_fmt-0.2.0.tar.gz
| Download URL | djot_fmt-0.2.0.tar.gz |
|---|---|
| Size | 31.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bfdbeb430233ff3737853fca6038f8bbac7a80c7b81b9c8ef362418a8e5e93a0
|
|
BLAKE2b-256 checksum How to use checksums |
f0fdd3e01c00625a310cf1f27205b25000b357f46e9949e2a19655865c0ffcd7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency logRelease files / djot_fmt-0.2.0-py3-none-win_arm64.whl
| Download URL | djot_fmt-0.2.0-py3-none-win_arm64.whl |
|---|---|
| Size | 873.8 kB |
| Tags | Python 3 Windows ARM64 |
|
SHA-256 checksum How to use checksums |
a254071baae80fdb89a41ec005ea9e3bf3c30f8cbfe012badf0da464f6c8ed50
|
|
BLAKE2b-256 checksum How to use checksums |
7221d646b25e990ed180f2b85be86588520d66123665de115c61f1a4b930b03a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency logRelease files / djot_fmt-0.2.0-py3-none-win_amd64.whl
| Download URL | djot_fmt-0.2.0-py3-none-win_amd64.whl |
|---|---|
| Size | 961.3 kB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
be0596507169c5fbb808cfd34c54ad24af1124d260b81927457d764ae874e279
|
|
BLAKE2b-256 checksum How to use checksums |
e2e7c2276c0f8aaf821e817c73c5cb29836c1d547680870903783a984a9b0be1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency logRelease files / djot_fmt-0.2.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
| Download URL | djot_fmt-0.2.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 893.6 kB |
| Tags | Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
1562aaa09144b202482a6589e16e85f3d3ae335823c5447de61c9718b5186c1c
|
|
BLAKE2b-256 checksum How to use checksums |
323c42f9a3086bd34c9bdc9b8d8202dac1caa30f56500fd33d7c95fe6e9266a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency logRelease files / djot_fmt-0.2.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
| Download URL | djot_fmt-0.2.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 969.0 kB |
| Tags | Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
b21ceb6dbee86e8f2b3ae2a16f2ea01fdddc9185d7ce58997b3da4022fb2f74a
|
|
BLAKE2b-256 checksum How to use checksums |
f849eabedd8df82608976893d292247c6edf6a9f1bb2b1a1b1b4a9ba817fc346
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency logRelease files / djot_fmt-0.2.0-py3-none-macosx_15_0_x86_64.whl
| Download URL | djot_fmt-0.2.0-py3-none-macosx_15_0_x86_64.whl |
|---|---|
| Size | 961.3 kB |
| Tags | Python 3 macOS 15.0+ x86-64 |
|
SHA-256 checksum How to use checksums |
94d4e8d5d7f3ce6351bf3d7bb416b7b3d1f3f24771185195b0fb859f5ca5080d
|
|
BLAKE2b-256 checksum How to use checksums |
5a0c4e073ac09d99613c0dc63f2fd0ab5ac526d987bfae5cae16af1e1f746022
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency logRelease files / djot_fmt-0.2.0-py3-none-macosx_15_0_arm64.whl
| Download URL | djot_fmt-0.2.0-py3-none-macosx_15_0_arm64.whl |
|---|---|
| Size | 902.9 kB |
| Tags | Python 3 macOS 15.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
1121557b5d699299e87a277f53d0b45bf660d86bb3016ceaa373e4ad2f7fb052
|
|
BLAKE2b-256 checksum How to use checksums |
e118059afd535c86a6ea0244c91df35c611ac434b1b91610529bd4f210333fb4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency log