README
¶
layerx
Interactive Docker image layer inspector with CI-friendly efficiency checks. Single binary; no daemon required when reading saved image archives.
What is layerx?
A terminal tool for understanding what's inside a Docker image — which layer added each file, where the wasted bytes are, and what your RUN steps actually produced.
Use it to:
- Debug bloated images and find the layer responsible
- Review the filesystem impact of a Dockerfile change before merging
- Gate CI on layer waste or efficiency thresholds
Quick Start
# macOS / Linux
brew install deveshctl/tap/layerx
# Inspect a Docker image (daemon required)
layerx nginx:latest
# Or inspect a local docker-save / OCI archive (no daemon needed)
layerx ./build/app.tar
Other platforms: see Install.
What you can do
| Mode | Command | Best for |
|---|---|---|
| Interactive | layerx IMAGE_OR_ARCHIVE |
Exploring layers, diffs, file contents, wasted bytes |
| CI | layerx ci IMAGE_OR_ARCHIVE or CI=true layerx ... |
Pipeline gates on efficiency / wasted bytes |
| Export | layerx --json out.json IMAGE_OR_ARCHIVE |
Scripts, dashboards, jq |
IMAGE_OR_ARCHIVE is auto-detected: an existing file is read directly without contacting any container runtime, anything else is resolved through the Docker daemon. All three modes accept either form.
Interactive explorer
- Browse layers with vim keys; see Dockerfile command, size, short digest
- Per-layer file tree with diff colouring (green = added, yellow = modified, red = removed)
- Open files inline with line numbers, scrolling, and in-viewer search
- Sort by size, filter by name, hide unchanged files
- Extract a file to disk, copy a path, or copy file contents to your clipboard (works over SSH and tmux)
- Efficiency score and wasted bytes always visible in the status bar
See TUI keybindings for the full shortcut list.
CI mode
- Three configurable rules: lowest efficiency, highest wasted bytes, highest user-wasted percent
- Exits
0on pass,1on rule failure,2on internal error - Configurable via
.layerx.yamlor CLI flags
JSON export
Full analysis (layers, files, efficiency) as JSON — pipe through jq for scripted checks.
Prerequisites
Docker is required when inspecting Docker image references (nginx:latest, myregistry/app:tag). It is not required when inspecting a local archive file (docker save output or OCI layout tarball) — archive mode reads the file directly.
| Platform | Install |
|---|---|
| Linux | Docker Engine |
| macOS | Docker Desktop |
| Windows | Docker Desktop |
Install
Homebrew (macOS & Linux)
brew install deveshctl/tap/layerx
Scoop (Windows)
scoop bucket add layerx https://github.com/deveshctl/scoop-bucket
scoop install layerx
Debian / Ubuntu
# amd64
curl -LO https://github.com/deveshctl/layerx/releases/latest/download/layerx_linux_amd64.deb
sudo dpkg -i layerx_linux_amd64.deb
# arm64
curl -LO https://github.com/deveshctl/layerx/releases/latest/download/layerx_linux_arm64.deb
sudo dpkg -i layerx_linux_arm64.deb
RHEL / Fedora
# amd64
curl -LO https://github.com/deveshctl/layerx/releases/latest/download/layerx_linux_amd64.rpm
sudo rpm -i layerx_linux_amd64.rpm
# arm64
curl -LO https://github.com/deveshctl/layerx/releases/latest/download/layerx_linux_arm64.rpm
sudo rpm -i layerx_linux_arm64.rpm
Direct download
Prebuilt binaries for Linux, macOS, and Windows (amd64 + arm64) on the Releases page. For a specific version, replace latest with the tag (e.g. v1.2.2) in the URLs above.
Build from source
Requires Go 1.26+:
go install github.com/deveshctl/layerx@latest
Usage
# Interactive TUI — Docker reference
layerx nginx:latest
# Interactive TUI — local archive (no daemon required)
layerx ./build/app.tar
# Force a fresh analysis (bypass the cache)
layerx --no-cache nginx:latest
# CI mode — exit 1 if efficiency < 95% (works for both inputs)
layerx ci --lowest-efficiency 0.95 nginx:latest
layerx ci --lowest-efficiency 0.95 ./build/app.tar
# JSON export
layerx --json analysis.json nginx:latest
# Shell completion (bash)
source <(layerx completion bash)
TUI keybindings
| Key | Action |
|---|---|
Tab |
Switch panel (layers ↔ file tree) |
j / k |
Move up / down |
g / G |
Jump to top / bottom |
Enter |
Open file viewer; expand or collapse a folder |
Esc |
Back (close search → close viewer → clear filter → quit) |
/ |
Filter file tree (tree) / search in viewer (viewer) |
n / N |
Next / previous search match (viewer) |
y |
Copy file path to clipboard |
Y |
Copy file content (viewer) or layer command (layers) |
d |
Toggle diff-only mode (hide unchanged files) |
s |
Cycle sort: default → largest → smallest |
x |
Extract focused file to disk |
? |
Toggle help overlay |
q |
Quit |
CI mode
GitHub Actions
- name: Install layerx
run: |
curl -LO https://github.com/deveshctl/layerx/releases/latest/download/layerx_linux_amd64.deb
sudo dpkg -i layerx_linux_amd64.deb
- name: Check image efficiency
run: layerx ci --lowest-efficiency 0.95 myapp:${{ github.sha }}
Configuration
Drop a .layerx.yaml in your project root:
rules:
lowest-efficiency: 0.9
highest-wasted-bytes: 52428800 # 50MB
highest-user-wasted-percent: 0.1
CLI flags override config-file values. Setting a threshold to 0 or negative disables that rule.
Caching & environment
| Variable | Purpose |
|---|---|
CI=true |
Treat layerx IMAGE (no subcommand) as layerx ci IMAGE |
LAYERX_CACHE_DIR |
Override the default analysis cache directory |
Repeat runs against an unchanged image digest reuse the cache and skip the tar export and parse. --no-cache (alias --refresh) bypasses the cache for a single run; the run still refreshes the cache on success.
Troubleshooting
- "Cannot connect to the Docker daemon" — Docker isn't running. Start Docker Desktop, or
sudo systemctl start dockeron Linux. (Tip: if your image is already saved as a tarball, pass the file path instead — no daemon required.) - "Archive not found" — the path you passed doesn't exist or isn't a regular file. Check spelling and that you're not pointing at a directory.
- "Not a valid image archive" — the file exists but isn't a
docker saveor OCI layout tarball. Re-export withdocker save -o image.tar IMAGEor build with--output type=oci,dest=image.tar. - "image not found" — layerx pulls images on demand. Check the reference and that you can
docker pullit manually. - Cache permission errors — point
LAYERX_CACHE_DIRsomewhere writable, e.g.LAYERX_CACHE_DIR=$HOME/.cache/layerx.
Contributing
Issues and PRs welcome. For larger changes, please open an issue first to discuss the approach. See CHANGELOG for release notes.
Architecture
image/ Domain layer — Docker SDK, tar parsing, file tree, efficiency
tui/ Bubbletea v2 TUI — consumes image/ interfaces only
ci/ CI evaluator — consumes image/ interfaces only
cmd/ Cobra CLI — wires packages together
config/ .layerx.yaml loader
Design rules:
image/has zero imports fromtui/,ci/, orconfig/- TUI and CI consume interfaces, never concrete Docker SDK types
- All Docker client calls negotiate the API version (no breakage on Docker Engine upgrades)
- Both whiteout conventions handled correctly (regular and opaque)
Tech stack
| Concern | Choice |
|---|---|
| Language | Go 1.26+ |
| CLI | cobra |
| TUI | bubbletea v2 + lipgloss v2 + bubbles v2 |
| Docker | moby/moby client |
| Config | goccy/go-yaml |
| Testing | testify |
License
MIT
Documentation
¶
There is no documentation for this package.