Adding an auto-formatter plugin to the Qlty CLI in 15 minutes

Jan 3, 2025

Bryan Helmkamp

4 min read

Do you have a favorite auto-formatting tool that you wish your whole team would use? Code formatters are great for maintaining clean diffs and limiting bikeshedding. However, formatting issues will creep into the codebase over time unless they are run on every commit.

The Qlty CLI is an open, extensible code quality tool that supports 50+ linters and formatter plugins. It is designed to be fast enough to be run as a pre-commit hook. Today, the Qlty CLI includes over 30+ code auto-formatters out of the box, and adding a plugin for a new formatter typically takes about 15 minutes.

In this tutorial, we’ll cover how to add support for a new formatter plugin to the Qlty CLI so you can use auto-formatting for all the code, markup, and configuration files in your repository. For this guide, we will add support for Google’s yamlfmt plugin to Qlty.

If you are building a plugin and need any help, please join us on Discord and say hello!

Prerequisites

Install the Qlty CLI

Follow the installation instructions if the Qlty CLI is not installed locally on your $PATH.

Create a temporary repository

Qlty plugins are defined in Sources, which are either Git repositories or local directories. When building plugins, the simplest approach is to create a test repository and configure Qlty to use the current directory as its Source.

To do this, just create a new Git repository and add a Qlty project configuration file at .qlty/qlty.toml with this content:

config_version = "0"

[[source]]
name = "local"
directory = "."

[[plugin]]
name = "yamlfmt"
version = "0.14.0"

Next, create a file at plugins/linters/yamlfmt/plugin.toml with an empty plugin definition for yamlfmt:

config_version = "0"

Running qlty config validate should now exit successfully without any output.

Finally, add a file for testing. To test yamlfmt, I created a basic YAML file with some whitespace issues as test.yaml:

foo     :           123

Step 1. Define a tool installation method

Qlty supports installing code quality tools in nearly every distribution format, including pre-compiled binaries, Node’s NPM, RubyGems, Python Pip, and Rust Crates.

yamlfmt is written in Go. Releases are published on GitHub with pre-compiled binaries for macOS, Linux, and Windows on X86 and Arm CPU architectures. Pre-compiled binaries are a great choice because they are fast and easy to install, so we will use them.

Add a basic plugin definition file at plugins/linters/yamlfmt/plugin.toml that enables installing yamlfmt on all of these platform combinations:

config_version = "0"

[plugins.releases.yamlfmt]
github = "google/yamlfmt"
download_type = "targz"
strip_components = 0

[plugins.definitions.yamlfmt]
releases = ["yamlfmt"]
file_types = ["yaml"

In this case, we use Qlty’s built-in support to download the correct *.tar.gz artifact based on the system it runs on from a GitHub release. (For now, the “driver” block at the end is just a stub.) Since you have already enabled the yamlfmt plugin, you can now install it:

To see what’s happening behind the scenes, you can check the CLI logs, and you’ll see some information about how yamlfmt was installed:

$ cat .qlty/logs/*
INFO [T12] qlty_check::executor (4.8 MB): Installing tool yamlfmt
INFO [T12] qlty_check::tool (4.8 MB): Setting up tool yamlfmt@Some("0.14.0"). Logging to /Users/bhelmkamp/.qlty/cache/tools/yamlfmt/0.14.0-ec6a643cb60a-install.log
INFO [T12] qlty_check::tool::github (4.8 MB): Fetching release assets from google/yamlfmt from 'v0.14.0' tag
INFO [T12] qlty_check::tool::download (4.8 MB): Downloading (tar.gz) https://github.com/google/yamlfmt/releases/download/v0.14.0/yamlfmt_0.14.0_Darwin_arm64.tar.gz
INFO [T12] qlty_check::tool::download (4.9 MB): Extracting to /Users/user/.qlty/cache/tools/yamlfmt/0.14.0-ec6a643cb60a
INFO [T12] qlty_check::tool (4.8 MB): Validated tool: yamlfmt --version: 0.14.0
INFO [T12] qlty_check::tool (4.8 MB): Set up yamlfmt@Some("0.14.0") in 0

Step 2. Define execution plan

Now that you can install yamlfmt, it’s time to finish the plugin and driver definitions so that it can run:

[plugins.definitions.yamlfmt.drivers.format]
driver_type = "formatter"    # ***
script = "yamlfmt ${target}" # ***
success_codes = [0]          # ***
output = "rewrite"           # ***

These driver configuration directives:

  1. Declares that yamlfmt is a formatter that rewrites files in place

  2. Directs Qlty to run yamlfmt by simply passing in the path to the YAML files to format as command line arguments on the shell: yamlfmt ${target}

  3. Instructs Qlty to interpret the exit code zero as success and any other exit code as an error

With those changes, you can now run the plugin:

➜ qlty fmt --all

And the test.yaml file will look much better!

foo: 123

Step 3. Add metadata

With the driver working, we can round out the plugin definition with a bit of additional metadata:

[plugins.definitions.yamlfmt]
description = "An extensible command line tool to format yaml files" # ***
releases = ["yamlfmt"]
file_types = ["yaml"]
config_files = [".yamlfmt"]          # ***
version_command = "yamlfmt -version" # ***
suggested = "config"                 # ***

These additional configuration directives:

  1. Add a metadata description

  2. Declare that files named .yamlfmt files are configuration files and tell Qlty to automatically enable yamlfmt if a .yamlfmt file is found

  3. Enables Qlty to validate yamlfmt installations by running the yamlfmt -version command and checking the output

Step 4. Enable batching for maximum speed

Finally, we can enable batching for a big speed boost. By default, Qlty will invoke the plugin concurrently with one target file at a time.

With batching, the CLI will pass up to 64 files at a time to yamlfmt, reducing overhead:

[plugins.definitions.yamlfmt.drivers.format]
script = "yamlfmt ${target}"
success_codes = [0]
output = "rewrite"
driver_type = "formatter"
batch = true # ***

Qlty CLI's concurrency and batching enable it to run most linters and formatters faster than if they are run directly.

Step 5. Join the community and become a contributor!

We maintain an official repository of 50+ plugins, and we accept contributions from the community for code quality tools that are actively maintained. To add your plugin to this set of plugins, open a pull request on the qltysh/qlty repository in the qlty-plugins/plugins/linters folder.

In future tutorials, we’ll cover adding automated integration tests for plugins and adding a linter that produces code quality issues as output.


Written by

Bryan Helmkamp

CEO, Qlty Software

Code quality and coverage done right

© 2024 Qlty Software Inc.

Code quality and coverage done right

© 2024 Qlty Software Inc.

Code quality and coverage done right

© 2024 Qlty Software Inc.