CLI tool
ymtdzzz/otel-tui avatar
ymtdzzz/otel-tui

otel-tui: an OpenTelemetry viewer that lives in your terminal

A terminal OpenTelemetry viewer inspired by otel-desktop-viewer

1,109 stars32 forksGoApache-2.0

At a glance

What is it?
otel-tui is a terminal user interface for OpenTelemetry, inspired by the otel-desktop-viewer project, and it receives signals over OTLP, Zipkin, Prometheus, and Datadog endpoints in one process. It is built on the OpenTelemetry Collector as a library, so the receivers come from the collector rather than being reimplemented.
Who is it for?
Adopt otel-tui if you want to watch traces, metrics, and logs from a local instrumented service without standing up a full backend. Do not adopt it as a production observability store, because the README documents a fixed in-memory buffer.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What it is, and what it is not

otel-tui is a terminal OpenTelemetry viewer inspired by otel-desktop-viewer, and it is described in the repository metadata as a terminal OpenTelemetry viewer. The first line of the README is more specific: a terminal OpenTelemetry viewer inspired by the otel-desktop-viewer project.

The scope is three data types and one medium. Traces are shown as a list, a span view, and a topology view. Metrics are shown as a stream. Logs are shown as a list, and the tool can show logs related to a specific trace or span. The screenshots in the README cover traces, spans, topologies, metrics, and logs, so the feature set is a viewer, not an analysis environment.

The formats supported are listed in one line and they matter, because they are the difference between a tool you can point at your existing service and one you cannot. It currently supports OpenTelemetry, Zipkin for traces, Prometheus for metrics, and Datadog for traces, metrics, and logs.

The project is written in Go, the primary language is Go, the licence is Apache 2.0, the default branch is main, and the last push to the repository was on 2026-10-14. The recent releases are v0.7.5 from 2026-09-12, v0.7.4 from 2026-08-10, and v0.7.3 from 2026-05-13. The homepage is not given, so the README and the releases are the reference.

The receivers, and why the extra protocols are opt-in

The Getting Started section lists the ports the tool exposes, and the detail to notice is that not all of them are on by default.

Port 4317 receives OpenTelemetry signals over gRPC, and 4318 receives them over HTTP, which are the standard OTLP ports. Port 9411 receives Zipkin traces and is enabled with the --enable-zipkin option. Port 8126 receives Datadog signals and port 8125 receives DogStatsD metrics, and both are enabled with the --enable-datadog option.

So the default posture is OTLP only, and the older and vendor protocols are opt-in. That is the right default for a tool that binds ports, since each extra receiver is another listening socket on the machine.

The other flag worth understanding is --prom-target, which takes a repeatable list and enables the Prometheus receiver with target endpoints, and the help text gives the two forms, a host and port such as localhost:9000, and a full URL such as http://other-host:9000/custom/prometheus.

There is also --from-json-file for a JSON file path exported by the JSON exporter, which is the offline path: you export a file and read it without running anything live.

And there is a detail about the browser. The server's Access-Control-Allow-Origin header includes localhost, allowing telemetry to be sent directly from browser applications running on localhost. That is a development convenience, since it lets a frontend SDK report straight into the viewer without a collector in between.

Installing it, in five different ways

The distribution options are unusually thorough, and each one tells you something about the intended audience.

Homebrew is the first:

sh
$ brew install ymtdzzz/tap/otel-tui

Then go install, for the Go toolchain crowd:

sh
$ go install github.com/ymtdzzz/otel-tui@latest

Then Docker, in the interactive form:

sh
$ docker run --rm -it --name otel-tui ymtdzzz/otel-tui:latest

or as a background process you attach to later, which is the pattern for running the viewer alongside a compose stack:

sh
# Run otel-tui as a background process
$ docker run --rm -dit --name otel-tui ymtdzzz/otel-tui:latest

# Show TUI in your current terminal session
$ docker attach otel-tui

# Detach by pressing Ctrl+p -> Ctrl+q

Docker Compose is the fourth, with a service definition for the viewer and the matching collector configuration to point an OpenTelemetry collector at it:

yml
oteltui:
  image: ymtdzzz/otel-tui:latest
  container_name: otel-tui
  stdin_open: true
  tty: true
  # Override entrypoint if you want use options
  entrypoint: ["/otel-tui", "--enable-zipkin"]
yml
exporters:
  otlp:
    endpoint: oteltui:4317
    tls:
      insecure: true
service:
  pipelines:
    traces:
      exporters: [otlp]
    logs:
      exporters: [otlp]

And Nix, with nix develop github:ymtdzzz/otel-tui, plus an executable binary from the GitHub releases page and a from source route that is go run ./... after cloning. The fact that a Nix flake, a Homebrew tap, a Go install path, and a distroless Docker image all exist suggests a project with a broad user base across different workflows.

Built on the OpenTelemetry Collector as a library

The go.mod is unusual enough to be worth reading closely, because it explains the whole receiver story.

The first line is a generated marker: the file was produced by the collector's own builder command, and it should not be edited. The module path is then github.com/ymtdzzz/otel-tui, targeting Go 1.26.0.

The dependencies are the collector's own components, at version 0.162.0 for the contrib packages and 1.68.0 for the core ones. The receivers are the contrib receivers for datadogreceiver, otlpjsonfilereceiver, prometheusreceiver, statsdreceiver, and zipkinreceiver, plus the core otlpreceiver. The collector service, processor, connector, extension, confmap, and component packages are all there, along with the yaml and env confmap providers, which is where the config.yml.tpl template in the repository comes from.

