Skip to main content

A language server, formatter, and linter for Markdown, Quarto, and R Markdown

Project description

Panache

Build and Test Crates.io Open VSX VS Code PyPI version npm version codecov

A language server, formatter, and linter for Markdown, Quarto, and R Markdown, built in Rust with a lossless CST parser and support for external formatters and linters on code blocks.

Installation

Homebrew

Panache is available from Homebrew on macOS and Linux:

brew install panache

From crates.io

If you have Rust installed, the easiest way is likely to install from crates.io:

cargo install panache

Pre-built Binaries

Alternatively, you can install pre-built binary packages from the releases page for Linux, macOS, and Windows. For Linux, packages are available for generic distributions (tarballs) as well as Debian/Ubuntu (.deb) and Fedora/RHEL/openSUSE (.rpm).

If you prefer a one-liner installer that picks the right release artifact for your platform, you can use the installer scripts below. These scripts are fetched directly from this repository and then download the latest matching Panache CLI release asset for your platform, installing to a user-local directory by default. If you prefer, download and inspect the script before running it.

For macOS and Linux:

curl --proto '=https' --tlsv1.2 -LsSf \
    https://raw.githubusercontent.com/jolars/panache/refs/heads/main/scripts/panache-installer.sh | sh

For Windows PowerShell:

powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://raw.githubusercontent.com/jolars/panache/refs/heads/main/scripts/panache-installer.ps1 | iex"

Arch Linux

There are also two recipies available for Arch Linux in the AUR: panache and panache-bin. The first builds from source for your system, the second uses precompiled binaries attatched to GH releases. Install either using yay or your favorite AUR helper:

yay -S panache
yay -S panache-bin

NixOS

Panache is available in NixOS via the panache package in nixpkgs. To add it to your system configuration, include it in the environment.systemPackages:

{ pkgs, ... }:

{
  environment.systemPackages = [
    pkgs.panache
  ];
}

From PyPI (via uv or pipx)

Install with uv or pipx:

# One-shot run, no install:
uvx --from panache-cli panache format path/to/file.qmd

# Persistent install:
uv tool install panache-cli
# or
pipx install panache-cli

From NPM (via npmx)

Install with npx or npmx:

# One-shot run, no install:
npx @panache-cli/panache format path/to/file.qmd

# Persistent install:
npm install -g @panache-cli/panache

VS Code Extension

If you are running VS Code or an editor that supports VS Code extensions (like Positron), you can install the Panache extension from the VS Code Marketplace or the Open VSX extension, which will automatically also install the panache CLI and start the language server when editing supported files.

Development Version

To install the latest development version, you can run

cargo install --git https://github.com/jolars/panache.git panache

This presumes you have a working and up-to-date Rust toolchain (stable, 2024 edition) installed. You also need to have cargo in your PATH if you want to use the panache command directly after installation.

Usage

Panache provides a single CLI interface for formatting, linting, and running the LSP server.

Formatting

To format a file in place, simply run:

panache format document.qmd

You can also format from stdin by piping content into panache format:

cat <file> | panache format

panache format supports glob patterns and recursive directory formatting:

panache format **/*.{qmd,md}

You can use Panache as a linter via the --check flag to check if files are already formatted without making changes:

panache format --check document.qmd

External Code Formatters

Panache supports external formatters for code blocks. For example, you can configure it to run air on R code blocks and ruff on Python code blocks:

[formatters]
r = "air"
python = "ruff"
javascript = "prettier"
typescript = "prettier" # Reuse same formatter

You can setup custom formatters or modify built-in presets with additional arguments:

[formatters]
python = ["isort", "black"]
javascript = "foobar"

[formatters.isort]
args = ["--profile=black"]

[formatters.myformatters]
cmd = "foobar"
args = ["--print-width=100"]
stdin = true

Linting

Panache also features a linter that can report formatting issues and optionally auto-fix them. To run the linter, use:

panache lint document.qmd

As with panache format, you can use glob patterns and recursive formatting:

panache lint **/*.{qmd,md}

External Linters

As with formatting, Panache supports external linters for code blocks. These are configured in the [linters] section of the configuration, but due to the complexity of linting, including dealing with auto-fixing, external linters cannot be customized and only support presets and at the moment only support R via the jarl linter:

# Enable R linting
[linters]
r = "jarl" # R linter with JSON output

Language Server

Panache implements the language server protocol (LSP) to provide editor features like formatting, diagnostics, code actions, and more. See the language server documentation for guides on how to connect Panache to your editor and configure LSP features.

The list of LSP features supported by Panache includes, among others:

  • Document formatting (full document, incremental and range)
  • Diagnostics with quick fixes
  • Code actions for refactoring
    • Convert between loose/compact lists
    • Convert between inline/reference footnotes
  • Document symbols/outline
  • Folding ranges
  • Go to definition for references and footnotes
  • Quaro and Bookdown project awareness

