@wharflab/tally-darwin-x64
v0.19.0
Published
tally binary for darwin-x64
Readme
tally
tally is a production-grade Dockerfile/Containerfile linter + formatter that keeps build files clean, modern, and consistent.
It uses BuildKit's official parser and checks (the same foundation behind docker buildx) plus a safe auto-fix engine. It runs fast,
doesn't require Docker Desktop or a daemon, and fits neatly into CI.
# Lint everything in the repo (recursive)
tally lint .
# Apply all safe fixes automatically
tally lint --fix DockerfileWhy tally
Modern Dockerfiles deserve modern tooling. tally is opinionated in the right places:
- BuildKit-native: understands modern syntax like heredocs,
RUN --mount=...,COPY --link, andADD --checksum=.... - Fixes, not just findings:
--fixapplies safe, mechanical rewrites;--fix-unsafeunlocks opt-in risky fixes (including AI). - Modernizes on purpose: converts eligible
RUN/COPYinstructions to heredocs, prefersADD --extract, and more. - Broad rule coverage: combines Docker's official BuildKit checks, embedded ShellCheck for shell snippets, Hadolint-compatible rules, and tally-specific rules.
- Registry-aware without Docker: uses a Podman-compatible registry client for image metadata checks (no daemon required).
- Editor + CI friendly: VS Code extension (
wharflab.tally, powered bytally lsp) and outputs for JSON, SARIF, and GitHub Actions annotations. - Easy to install anywhere: Homebrew, Go, npm, pip, and RubyGems.
- Written in Go: single fast binary, built on production-grade libraries.
Quality bar: 92% code coverage on Codecov and 2,900+ Go tests executed in CI.
Dockerfile linting usually means 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 also is commonly consumed as a prebuilt binary, and it focuses on reporting — not fixing.
docker buildx --checkruns Docker's official BuildKit checks, but it requires the Docker/buildx toolchain and can be heavier than a pure static linter (and not always available if you're using Podman/Finch/other runtimes).
Roadmap: more auto-fixes, more Hadolint parity, richer registry-aware checks, and higher-level rules (cache & tmpfs mount recommendations, tooling-aware checks for uv/bun, line-length and layer optimizations).
Optional: AI AutoFix via ACP
tally supports opt-in AI AutoFix for the kinds of improvements that are hard to express as a deterministic rewrite.
Instead of asking you for an API key, tally integrates with ACP (Agent Client Protocol) so you can use the agent you already trust (Gemini CLI, OpenCode, GitHub Copilot CLI, and more), while tally keeps linting fast and validates proposed changes before applying them.
AI fixes are rule-driven (one narrow transformation at a time) and verified (re-parse + re-lint) before anything is applied.
- Guide:
docs/guide/ai-autofix-acp.md
Supported Rules
tally integrates rules from multiple sources:
| Source | Rules | Description | |--------|-------|-------------| | BuildKit | 22/22 rules | Docker's official Dockerfile checks (captured + reimplemented) | | tally | 23 rules | Custom rules including secret detection with gitleaks | | Hadolint | 37 rules | Hadolint-compatible Dockerfile rules (expanding) |
Shell linting is provided via embedded ShellCheck (rules under the shellcheck/ namespace).
See RULES.md for the complete rules reference.
Installation
Homebrew (macOS/Linux)
brew install wharflab/tap/tallyNPM
npm install -g tally-cliPyPI
pip install tally-cliRubyGems
gem install tally-cliGo
go install github.com/wharflab/tally@latestFrom Source
git clone https://github.com/wharflab/tally.git
cd tally
go build .Usage
# Check a Dockerfile
tally lint Dockerfile
# Check all Dockerfiles in current directory (recursive)
tally lint .
# Check with glob patterns
tally lint "**/*.Dockerfile"
# Exclude patterns
tally lint --exclude "vendor/*" --exclude "test/*" .
# Check with max lines limit
tally lint --max-lines 100 Dockerfile
# Output as JSON
tally lint --format json Dockerfile
# Check multiple files
tally lint Dockerfile.dev Dockerfile.prod
# Enable context-aware rules (e.g., copy-ignored-file)
tally lint --context . DockerfileFile Discovery
When given a directory, tally recursively searches for Dockerfiles using these default patterns:
DockerfileDockerfile.*(e.g.,Dockerfile.dev,Dockerfile.prod)*.Dockerfile(e.g.,api.Dockerfile,frontend.Dockerfile)Containerfile(Podman convention)Containerfile.**.Containerfile
Use --exclude to filter out unwanted files:
# Exclude vendor and test directories
tally lint --exclude "vendor/*" --exclude "test/*" .
# Exclude all .bak files
tally lint --exclude "*.bak" .Rules Overview
For the complete list of all supported rules, see RULES.md.
Context-Aware Rules
Some rules require build context awareness. Enable them with the --context flag:
# Enable context-aware rules
tally lint --context . Dockerfilecopy-ignored-file: Detects when COPY or ADD commands reference files that would be excluded by .dockerignore. This helps catch mistakes
where files are copied but won't actually be included in the build.
# .dockerignore contains: *.log
# This will trigger a warning:
COPY app.log /app/ # File matches .dockerignore pattern
# Heredoc sources are exempt (they're inline, not from context):
COPY <<EOF /app/config.txt
inline content
EOFIgnoring Violations
Suppress specific violations using inline comment directives:
# tally ignore=StageNameCasing
FROM alpine AS Build
# tally global ignore=max-lines;reason=Generated file
FROM alpinetally also supports hadolint and check=skip directive formats for easy migration.
See Configuration Guide for full directive syntax.
Configuration
Create a .tally.toml in your project:
[output]
format = "text"
fail-level = "warning"
[rules]
include = ["buildkit/*", "tally/*"]
exclude = ["buildkit/MaintainerDeprecated"]
[rules.tally.max-lines]
max = 100Configuration priority: CLI flags > environment variables > config file > defaults.
See Configuration Guide for full reference.
Output Formats
tally supports multiple output formats for different use cases.
Text (default)
Human-readable output with colors and source code snippets:
tally lint DockerfileWARNING: StageNameCasing - https://docs.docker.com/go/dockerfile/rule/stage-name-casing/
Stage name 'Builder' should be lowercase
Dockerfile:2
────────────────────
1 │ FROM alpine
>>>2 │ FROM ubuntu AS Builder
3 │ RUN echo "hello"
────────────────────JSON
Machine-readable format with summary statistics and scan metadata:
tally lint --format json DockerfileThe JSON output includes:
files: Array of files with their violationssummary: Aggregate statistics (total, errors, warnings, etc.)files_scanned: Total number of files scannedrules_enabled: Number of active rules (withDefaultSeverity != "off")
{
"files": [
{
"file": "Dockerfile",
"violations": [
{
"location": {
"file": "Dockerfile",
"start": { "line": 2, "column": 0 }
},
"rule": "buildkit/StageNameCasing",
"message": "Stage name 'Builder' should be lowercase",
"severity": "warning",
"docUrl": "https://docs.docker.com/go/dockerfile/rule/stage-name-casing/"
}
]
}
],
"summary": {
"total": 1,
"errors": 0,
"warnings": 1,
"info": 0,
"style": 0,
"files": 1
},
"files_scanned": 1,
"rules_enabled": 41
}SARIF
Static Analysis Results Interchange Format for CI/CD integration with GitHub Code Scanning, Azure DevOps, and other tools:
tally lint --format sarif Dockerfile > results.sarifGitHub Actions
Native GitHub Actions workflow command format for inline annotations:
tally lint --format github-actions Dockerfile::warning file=Dockerfile,line=2,title=StageNameCasing::Stage name 'Builder' should be lowercaseMarkdown
Concise Markdown tables optimized for AI agents and token efficiency:
tally lint --format markdown Dockerfile**2 issues** in `Dockerfile`
| Line | Issue |
| ---- | ------------------------------------------- |
| 10 | ❌ Use absolute WORKDIR |
| 2 | ⚠️ Stage name 'Builder' should be lowercase |Features:
- Summary upfront with issue counts
- Sorted by severity (errors first)
- Emoji indicators: ❌ error, ⚠️ warning, ℹ️ info, 💅 style
- No rule codes or doc URLs (token-efficient)
- Multi-file support with File column when needed
Output Options
| Flag | Description |
| --------------- | -------------------------------------------------------------------- |
| --format, -f | Output format: text, json, sarif, github-actions, markdown |
| --output, -o | Output destination: stdout, stderr, or file path |
| --no-color | Disable colored output (also respects NO_COLOR env var) |
| --show-source | Show source code snippets (default: true) |
| --hide-source | Hide source code snippets |
Exit Codes
See Exit Codes for the full reference.
Fail Level
Control which severity levels cause a non-zero exit code:
# Fail only on errors (ignore warnings)
tally lint --fail-level error Dockerfile
# Never fail (useful for CI reporting without blocking)
tally lint --fail-level none --format sarif Dockerfile > results.sarif
# Fail on any violation including style issues (default behavior)
tally lint --fail-level style DockerfileAvailable levels (from most to least severe): error, warning, info, style (default), none
IDE Integration
VS Code
Install the official tally extension from the Visual Studio Marketplace for real-time linting and diagnostics.
JetBrains IDEs
Install the official Tally plugin from JetBrains Marketplace for IDE integration in IntelliJ-based editors.
Other Editors
Any editor that supports the Language Server Protocol can use tally's built-in LSP server over stdio:
npx -y tally-cli lsp --stdioDevelopment
Running Tests
# Run all tests
make test
# Run linting
make lint
# Run copy/paste detection (CPD)
make cpdCode Quality
This project uses:
- golangci-lint for Go linting
- PMD CPD for copy/paste detection (minimum 100 tokens)
Copy/paste detection runs automatically in CI and helps identify duplicate code patterns.
Contributing
See CLAUDE.md for development guidelines.
License
GPL-3.0-only. See LICENSE for the full license text.
