Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>TrunkNew to Visual Studio Code? Get it now.

Trunk

Trunk

trunk.io
|
58,650 installs
| (15) | Free
The last linter you'll ever need
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Trunk VS Code Extension

Visual Studio Marketplace Installs Visual Studio Marketplace Rating slack docs platform

Trunk is an extensible, fast, meta code checker and formatter with extraordinary features like caching, preexisting issue detection, a daemon, a language server, and githook management. It's managed completely via config-as-code, so you can easily pin your repo to specific versions of your linters, formatters, and static analyzers.

Don't install a dozen different linter and formatting plugins, just use Trunk. Level up your code quality and consistency today.

Trunk currently runs on OSX, Linux, and WSL2, with Windows support coming soon!

Trunk VSCode Extension

Get Started

Before using the Trunk VSCode extension you need to initialize trunk in your repo. The linters enabled for your repo, their versions, and the version of trunk itself, are all stored in your repo's .trunk/trunk.yaml file.

Press the 'Initialize Trunk' button in the Trunk side panel, to get started

initialize trunk

Or, you can initialize via the command line: Just install the Trunk CLI and run trunk init in your repo.

  • Install Trunk → curl https://get.trunk.io -fsSL | bash (docs)
  • Setup Trunk in your repo → trunk init (docs)
  • See and fix issues as you code in VSCode → You're in the right place 👍

Linters / Formatters

We integrate new linters every release. Stop by on slack and let us know what you'd like next!

Official docs: here

Language Linters
All codespell, cspell, gitleaks, git-diff-check
Ansible ansible-lint
Bash shellcheck, shfmt
Bazel, Starlark buildifier
C, C++, Protobuf clang-format, clang-tidy, include-what-you-use
Cloudformation cfnlint
CSS, SCSS stylelint
Cue cue-fmt
Docker hadolint
Dotenv dotenv-linter
GitHub actionlint
Go gofmt, golangci-lint, semgrep, goimports
HAML haml-lint
Java semgrep
JavaScript, TypeScript, YAML, JSON eslint, prettier, semgrep
Kotlin detekt1, detekt-explicit1, detekt-gradle1, ktlint
Markdown markdownlint
Protobuf buf-breaking, buf-lint
Python autopep8, bandit, black, flake8, isort, mypy, pylint, semgrep, yapf
Ruby brakeman, rubocop, rufo, semgrep, standardrb
Rust clippy, rustfmt
Scala scalafmt
SQL sql-formatter, sqlfluff
SVG svgo
Terraform terraform (validate and fmt), tflint2
TOML taplo
YAML prettier, semgrep, yamllint

  1. Support for Detekt is under active development; see its docs for more details.
  2. Module inspection, deep Checking, and setting variables are not currently supported.

How it works

Trunk downloads everything it needs to run on demand and caches it in ~/.cache/trunk. We run linters in parallel, in the background, and provide a language server interface to show results from VSCode via the Trunk VSCode Extension.

Linting and formatting principles

  • Autoformat every file. Every file.
  • Every file in your repo should have at least one tool checking its validity
  • You should always get the same results locally as on CI

Features

Initialization

Trunk manages all configuration as code in your repo's .trunk/trunk.yaml file. When you first start trunk you'll get a button to initialize it. This scans your repo for which linters and formatters are applicable to you and sets up an initial .trunk/trunk.yaml file for you to use. See the docs for more details.

trunk init

Trunk Side Panel

On the side bar to the left you'll the Trunk icon, which you can use to open the side panel to view issues. By default, issues are populated for every file you open as well as any modified files.

side panel

Trunk also shows Trunk Check Issues in a panel in the File Explorer, but you can hide it if you wish:

hide explorer panel

Formatting

Don't install 15 formatter plugins, just use trunk

Ever hit one of these problems?

  • A formatter plugin doesn't actually install the formatter for you
  • Devs on your team all get slightly different formatting results because you're running different versions of the formatters as vscode plugins
  • Your formatting doesn't match what your CI lint job is expecting because you're running a different version of a formatter locally
  • Your team mostly uses vscode with a committed workspace config w/ formatters, but some people don't use it, leaving your codebase inconsistent

That's what formatting via Trunk solves. Everyone on your team only has to install one plugin, they're guaranteed to get the same results and run the same version of each formatter/linter, and guaranteed to get the same results as your CI lint job (use the Trunk GitHub Action!).

Configuration

None required! But, if you have multiple VSCode plugins installed which act as formatters, you can choose which filetypes to set Trunk as the default formatter for by right clicking and selecting 'Format Document With...'

Then 'Configure Default Formatter' and select 'Trunk'

Or, you can configure which formatter to prefer by editing your json settings (either user settings or workspace settings) with:

"[markdown]": {
  "editor.defaultFormatter": "trunk.io"
},

Issue code documentation links

For many linters we support links to their docs per-issue in the tooltips for each issue:

linter code docs

Ignoring Issues

Trunk supports a special syntax to ignore issues from any linter. See below for the format of trunk-ignore comments.

trunk-ignore

Extras: Trunk CLI & GitHub Action

  1. Install Trunk CLI → curl https://get.trunk.io -fsSL | bash (docs)
  2. Locally check your changes for issues → trunk check (docs)
  3. Locally format your changes → trunk fmt (docs)
  4. Protect lint and format issues from leaking into main → Trunk GitHub Action

Prereqs

