All your service logs, one beautiful terminal.
logpilot fans in log streams from Docker Compose services, log files, and systemd units into a single interactive terminal UI — with real-time fuzzy search, per-service filtering, and follow/scroll mode.
- Multi-source fan-in — watch Docker Compose services, plain log files, or a mix of both in one view
- Real-time fuzzy search — type to filter across all log messages instantly
- Regex mode — toggle between fuzzy and regex with
r - Per-service sidebar — enable/disable individual services with
Space - Follow / scroll — auto-scroll to the latest entry, or pause and browse history freely
- Ring buffer — keeps the last N entries in memory (configurable); older entries are evicted, not lost to disk
- Log export — dump the current filtered view to a timestamped
.logfile withe - Zero-config start — works without a config file using sane defaults
go install github.com/renaldid/logpilot@latestDownload a pre-built binary from the releases page.
# Linux (amd64)
curl -sL https://github.com/renaldid/logpilot/releases/latest/download/logpilot_Linux_x86_64.tar.gz \
| tar xz -C /usr/local/bin logpilotgit clone https://github.com/renaldid/logpilot.git
cd logpilot
make build # binary at bin/logpilotRun without any config — logpilot starts up and waits for sources:
logpilotTo watch a Docker Compose project and a log file at the same time, create .logpilot.yaml in your project directory:
buffer_size: 10000 # entries to keep in memory
follow: true # auto-scroll to latest entry
sources:
- name: api
type: docker
compose_file: docker-compose.yml
- name: worker
type: docker
compose_file: docker-compose.yml
- name: nginx
type: file
path: /var/log/nginx/access.logThen run:
logpilot
# or point to a specific config:
logpilot --config /path/to/.logpilot.yaml| Field | Type | Default | Description |
|---|---|---|---|
buffer_size |
int | 10000 |
Maximum log entries kept in memory |
follow |
bool | true |
Auto-scroll to the latest entry on startup |
colors |
map | — | Custom hex colors per service name |
sources |
list | [] |
Log sources (see below) |
docker — streams logs from all running containers in a Compose project:
- name: myapp
type: docker
compose_file: docker-compose.yml # path to your compose filefile — tails a plain text log file:
- name: access
type: file
path: /var/log/nginx/access.logsystemd — follows a systemd unit journal (Linux only):
- name: nginx
type: systemd
unit: nginx.servicecolors:
api: "#7C3AED"
worker: "#059669"
nginx: "#2563EB"| Key | Action |
|---|---|
/ |
Open search bar |
Tab |
Toggle focus: log view ↔ sidebar |
Space |
Toggle service on/off (sidebar focused) |
↑ / k |
Scroll up one line |
↓ / j |
Scroll down one line |
PgUp / PgDn |
Scroll half a page |
f |
Toggle follow mode |
r |
Toggle regex search |
c |
Clear all filters |
e |
Export filtered logs to logpilot-export-<timestamp>.log |
? |
Toggle help overlay |
q / Ctrl+C |
Quit |
logpilot is split into three clean layers with no circular dependencies:
┌─────────────────────────────────────────┐
│ cmd/root.go (Cobra CLI, wires layers) │
└────────────────────┬────────────────────┘
│
┌────────────▼───────────┐
│ internal/source │ LogSource interface
│ FileSource │ TailFunc injectable
│ DockerSource │ DockerClient interface
└────────────┬───────────┘
│ fan-in
┌────────────▼───────────┐
│ internal/pipeline │
│ Aggregator │ goroutine fan-in
│ RingBuffer │ thread-safe circular buffer
│ Filter │ fuzzy + regex, service/level masks
└────────────┬───────────┘
│ <-chan LogEntry
┌────────────▼───────────┐
│ internal/tui │ BubbleTea model
│ State (pure, no I/O) │ fully unit-testable
│ Model (thin wrapper) │ delegates to State
└────────────────────────┘
Key design decisions:
LogSourceinterface — each source is independently startable, stoppable, and mockableTailFuncinjection — file tailing is a function parameter, sowatchLoopis testable without real filesDockerClientinterface — the Docker SDK is hidden behind an interface; tests use a mock- Pure
Statestruct — all TUI business logic lives inStatewith no BubbleTea dependencies; theModelis a thin event dispatcher - 100% test coverage — every business-logic branch is covered; only OS-level terminal/socket I/O is excluded
make test # run all tests
make test-coverage # tests + HTML coverage report
make build # binary at bin/logpilot
make lint # golangci-lint
make release-dry # goreleaser snapshot (no publish)cmd/ CLI entry point (Cobra)
internal/
config/ Config loading (Viper + YAML)
pipeline/ RingBuffer, Filter, Aggregator
source/ FileSource, DockerSource, SystemdSource (Linux), MockSource
tui/ BubbleTea model, State, renderers
pkg/
logentry/ LogEntry type, parser (JSON + text)
MIT — see LICENSE.