The reason this matters is that otel-tui is not a program that reimplemented five ingestion protocols. It is the OpenTelemetry Collector running in-process with a terminal user interface attached to it. Every receiver, every processor behaviour, and every configuration option the collector supports is available, and the tool inherits them rather than reimplementing them.

There is also a bearertokenauthextension in the dependency list, which is the collector's bearer token authentication extension. That is how you put a token in front of the OTLP endpoints, which matters because the tool binds to 0.0.0.0 by default, as the --host flag shows, and a receiver listening on all interfaces with no authentication is not something you want on a shared network.

The other dependencies are the ordinary ones for a CLI: cobra for the command line, testify for assertions, zap for logging, and the collector's own builder-generated code.

The buffer, the TODOs, and where the gaps are

The TODOs section is unusually informative, because it is a status board for the whole tool rather than a wish list, and it shows both what works and what does not.

For traces, display, filter, and trace information are all done. For logs, display, filter, log information, and showing logs related to a specific trace or span are done. For the metric stream, display, filter, metric information, and the chart types for Gauge, Sum, and Histogram are done.

The open items are specific. ExponentialHistogram and Summary charts are not implemented. There is no metric list yet, and no flexible chart with query and selectable dimensions, and no auto refresh chart, and no asynchronous chart rendering. Improve UI and add more keybindings are both open, and under Configurations only the port is done, with refresh interval and buffer size still to come.

The performance section shows what has been done, and it contains the answer to the durability question. Timer based refresh is done, and so is data rotation, with the current buffer size given as 1000 service root spans and logs.

That is the constraint to understand before you rely on this tool. The viewer keeps a thousand root spans and a thousand log lines in memory, and rotation discards what falls outside that. So it is a live window onto a service, not a store, and any question about a span from an hour ago will not be answered by it.

The configuration section confirms the same thing from the other side. The port is configurable, the refresh interval is not yet, and the buffer size is not yet either, which means the thousand item limit is currently fixed rather than a knob you can turn.

The build, the tests, and the clipboard caveat

The Makefile is short and follows the Go convention of a self-documenting help target.

The lint target checks that golangci-lint is present and then runs it over both the main tree and the tuiexporter directory. The test target runs go test with the race detector and TZ=UTC set, which is a careful choice, since a race in a tool that renders a live stream of telemetry is a race you want to see. The coverage targets add a profile and then render it as HTML.

The exporter has its own test targets, test-exporter and the two coverage variants, and the top level exporter test is invoked by running the same target with the directory changed, which is a tidy way to share one recipe. And there is a screenshot target that needs vhs driving a tape file to regenerate the documentation images, which is how the README screenshots stay current.

The clipboard is the one platform caveat, and it is stated clearly. The clipboard feature, the y key to copy log body, requires platform-specific tools. On Linux and Unix you need xclip or xsel installed. On macOS and Windows no additional tools are required. And the note is that if the clipboard tools are not available, the application will run normally but clipboard functionality will be disabled.

The container image is worth one more look because of how it is built. The builder stage is golang:1.24 with CGO_ENABLED=0 and GOOS=linux, building the binary, and the deploy stage is gcr.io/distroless/static-debian12 with the binary copied in and the user set to nonroot. A static binary into a distroless image with no shell and no package manager is a small, hard image, which suits a tool that is often run alongside other containers in a compose stack.

Editorial conclusion

Adopt otel-tui if you want to watch traces, metrics, and logs from a local instrumented service without standing up a full backend. Do not adopt it as a production observability store, because the README documents a fixed in-memory buffer. Verify first that the port your application already exports to is one of the enabled receivers, since Zipkin, Datadog, and DogStatsD are all off by default.

Frequently asked questions

What formats can otel-tui receive?

OpenTelemetry over OTLP on 4317 for gRPC and 4318 for HTTP, plus Zipkin traces on 9411, Datadog signals on 8126, and DogStatsD metrics on 8125. The Zipkin, Datadog, and DogStatsD receivers are off by default and enabled with --enable-zipkin and --enable-datadog.

How do I install otel-tui?

With brew install ymtdzzz/tap/otel-tui, with go install github.com/ymtdzzz/otel-tui@latest, from the Docker image ymtdzzz/otel-tui:latest, with nix develop github:ymtdzzz/otel-tui, from a release binary, or from source with go run ./... after cloning.

Is otel-tui a replacement for a full observability backend?

No. The data rotation keeps a current buffer of 1000 service root spans and 1000 logs, so it is a live window onto a service rather than a store, and the TODO list shows that refresh interval and buffer size are not yet configurable.

How is otel-tui built on the OpenTelemetry Collector?

The go.mod is generated by the collector's builder command and depends on the collector service, processor, connector, extension, confmap and component packages, along with contrib receivers for Datadog, Prometheus, StatsD, Zipkin and the JSON file receiver, so the ingestion protocols come from the collector rather than being reimplemented.

Can I point otel-tui at an existing Prometheus?

Yes, with the --prom-target option, which takes a repeatable list of target endpoints such as localhost:9000 or http://other-host:9000/custom/prometheus. It enables the Prometheus receiver with those scrape targets, rather than receiving a push protocol.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. ymtdzzz/otel-tui on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ymtdzzz-otel-tui.svg)](https://hysenlabs.com/projects/ymtdzzz-otel-tui)

Was this useful?