LogoLogo
SlackLogin
  • Overview
    • Welcome
  • Setup & Configuration
    • Connecting to Trunk
    • Managing Your Organization
      • GitHub App Permissions
  • Integration with Slack
  • Flaky Tests (Beta)
    • Overview
    • Get Started
      • Test Frameworks
        • Android
        • Bazel
        • Behave
        • cargo-nextest
        • Cypress
        • Dart Test
        • Go
        • GoogleTest
        • Gradle
        • Jasmine
        • Jest
        • Karma
        • Maven
        • minitest
        • Mocha
        • Nightwatch
        • NUnit
        • Pest
        • PHPUnit
        • Playwright
        • Pytest
        • Robot Framework
        • RSpec
        • Swift Testing
        • Vitest
        • XCTest
        • Other Test Frameworks
      • CI Providers
        • Azure DevOps Pipelines
        • BitBucket Pipelines
        • Buildkite
        • CircleCI
        • Drone CI
        • GitHub Actions
        • GitLab
        • Jenkins
        • Semaphore CI
        • TeamCity
        • Travis CI
        • Other CI Providers
    • Dashboard
    • Flaky Test Detection
    • Quarantining
    • PR Comments
    • Ticketing Integrations
      • Jira Integration
      • Linear Integration
      • Other Ticketing Platforms
    • Webhooks
      • Slack Integration
      • Microsoft Teams Integration
      • GitHub Issues Integration
      • Linear Integration
    • Uploader CLI Reference
  • Merge Queue
    • Overview
    • How does it work?
    • Setup
      • Quick Start
      • Settings
      • Integration for Slack
    • Concepts and Optimizations
      • Predictive Testing
      • Optimistic Merging
      • Pending Failure Depth
      • Anti-Flake Protection
      • Batching
      • Parallel Queues
        • Bazel
        • Nx
        • API
      • FAQ
    • Priority
    • Managing Merge Queue
      • Using the Merge UI
      • Metrics
      • Command Line
    • Webhooks
    • Reference
  • Code Quality
    • Overview
    • Why Metalinters?
      • How does it work?
      • Why Code Quality?
    • Setup & Installation
      • Initialize Trunk
      • Local Linting
      • Linting in CI
      • Nightly Report (Deprecated)
    • IDE Integration
      • VSCode
      • Neovim
      • GitHub Codespaces
    • Linters
      • Supported Linters
        • Actionlint
        • Ansible-lint
        • Autopep8
        • Bandit
        • Biome
        • Black
        • Brakeman
        • buf
        • Buildifier
        • cfnlint
        • Checkov
        • circleci
        • ClangFormat
        • clang-tidy
        • Clippy
        • cmake-format
        • codespell
        • cspell
        • cue-fmt
        • dart
        • deno
        • Detekt
        • djlint
        • dotenv-linter
        • dotnet-format
        • dustilock
        • ESLint
        • Flake8
        • git-diff-check
        • Gitleaks
        • Gofmt
        • gofumpt
        • goimports
        • gokart
        • golangci-lint
        • golines
        • google-java-format
        • graphql-schema-linter
        • hadolint
        • haml-lint
        • isort
        • iwyu
        • ktlint
        • kube-linter
        • markdown-link-check
        • markdown-table-prettify
        • Markdownlint
        • markdownlint-cli2
        • mypy
        • nancy
        • nixpkgs-fmt
        • opa
        • OSV-Scanner
        • Oxipng
        • perlcritic
        • perltidy
        • php-cs-fixer
        • phpstan
        • pmd
        • pragma-once
        • pre-commit-hooks
        • Prettier
        • prisma
        • psscriptanalyzer
        • Pylint
        • pyright
        • regal
        • remark-lint
        • renovate
        • rome
        • rubocop
        • Ruff
        • rufo
        • rustfmt
        • scalafmt
        • semgrep
        • ShellCheck
        • shfmt
        • sort-package-json
        • sourcery
        • sql-formatter
        • SQLFluff
        • sqlfmt
        • squawk
        • standardrb
        • stringslint
        • stylelint
        • stylua
        • SVGO
        • swiftformat
        • swiftlint
        • taplo
        • Terraform
        • terragrunt
        • terrascan
        • TFLint
        • tfsec
        • tofu
        • Trivy
        • Trufflehog
        • txtpbfmt
        • vale
        • Yamllint
        • yapf
      • Run Linters
      • Manage Linters
      • Configure Linters
      • Ignoring Issues and Files
      • Custom Linters
      • Shared Configs
      • Upgrades
    • Debugging
    • Licensing
  • CLI & API References
    • CLI Reference
      • Install
      • Getting Started
        • Code Quality
        • Merge Queue
        • Flaky Tests
        • Tools
        • Actions
          • Git Hooks
        • Announce
      • Compatibility
      • Caching
      • Commands Reference
        • Code Quality
        • Actions
        • Merge
      • Configuration
        • Plugins
          • Share Config Between Codebases
          • Exporting Linter Configs
        • Runtimes
        • Tools
        • Lint
          • Definitions
          • Commands
          • Output
          • Output Parsing
          • Files and Caching
          • Dependencies
          • Auto-Enable
        • Actions
          • Notifications
          • Logging and Troubleshooting
        • Merge
        • Telemetry
        • Per User Overrides
    • API Reference
      • Flaky Tests
      • Merge Queue
      • Webhooks Reference
  • Pricing & Security
    • Security
  • Billing
  • Community & Support
  • Links
    • Open App
    • Slack Community
    • Changelog
    • Feature Requests
