Skip to main content
tally is a production-grade Dockerfile and Containerfile linter + formatter built on BuildKit’s official parser — the same foundation behind docker buildx. It catches issues before they reach production, modernizes syntax automatically, and fits cleanly into any CI pipeline or editor workflow.

Installation

Install via Homebrew, mise, WinGet, npm, Bun, uv, pip, RubyGems, Docker, or Go.

Quick start

Lint your first Dockerfile in under a minute.

Rules reference

Rules across BuildKit, tally, Hadolint, and ShellCheck namespaces.

Configuration

Configure rules, output formats, and fix modes with .tally.toml.

Build invocations

Lint Dockerfiles through Bake targets and Compose services.

Why tally?

Dockerfile linting has traditionally meant picking a compromise:
  • Hadolint is popular and battle-tested, but it uses its own Dockerfile parser, so support for newer BuildKit features can lag behind. It focuses on reporting — not fixing.
  • docker buildx --check runs Docker’s official BuildKit checks, but it requires the Docker/buildx toolchain and is not available if you are using Podman, Finch, or another runtime.
tally takes a different approach:

Key capabilities

BuildKit-native parsing

tally uses BuildKit’s official parser — the same one that docker buildx uses. It correctly handles modern syntax like heredocs, RUN --mount=type=cache, COPY --link, and ADD --checksum without lagging behind new Docker features.

Rules across four namespaces

Rules are grouped by category: correctness, security, performance, style, and maintainability. See the rules reference for the full list.

Safe auto-fix

--fix applies safe, mechanical rewrites — things like canonicalizing STOPSIGNAL, adding --chown flags, and converting RUN echo patterns to COPY heredocs. Nothing is applied that could change build behavior.

Build invocation context

tally can lint Dockerfiles through Docker Buildx Bake and Docker Compose entrypoints. When you run tally lint docker-bake.hcl or tally lint compose.yaml, tally resolves each target or service into the Dockerfile, build context, build args, platform, and selected target stage. See Build invocations for the full workflow.

AI AutoFix via ACP

--fix-unsafe unlocks opt-in AI AutoFix for improvements that are hard to express as a deterministic rewrite. Instead of requiring an API key, tally integrates with ACP (Agent Client Protocol) so you can use the AI agent you already trust — Gemini CLI, OpenCode, GitHub Copilot CLI, and more. All AI fixes are rule-driven (one narrow transformation at a time) and verified by re-parsing and re-linting before anything is written to disk. See the AI AutoFix guide for details.

LSP and editor support

tally lsp exposes a full Language Server Protocol server over stdio, giving you real-time diagnostics in any LSP-compatible editor. Official extensions are available for VS Code and JetBrains IDEs.

CI-ready output formats

tally supports text, JSON, SARIF, GitHub Actions annotations, and Markdown output. SARIF integrates with GitHub Code Scanning, Azure DevOps, and other tools. The Markdown format is optimized for AI agents and token efficiency.

Get started

Install tally

Choose your package manager: Homebrew, mise, WinGet, npm, Bun, uv, pip, RubyGems, Docker, or Go.

Run your first lint

Lint a Dockerfile, read the output, apply fixes, and set up .tally.toml.

Lint Bake and Compose

Use the build definition your project already uses.