None! Trunk manages linters and formatters for you via pinned versions in your repo's .trunk/trunk.yaml file. You don't need to install any linters or configure the extension in any way. We cache linters, formatters, and runtimes in ~/.cache/trunk. Using a linter distributed as a go module but you're not a go user? Don't worry about it, we handle it all 😉.

How versioning works

After you trunk init, trunk.yaml will contain a pinned version of Trunk to use for your repo. When you run trunk, it will automatically detect which version you should be running for a particular repo and, if needed, download it, then run it. The trunk VSCode extension works the same way: regardless of what repo you're in, the underlying version of trunk it runs is based on the pinned version in your trunk.yaml file. Config-as-code 👍.

This means that everyone working in a repo, using the trunk cli, the VSCode extension, or when running on CI, all get the same results because they're running the same version of trunk and the same versions of all the linters/formatters. No more "doesn't happen on my machine". When you want to upgrade to a newer version, just run trunk upgrade and commit the updated trunk.yaml.

Suppressing Issues

Sometimes we want to deliberately tell a linter that, yes, I know what I'm doing, and yes, in any other situation I should not do this, but in this specific case it's fine. Maybe there's a stand-in private key you're using for a test stack, or fixing the lint issue will actually make your code less readable: whatever it is, you now need to figure out how to suppress a given lint issue.

trunk provides a simple, standardized mechanism to do this, saving you from having to look up the linter-specific syntax for doing so:

struct FooBar {
  // trunk-ignore(clang-tidy/modernize-use-nullptr): this is a load-bearing NULL, see ISSUE-832
  void *ptr = NULL;
};

This tells trunk that the clang-tidy linter found a modernize-use-nullptr issue on the highlighted line and that trunk should suppress this linter issue.

Comments are obviously not required:

struct FooBar {
  // trunk-ignore(clang-tidy/modernize-use-nullptr)
  void *ptr = NULL;
};

You can also omit the name of the check to simply tell trunk that all issues from a given linter on a specific line should be suppressed:

struct FooBar {
  // trunk-ignore(clang-tidy)
  void *ptr = NULL;
};

trunk-ignore directives can also be placed at the end of the line on which they're suppressing lint issues:

struct FooBar {
  void *ptr1 = NULL;  // trunk-ignore(clang-tidy/modernize-use-nullptr)
  void *ptr2 = NULL;  // trunk-ignore(clang-tidy)
};

If you need to suppress issues from multiple linters, trunk-ignore supports that too:

struct FooBar {
  // trunk-ignore(clang-tidy): ISSUE-914 explains why the `void *` type is needed
  // trunk-ignore(gitleaks,my-custom-linter/do-not-hardcode-passwords): see ISSUE-915
  void *super_secret_password = (void *)("915dr~S$Pzqod~oR*CrQ$/SQ@hbtQBked:CL@z!y]");
};

Supressing all issues in a file:

// trunk-ignore-all(clang-tidy)
struct FooBar {
  void *ptr1 = NULL;
  void *ptr2 = NULL;
};

Supressing all issues in block of code:

struct FooBar {
  // trunk-ignore-begin(clang-tidy)
  void *ptr1 = NULL;
  void *ptr2 = NULL;
  // trunk-ignore-end(clang-tidy)
};

Notice that a trunk-ignore directive applies not to the next line, but the next non-trunk-ignore line (this only works for preceding directives, not trailing directives), and that you can use a single directive for suppressing multiple checks.

Specification

The syntax of a trunk-ignore directive is as follows:

<trunk-ignore>      ::= "trunk-ignore(" <check-ids> ")" <optional-comment>
<check-ids>         ::= <check-id> <optional-check-id>
<optional-check-id> ::= "," <check-id>
<check-id>          ::= <linter-id> <optional-rule-id>
<optional-rule-id>  ::= "/" <rule-id>
<optional-comment>  ::= ": " <comment>

Configuration

  • trunk.inlineDecorators: boolean – allows to disable inline decorators for diagnostics.
  • trunk.inlineDecoratorsForAllExtensions: boolean – allows to render inline decorators only for diagnostics
  • trunk.showPreexistingIssues: boolean - allows to show/hide pre-existing issues.
  • trunk.showBelowThresholdIssues: boolean - allows to show/hide below-threshold issues

Advanced

  • trunk.autoInit: boolean - sets whether to auto-initialize trunk in non-trunk repositories
  • trunk.trunkPath: string - absolute or workspace-relative path to Trunk
  • trunk.languageServerArguments: array: - allows modifying the arguments to start the trunk LSP. By default, this is just ["lsp-proxy"]. It is unlikely this is needed, unless to submit a debug report, in which case you might set it to be ["lsp-proxy", "--log-level=debug", "--log-file=/tmp/lsp-log.txt].

Multi-root workspace support

The trunk extension supports multi-root workspaces, although it does not currently run trunk simultaneously in multiple repositories.

The default behavior for the extension is to run in the first listed trunk-initialized folder. If none are trunk-initialized, the extension will initialize and run in the first git-initialized folder.

This behavior can be overriden with the trunk.workspaceFolderName setting, which will run the trunk extension in the workspace folder with the matching name.

Feature Requests & Bug Reports

Looking for another feature? Submit a request on Canny!

Hit a bug? 🐛 Let us know on Slack!

Feedback

Join the Trunk Community Slack. ❤️

  • Contact us
  • Jobs
  • Privacy
  • Terms of use
  • Trademarks
© 2023 Microsoft