On this page
  • Get started
  • Organizing your code
  • Publishing your plugin
Edit on GitHub
  1. CLI & API References
  2. CLI Reference
  3. Configuration
  4. Plugins

Share Config Between Codebases

Sharing configuration between codebases using public config repos

Last updated 6 months ago

To standardize Trunk configuration across an organization, you can create and publish a public plugins repository. This repo can define new linter definitions, specify enabled linters and actions, and even .

Once you've created your plugin repository, you can source it in other repositories to adopt shared configuration across your organization. For an example of how we do this in our own org, check out our .

Note that in order to keep linters and tools up to date in your plugin configs repo, you'll need to run trunk upgrade --apply-to=plugin.yaml to apply . After making a public GitHub release with your plugin changes, other dependent repos will pick up these changes automatically when running trunk upgrade.

Get started

Let's walk through how to create a simple linter that warns about TODOs in your codebase.

We'll start by creating a new Git repository:

PLUGIN_PATH=~/my-first-trunk-plugin
mkdir "${PLUGIN_PATH}" && cd "${PLUGIN_PATH}"
git init

And then create a linter that can find TODOs in your codebase using grep and sed:

cat >plugin.yaml <<EOF
version: 0.1
lint:
  definitions:
    - name: todo-finder
      files: [ALL]
      commands:
        - output: parsable
          run: grep --with-filename --line-number --ignore-case todo ${target}
          success_codes: [0, 1]
          read_output_from: stdout
          parser:
            run: "sed -E 's/(.*):([0-9]+):(.*)/\\1:\\2:0: [error] Found todo in \"\\3\" (found-todo)/'"
EOF

Now we can turn this linter on in a repository where we have trunk set up:

trunk plugins add my-first-plugin <plugin-path>
trunk check enable todo-finder

And now, to demonstrate how this works, let's trunk check some files where we know we have TODOs:

trunk check $(git grep -li todo | head -n 10)

which will show you something like this:

.eslintrc.yaml:19:0
  19:0  high  Found todo in "  # TODO(chris): Figure out why this causes a massive slowdown ... .trunk/dev-out/O1F.txt  local.todo-finder/found-todo
 101:0  high  Found todo in "  node/no-unpublished-import: off # TODO: do we want this?"                                local.todo-finder/found-todo

Organizing your code

In the example we gave above, we put the linter's source code in plugin.yaml, which is fine for an example, but not really great for anything more than that. We can take the sed command from the plugin we created earlier and push that into the shell script:

#!/bin/bash
sed -E 's/(.*):([0-9]+):(.*)/\1:\2:0: [error] Found todo in \"\3\" (found-todo)/'"

Tip: Remember to run chmod u+x todo-finder-parser.sh so that trunk can run it!

and also point the definition of todo-finder at it:

version: 0.1
lint:
  definitions:
    - name: todo-finder
      files: [ALL]
      commands:
        - output: parsable
          run: grep --with-filename --line-number --ignore-case todo ${target}
          success_codes: [0, 1]
          read_output_from: stdout
          parser:
            run: ${plugin}/todo-finder-parser.sh

We can also go another step and push the entire linter definition into a shell script:

#!/bin/bash
grep --with-filename --line-number --ignore-case todo "${1}" | \
  sed -E 's/(.*):([0-9]+):(.*)/\1:\2:0: [error] Found todo in \"\3\" (found-todo)/'"
version: 0.1
lint:
  definitions:
    - name: todo-finder
      files: [ALL]
      commands:
        - output: parsable
          run: ${plugin}/todo-finder.sh
          success_codes: [0]

Publishing your plugin

To share your plugin with the world, all you have to do is tag a release and push it to GitHub, Gitlab, or some other repository hosting service:

git add .
git commit "Create a TODO finder"
git tag -a v0.0.0 --message "Initial TODO finder release"
git remote add origin <repo-url>
git push origin main v0.0.0

Now that it's available on the Internet, everyone else can just use your plugin by running:

trunk plugins add --id=their-first-plugin <repo-url> v0.0.0

See our documentation on and for more on what you can do, such as writing your parser in Javascript or Python!

export linter configs
configs repo
upgrades
custom linters
custom parsers