Configuration

Panache looks for a configuration in:

  1. .panache.toml or panache.toml in current directory or parent directories
  2. $XDG_CONFIG_HOME/panache/config.toml (usually ~/.config/panache/config.toml)

Example

# Markdown flavor and line width
flavor = "quarto"
line-width = 80
line-ending = "auto"

# Formatting style
[format]
wrap = "reflow"

# External code formatters (opt-in)
[formatters]
python = ["isort", "black"] # Sequential formatting
r = "air"                   # Built-in preset
javascript = "prettier"     # Reusable definitions
typescript = "prettier"
yaml = "yamlfmt"            # Formats both code blocks AND frontmatter

# Customize formatters
[formatters.prettier]
prepend-args = ["--print-width=100"]

# External code linters
[linters]
r = "jarl"      # Enable R linting
python = "ruff"

See examples/panache.toml for a complete configuration reference.

Integrations

GitHub Actions

For CI, use the dedicated GitHub Action:

- uses: jolars/panache-action@v1

See the Integrations documentation for configuration options.

Pre-commit Hooks

Panache integrates with pre-commit to automatically format and lint your files before committing.

Installation:

First, install pre-commit if you haven't already:

pip install pre-commit
# or
brew install pre-commit

Then add Panache to your .pre-commit-config.yaml:

repos:
  - repo: https://github.com/jolars/panache-pre-commit
    rev: v2.43.1 # Use the latest version
    hooks:
      - id: panache-format # Format files
      - id: panache-lint # Lint and auto-fix issues

Note: The hooks live in jolars/panache-pre-commit, a thin shim repo. This avoids pre-commit autoupdate resolving to unrelated sub-package tags from this monorepo (e.g. panache-code-*). If you currently point at https://github.com/jolars/panache, update the repo: URL and run pre-commit autoupdate.

Install the hooks:

pre-commit install

Panache will now automatically run on your staged .qmd, .md, and .Rmd files before each commit.

See examples/pre-commit-config.yaml for more configuration options.

Motivation

I wanted a formatter that understands Quarto and Pandoc syntax. I have tried to use Prettier as well as mdformat, but both fail to handle some of the particular syntax used in Quarto documents, such as fenced divs and some of the table syntax.

For a side-by-side overview of how Panache compares to Prettier, Pandoc, rumdl, mdformat, mado, markdownlint, markdownlint-cli2, and marksman, see the comparison page. For benchmarks against the same set of tools, see the performance page.

Design Goals and Scope

  • Full LSP implementation with formatting, diagnostics, code actions, and more
  • Standalone CLI for both formatting and linting
  • Support for Quarto, Pandoc, and R Markdown syntax
  • Lossless CST-based parsing
  • Idempotent formatting
  • Semi-opinionated defaults with configurable style options for common formatting decisions
  • Support for running external formatters and linters on code blocks, with built-in presets for popular languages and tools

Acknowledgements

The development of Panache has simplified considerably thanks to the extensive documentation, well-structured code, and testing infrastructure provided by Pandoc. We also owe significant debt to the rust-analyzer project, on which Panche is heavily inspired.

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

panache_cli-2.49.0.tar.gz (2.4 MB view details)

Uploaded Source

Built Distributions

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

panache_cli-2.49.0-py3-none-win_arm64.whl (4.7 MB view details)

Uploaded Python 3Windows ARM64

panache_cli-2.49.0-py3-none-win_amd64.whl (5.0 MB view details)

Uploaded Python 3Windows x86-64

