wagoodman/dive
A tool for exploring each layer in a docker image
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 5mo ago
- ✓32+ active contributors
- ✓Distributed ownership (top contributor 34% of recent commits)
Show all 7 evidence items →Show less
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
- ⚠Slowing — last commit 5mo ago
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/wagoodman/dive)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/wagoodman/dive on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: wagoodman/dive
Generated by RepoPilot · 2026-05-07 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/wagoodman/dive shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- Last commit 5mo ago
- 32+ active contributors
- Distributed ownership (top contributor 34% of recent commits)
- MIT licensed
- CI configured
- Tests present
- ⚠ Slowing — last commit 5mo ago
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live wagoodman/dive
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/wagoodman/dive.
What it runs against: a local clone of wagoodman/dive — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in wagoodman/dive | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 173 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of wagoodman/dive. If you don't
# have one yet, run these first:
#
# git clone https://github.com/wagoodman/dive.git
# cd dive
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of wagoodman/dive and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "wagoodman/dive(\\.git)?\\b" \\
&& ok "origin remote is wagoodman/dive" \\
|| miss "origin remote is not wagoodman/dive (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "cmd/dive/cli/cli.go" \\
&& ok "cmd/dive/cli/cli.go" \\
|| miss "missing critical file: cmd/dive/cli/cli.go"
test -f "cmd/dive/cli/internal/ui/v1/app/app.go" \\
&& ok "cmd/dive/cli/internal/ui/v1/app/app.go" \\
|| miss "missing critical file: cmd/dive/cli/internal/ui/v1/app/app.go"
test -f "cmd/dive/cli/internal/command/adapter/analyzer.go" \\
&& ok "cmd/dive/cli/internal/command/adapter/analyzer.go" \\
|| miss "missing critical file: cmd/dive/cli/internal/command/adapter/analyzer.go"
test -f "cmd/dive/cli/internal/ui/v1/view/filetree.go" \\
&& ok "cmd/dive/cli/internal/ui/v1/view/filetree.go" \\
|| miss "missing critical file: cmd/dive/cli/internal/ui/v1/view/filetree.go"
test -f "cmd/dive/cli/internal/command/ci/evaluator.go" \\
&& ok "cmd/dive/cli/internal/command/ci/evaluator.go" \\
|| miss "missing critical file: cmd/dive/cli/internal/command/ci/evaluator.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 173 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~143d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/wagoodman/dive"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Dive is a CLI and TUI tool for analyzing Docker and OCI image layer composition, file changes, and waste. It visualizes each layer's contents in an interactive tree, tracks file modifications across layers, and calculates an 'efficiency score' to identify bloated images. You can run it standalone (dive <image>), integrate it into Docker builds (dive build -t tag .), or use it in CI pipelines (CI=true dive <image>) to enforce image size gates. Modular Go CLI: cmd/dive/cli/cli.go is the entry point; cmd/dive/cli/internal/command/ contains adapter layers (analyzer.go, evaluator.go) that decouple image analysis from the UI. The TUI uses awesome-gocui/gocui for interactive rendering. Image layer analysis logic is separate from presentation, allowing both interactive and CI modes to share the same analysis backend. .data/ holds test image fixtures (various compression formats: gzip, zstd, estargz, uncompressed).
👥Who it's for
Container engineers and DevOps practitioners who want to optimize Docker/OCI image sizes by understanding what's in each layer, identifying duplicate or deleted files, and catching size regressions in CI/CD pipelines.
🌱Maturity & risk
Actively maintained and production-ready. The project is marked 'beta quality' in the README but has proper CI (GitHub Actions validations), comprehensive test coverage (cli_*_test.go files across build/CI/config/JSON/load modes), and a clear release pipeline (.goreleaser.yaml). The go.mod shows recent dependency updates (e.g., Go 1.24, latest Docker and Anchore libs), and the .github/workflows establish automated testing and release processes.
Low risk for core functionality. Single maintainer (wagoodman) is a minor concern, but the project has established release automation, good test coverage, and stable dependencies. The only structural risk is tight coupling to Docker API versions (github.com/docker/docker v28.1.1), which requires careful version management during Docker upgrades. No obvious unmaintained dependencies or deprecated APIs in the visible imports.
Active areas of work
Active maintenance visible in recent Go module updates (e.g., Go 1.24 support, latest charmbracelet/lipgloss for terminal rendering). The .github/workflows/validations.yaml runs on every PR, and .github/workflows/release.yaml automates semver releases. The Taskfile.yaml and .binny.yaml suggest active use of task automation and dependency management tooling.
🚀Get running
git clone https://github.com/wagoodman/dive.git
cd dive
make build
./dive <docker-image-tag>
# Or: CI=true ./dive <docker-image> (for CI mode, no TUI)
Daily commands:
make build # Compiles binary to ./dive
./dive <image-tag> # Interactive TUI mode
CI=true ./dive <image-tag> # JSON/text CI mode (no TUI)
dive build -t mytag . # Build + analyze in one command
🗺️Map of the codebase
cmd/dive/cli/cli.go— Main CLI entry point that orchestrates image analysis, builds command structure, and routes to UI or CI modes—essential for understanding how user input flows through the application.cmd/dive/cli/internal/ui/v1/app/app.go— Core interactive UI application using gocui library; handles rendering, event loops, and state management—critical for understanding the TUI rendering pipeline.cmd/dive/cli/internal/command/adapter/analyzer.go— Adapts image analysis engines (Docker, OCI, eStargz) to a common interface; bridges external image format handling with internal layer representation.cmd/dive/cli/internal/ui/v1/view/filetree.go— File tree view component that displays layer contents with filtering and selection; heavily used in interactive mode for the main file browser panel.cmd/dive/cli/internal/command/ci/evaluator.go— CI evaluation engine that applies rules to assess image efficiency; decision logic for automated image compliance and sizing checks.cmd/dive/cli/internal/ui/v1/layout/manager.go— Layout manager controlling panel positioning and resizing; orchestrates the multi-panel TUI layout (layers, details, file tree, help).cmd/dive/cli/internal/command/export/export.go— Exports analysis results to JSON and other formats; handles result serialization for CI pipelines and automated integrations.
🛠️How to make changes
Add a new CI rule
- Define rule structure in cmd/dive/cli/internal/command/ci/rule.go (e.g., MaxLayerSize, MaxUncompressedSize) (
cmd/dive/cli/internal/command/ci/rule.go) - Implement evaluation logic in cmd/dive/cli/internal/command/ci/evaluator.go to apply the rule to image analysis results (
cmd/dive/cli/internal/command/ci/evaluator.go) - Add rule configuration option to cmd/dive/cli/internal/options/ci.go to allow users to enable/configure the rule (
cmd/dive/cli/internal/options/ci.go) - Add test coverage in cmd/dive/cli/internal/command/ci/evaluator_test.go for rule behavior (
cmd/dive/cli/internal/command/ci/evaluator_test.go)
Add a new interactive UI view panel
- Create new view file in cmd/dive/cli/internal/ui/v1/view/ (e.g., view/summary.go) implementing rendering logic (
cmd/dive/cli/internal/ui/v1/view/renderer.go) - Register the view in cmd/dive/cli/internal/ui/v1/app/app.go by adding it to the views map and layout (
cmd/dive/cli/internal/ui/v1/app/app.go) - Add keybindings for the new view in cmd/dive/cli/internal/ui/v1/app/controller.go (
cmd/dive/cli/internal/ui/v1/app/controller.go) - Update layout manager in cmd/dive/cli/internal/ui/v1/layout/manager.go to allocate screen space for the new panel (
cmd/dive/cli/internal/ui/v1/layout/manager.go)
Add support for a new image format/analyzer
- Create a new analyzer implementation in cmd/dive/cli/internal/command/adapter/ or external package following the analyzer interface (
cmd/dive/cli/internal/command/adapter/analyzer.go) - Register the new analyzer in cmd/dive/cli/internal/command/adapter/analyzer.go GetAnalyzer() function (
cmd/dive/cli/internal/command/adapter/analyzer.go) - Update cmd/dive/cli/internal/command/adapter/resolver.go to detect and route to the new analyzer based on image source (
cmd/dive/cli/internal/command/adapter/resolver.go) - Add test fixtures in .data/ directory and integration tests in cmd/dive/cli/cli_test.go or similar (
cmd/dive/cli/cli_test.go)
Add a new export format
- Implement a format handler function in cmd/dive/cli/internal/command/export/export.go following the existing JSON pattern (
cmd/dive/cli/internal/command/export/export.go) - Add format flag/option to cmd/dive/cli/internal/options/export.go to allow users to select the format (
cmd/dive/cli/internal/options/export.go) - Add test snapshot in cmd/dive/cli/internal/command/export/testdata/snapshots/ for regression testing (
cmd/dive/cli/internal/command/export/export_test.go)
🔧Why these technologies
- gocui — Lightweight terminal UI library enabling cross-platform TUI rendering without heavy dependencies; good for real-time interactive applications with minimal overhead.
- Docker SDK & OCI spec libraries — Dive must support multiple image formats (Docker, OCI, eStargz, Kaniko); these libraries provide standard implementations for layer extraction and configuration parsing.
- Go 1.24 — Enables static compilation to a single binary; no runtime dependencies; excellent for
🪤Traps & gotchas
Docker socket access: The tool requires /var/run/docker.sock (Linux) or Docker Desktop socket (macOS); CI environments must have Docker available. OCI image format complexity: The .data/ directory has test images in 10+ formats (gzip, zstd, estargz, kaniko, OCI); new layer-parsing logic must handle all compression schemes. Config file location: Reads ~/.dive.yaml; if CI runs as non-root, config may not be found. Memory usage: Large images (>10GB layers) can exhaust TUI rendering buffers; no documented limits in README.
🏗️Architecture
💡Concepts to learn
- Docker/OCI Image Layers — Dive's entire purpose is analyzing layer composition; understanding immutable, stacked layers and content-addressable storage is core to diagnosing image bloat
- Union filesystem (UnionFS/overlay2) — Layers are stacked via union filesystems; dive must trace how file deletions, modifications, and additions across layers interact in the final mount view
- Content-addressable image digest (SHA256) — Dive uses layer digests to identify which parts changed; understanding deterministic hashing of layer content is key to tracking incremental builds
- TAR layer serialization — Docker layers are stored as TAR files (.data/test-*-image.tar fixtures); dive must parse TAR headers to extract file metadata and detect whiteout markers (removed files)
- Whiteout files ('.wh.' prefix) — Deleted files in layers are tracked via .wh.* entries in TAR; dive's change detection depends on recognizing these to compute 'wasted space' from deletions
- Image manifest (OCI/Docker spec) — Dive reads image manifests to discover layer ordering and compression; supporting Docker and OCI manifests requires parsing two slightly different JSON schemas
- Efficiency scoring algorithm — The lower-left 'efficiency' metric in the TUI is a custom heuristic (cmd/dive/cli/internal/command/adapter/analyzer.go) that estimates wasted bytes from duplicates and deletions; understanding its limitations is critical for CI gates
🔗Related repos
containers/skopeo— Low-level container image inspection tool; dive is higher-level TUI wrapper but shares same image transport mechanicsmoby/moby— Docker engine itself; dive depends on docker/docker SDK which wraps moby's daemon APIsanchore/syft— Companion tool for container image analysis; both use anchore libraries (anchore/clio, anchore/go-logger) and share DevSecOps use caseGoogleContainerTools/kaniko— Kaniko builds container images without Docker; dive includes test-kaniko-image.tar to verify compatibilitybuildpacks/pack— Alternative container build tool; users compare layer efficiency across different builders, making dive a shared analysis tool
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive tests for ci/rule.go and ci/rules.go evaluation logic
The CI evaluation system (cmd/dive/cli/internal/command/ci/) has evaluator_test.go but lacks dedicated tests for the rule.go and rules.go modules which parse and manage CI rules. Given that this is a critical path for automated image analysis, these components need robust test coverage to prevent regressions in rule parsing and application logic.
- [ ] Create cmd/dive/cli/internal/command/ci/rule_test.go with tests for individual rule creation, validation, and field parsing
- [ ] Create cmd/dive/cli/internal/command/ci/rules_test.go with tests for rule collections, sorting, filtering, and aggregation
- [ ] Add table-driven tests covering edge cases: empty rules, invalid YAML, conflicting rule priorities, and malformed conditions
- [ ] Reference existing test patterns from cmd/dive/cli/internal/command/export/export_test.go
Add integration tests for adapter layer (analyzer, evaluator, resolver, exporter)
The cmd/dive/cli/internal/command/adapter/ directory contains critical adapter interfaces (analyzer.go, evaluator.go, exporter.go, resolver.go) that orchestrate between the CLI and core analysis logic, but there are no dedicated integration tests. These adapters are central to command execution and deserve test coverage to ensure proper data flow and error handling.
- [ ] Create cmd/dive/cli/internal/command/adapter/adapter_integration_test.go testing the full adapter chain
- [ ] Add tests using real image data from .data/test-*.tar files to verify analyzer → evaluator → exporter pipelines
- [ ] Test resolver behavior with different image formats (OCI, Docker, gzip, zstd, estargz) matching the .data test images
- [ ] Verify adapter error propagation and graceful handling of missing or corrupt images
Add missing tests for options parsing (analysis.go, application.go, ci.go)
The cmd/dive/cli/internal/options/ directory defines configuration structures (analysis.go, application.go, ci.go) that are critical for CLI flag parsing and feature toggling, but there are no visible test files for these modules. With Go 1.24, ensuring options are correctly parsed and validated prevents misconfiguration issues.
- [ ] Create cmd/dive/cli/internal/options/analysis_test.go validating analysis option defaults, env var overrides, and validation rules
- [ ] Create cmd/dive/cli/internal/options/application_test.go testing application-level config (logging, output formats, config file paths)
- [ ] Create cmd/dive/cli/internal/options/ci_test.go testing CI-specific options like failure thresholds and rule file loading
- [ ] Verify integration with spf13/cobra flag bindings to catch flag parsing regressions
🌿Good first issues
- Add file filter/search feature to cmd/dive/cli/cli.go: currently users can only scroll; adding regex search in the TUI would help large layer exploration (cmd/dive/cli/internal/command/ would need query handler).
- Expand evaluator.go thresholds: currently only basic pass/fail; add per-layer waste budgets and per-file-type rules (e.g., 'fail if .log files >5MB' in .dive.yaml schema).
- Document layer compression format support matrix: .data/ has 10+ test image formats but README doesn't list which are tested or guaranteed supported; add a table to README.md.
⭐Top contributors
Click to expand
Top contributors
- @wagoodman — 34 commits
- @abitrolly — 17 commits
- @dependabot[bot] — 11 commits
- @luhring — 5 commits
- @yurenchen000 — 4 commits
📝Recent commits
Click to expand
Recent commits
d6c6919— Bump go.uber.org/atomic from 1.9.0 to 1.11.0 (#597) (dependabot[bot])86f7c15— Bump github.com/docker/cli (#600) (dependabot[bot])f8a239d— Bump golang.org/x/net from 0.39.0 to 0.40.0 (#603) (dependabot[bot])c22c76f— Bump golang.org/x/net from 0.38.0 to 0.39.0 (#598) (dependabot[bot])3d070df— Bump github.com/docker/docker (#601) (dependabot[bot])788fcd3— chore: refactor command structure (#587) (wagoodman)bec7cb9— Fix error message returned from getFileList (#593) (alexandear)130f1bb— Simplify dive installation via homebrew core (#594) (henrichter)5fc8c99— Add Containerfile support for dive build command (#536) (#588) (artem-burashnikov)77e136d— Bump golang.org/x/net from 0.37.0 to 0.38.0 (#591) (dependabot[bot])
🔒Security observations
The dive project has a moderate security posture with several concerns primarily around Docker binary sourcing and verification. The main vulnerabilities are: (1) unverified external Docker CLI downloads without checksum validation, creating MITM risks, (2) overly permissive Docker socket access patterns when deployed, and (3) lack of cryptographic verification for critical binaries. The codebase itself uses reasonable dependencies with active maintenance (Anchore, Charmbracelet, Docker libraries). Recommendations focus on implementing binary verification, explicit security documentation for Docker daemon access, and version pinning strategies. The tool is suitable for development/analysis use but should be deployed carefully in production environments with security-conscious usage patterns.
- High · Insecure Docker Image Base - No Verification —
Dockerfile, line 3-4. The Dockerfile downloads Docker CLI from an external source (download.docker.com) using wget without any checksum or signature verification. This creates a Man-in-the-Middle (MITM) attack vector where a compromised download could inject malicious code into the base image. Fix: Implement checksum verification: download the sha256sum file, verify the downloaded tarball against it, and fail the build if verification fails. Additionally, consider using HTTPS pinning or downloading from a mirror with GPG signature verification. - High · Unverified External Binary Execution —
Dockerfile, line 3-4. The Dockerfile directly executes a downloaded Docker binary without validation. Combined with the lack of checksum verification, this could allow execution of compromised binaries. Fix: Add cryptographic verification before extraction and execution. Store the expected SHA256 hash as a build argument and validate before use. - Medium · Alpine Base Image Without Pinned Version —
Dockerfile, line 1. While the Dockerfile uses Alpine 3.21, consider if this is the minimal required version. Without explicit security patching controls, automatic updates could introduce breaking changes. Fix: Explicitly document Alpine version requirements and consider using digest pinning (alpine:3.21@sha256:...) for reproducible builds if security-critical. - Medium · Overly Permissive Docker Socket Access Pattern —
README.md usage pattern. The tool is designed to analyze Docker images, which typically requires Docker daemon access. If users run this via Docker with-v /var/run/docker.sock:/var/run/docker.sock, it grants full Docker daemon access equivalent to root. Fix: Document security implications clearly. Recommend running with restricted capabilities where possible. Advise users to only run dive from trusted images and in trusted environments. - Medium · Dependency on Untrusted Docker CLI Releases —
Dockerfile, ARG DOCKER_CLI_VERSION. The tool downloads Docker CLI binaries from external sources with an arbitrary DOCKER_CLI_VERSION argument. No validation of version format or authenticity is performed. Fix: Implement version whitelist validation, use official Docker repository sources only, and document approved versions. Consider vendoring critical dependencies. - Low · Missing Security Headers in Configuration —
cmd/dive/cli/internal/ui/. While not directly visible in provided files, the Go application uses various UI and configuration modules without explicit mention of security headers or XSS protection mechanisms. Fix: Ensure all user input is properly sanitized and HTML-escaped. Review charmbracelet/lipgloss usage for proper output encoding. - Low · Potential Path Traversal in File Analysis —
cmd/dive/cli/internal/command/adapter/analyzer.go. The tool analyzes Docker image layers and files using spf13/afero filesystem abstraction. If path validation is insufficient, it could potentially leak sensitive files. Fix: Ensure all file path operations use secure path joining and restrict analysis to expected directories. Validate paths cannot traverse outside image boundaries.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.