panache_cli-2.49.0-py3-none-musllinux_1_2_x86_64.whl (5.2 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

panache_cli-2.49.0-py3-none-musllinux_1_2_aarch64.whl (4.7 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

panache_cli-2.49.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.1 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

panache_cli-2.49.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.7 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

panache_cli-2.49.0-py3-none-macosx_11_0_arm64.whl (4.7 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

panache_cli-2.49.0-py3-none-macosx_10_12_x86_64.whl (4.9 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file panache_cli-2.49.0.tar.gz.

File metadata

  • Download URL: panache_cli-2.49.0.tar.gz
  • Upload date:
  • Size: 2.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for panache_cli-2.49.0.tar.gz
Algorithm Hash digest
SHA256 9347da05b6fcffdcd2385b595e8a20dc4c50c3662f095cc493d118524436f6c7
MD5 06daf17189035a3c75d6e99fb6df19ab
BLAKE2b-256 109921122f98da121184ce7837fede7fe3b586a8c2a1e0dfcb8a3415093f69e1

See more details on using hashes here.

Provenance

The following attestation bundles were made for panache_cli-2.49.0.tar.gz:

Publisher: publish-pypi.yml on jolars/panache

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

File details

Details for the file panache_cli-2.49.0-py3-none-win_arm64.whl.

File metadata

  • Download URL: panache_cli-2.49.0-py3-none-win_arm64.whl
  • Upload date:
  • Size: 4.7 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for panache_cli-2.49.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 5cfc9a28a4f2ea7ef6c489e80db4d890eac880597417b092ed2191025a05c1c6
MD5 cc5e83640670110b43d86d40bb2c84bf
BLAKE2b-256 c793aa80d24d54bf3de247ed53615ef7529ceeeb87d757eb14008d4b6a9ee99c

See more details on using hashes here.

Provenance

The following attestation bundles were made for panache_cli-2.49.0-py3-none-win_arm64.whl:

Publisher: publish-pypi.yml on jolars/panache

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

File details

Details for the file panache_cli-2.49.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: panache_cli-2.49.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 5.0 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for panache_cli-2.49.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 6b80e6be2136bd425092d3f1cb0d4b5273749b8e32ab4798dbfdfe99ffd86c3a
MD5 d33c7b04e1455591c6a758aac6382982
BLAKE2b-256 0d66d020064b35ce3a1175cf9375f0bfe7716dfca72f999cb14d7f04af998dc4

See more details on using hashes here.

Provenance

The following attestation bundles were made for panache_cli-2.49.0-py3-none-win_amd64.whl:

Publisher: publish-pypi.yml on jolars/panache

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

File details

Details for the file panache_cli-2.49.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for panache_cli-2.49.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 c2cf8615c7c9a44691292c4fd17f0a91727701edd7ff490cf6e89027ec15dad8
MD5 ac5aa0dbaf5ad60e5af3b47697488fac
BLAKE2b-256 eef7bdebe45050ee076536c056259d26f34f56ccd66225393bd446d54c67c8fa

See more details on using hashes here.

Provenance

The following attestation bundles were made for panache_cli-2.49.0-py3-none-musllinux_1_2_x86_64.whl:

Publisher: publish-pypi.yml on jolars/panache

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

File details

Details for the file panache_cli-2.49.0-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for panache_cli-2.49.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 f4b10c2e64de92a27c9da0a488cf1d6358d78175113e67f7d5af418428720f3b
MD5 b236a25e74e006d8744d481a1b668786
BLAKE2b-256 0a0bb9907df47edb0705b239abd07dfc6517951234bbf89d326627f84b9c7550

See more details on using hashes here.

Provenance

The following attestation bundles were made for panache_cli-2.49.0-py3-none-musllinux_1_2_aarch64.whl:

Publisher: publish-pypi.yml on jolars/panache

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

File details

Details for the file panache_cli-2.49.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for panache_cli-2.49.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9c20309b2929dad24f51bf525f51a9c48b4de7c9acef0bce622378c37ed0a4ea
MD5 292fd329b0217e5a9ccb74229daaf422
BLAKE2b-256 4a8549f3b1b0b4043c5c6401c6d327415f897f72228a837dbc0f20aef924a1eb

See more details on using hashes here.

Provenance

The following attestation bundles were made for panache_cli-2.49.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish-pypi.yml on jolars/panache

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

File details

Details for the file panache_cli-2.49.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for panache_cli-2.49.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 2d264ee58f4ef48f9390dbadb375c695071e1955907ca283770c86f402e27e35
MD5 b01391b095e7e2686bb63d4f0ba803c0
BLAKE2b-256 5bb137843524ce2b3710b186057b0ab87a9986a1b9fef84ab3c3e5ed9be3b9be

See more details on using hashes here.

Provenance

The following attestation bundles were made for panache_cli-2.49.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish-pypi.yml on jolars/panache

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

File details

Details for the file panache_cli-2.49.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for panache_cli-2.49.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bf544ffb3c12f763daec38ea050b92ff50206b1b47eb260cb36fa21122139a32
MD5 45bf0fa7b659e916230f9c32df773e86
BLAKE2b-256 b27a8cb3fa7bea45995b11b87a34ce689bdb7f2eb53df222c1db25f7b22a8e8d

See more details on using hashes here.

Provenance

The following attestation bundles were made for panache_cli-2.49.0-py3-none-macosx_11_0_arm64.whl:

Publisher: publish-pypi.yml on jolars/panache

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

File details

Details for the file panache_cli-2.49.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for panache_cli-2.49.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 a18498c4384e27660ec07a2aecf85df98ffea5ec36fd1534b10110edff85ea46
MD5 a6f1c2c85429fce31498ff7e0c1b9e76
BLAKE2b-256 e9b3cdb7b42754148217da46636e45d7958831af59006ed34fef4dd25daf968e

See more details on using hashes here.

Provenance

The following attestation bundles were made for panache_cli-2.49.0-py3-none-macosx_10_12_x86_64.whl:

Publisher: publish-pypi.yml on jolars/panache

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