Tepegöz — Unified Local Development Observability
By Emin Can Başkaya
2026-04-22
Project
A single-binary daemon + TUI that collapses the scattered state of a working developer’s machine into one screen. Processes, Docker containers, port bindings, SSH fleet, and active Claude Code sessions, all owned by one daemon and surfaced through a client-agnostic wire protocol. Built in Rust, MIT/Apache dual-licensed, zero telemetry, zero auto-update, fully local.
The problem it exists to solve
A working dev environment today is half a dozen tools that don’t know each other exist. A terminal multiplexer, Docker Desktop, lsof in a scratch window, two SSH sessions to staging and dev, a netstat left open from an hour ago. Port conflicts surface as confusing connection refusals instead of a clean name collision. Containers die silently and the first signal is a downstream timeout. Every remote machine is a context switch that costs the thread you were holding. The fragmentation is the product; nobody sat down and designed it, it accumulated.
Tepegöz is the deliberate alternative: one eye, total visibility.
Architecture
Daemon-client split
One daemon owns all state. The TUI is a client. So is every future interface — phone app, web client, AI query layer. The daemon doesn’t care which client is connected or whether any client is connected at all. Kill the TUI, reopen it, nothing is lost. This is the architectural choice that makes every subsequent feature easier: remote access, multiple simultaneous views, scripting, mobile notifications, all become “another client on the wire” rather than features that require rewriting the core.
Single binary, zero configuration
tepegoz daemon and tepegoz tui and you’re looking at your system. The first-run layout isn’t a default to configure away from — it’s the answer to what a developer actually needs to see. Configuration is a failure mode, not a feature.
Observability scope
PTY-managed terminal sessions with focus state, Docker container lifecycle and port mapping, system-wide port bindings with conflict detection (the :9229 node (pty#2) ⚠ dup line in the layout is the whole thesis — a conflict surfaced as a name collision, not as a confusing error downstream), SSH fleet health with process counts and reachability, and Claude Code session state across multiple concurrent workflows.
Engineering choices worth flagging
Rust for the daemon
Not because Rust is fashionable, but because a long-running process that owns terminal state, network sockets, SSH multiplexing, and child process lifecycles needs to not crash and not leak. The alternatives (Go, Node, Python) all make tradeoffs that matter for this specific shape of system — Rust’s ownership model plus its async ecosystem (tokio) is the right fit for a daemon that has to be boring and reliable for days at a time.
Wire protocol before second client
v1 ships with just the TUI, but the daemon-client split is already real. The phone app in v2 isn’t a new codebase; it’s a new client against the same protocol, with zero daemon changes. This is the difference between “added a feature” and “designed for the feature.” Most tools in this space skip this step and regret it when the first platform expansion request arrives.
No telemetry, no auto-update, everything local
These aren’t marketing points — they’re architectural commitments that shape every subsequent decision. A tool that phones home has to handle network failures; one that doesn’t, doesn’t. A tool that auto-updates has to handle version skew between daemon and client; one that doesn’t, doesn’t. The simplicity compounds.
The v3 direction
“AI god query — one prompt orchestrates actions across the entire fleet” is the payoff of the daemon-owns-state architecture. Because the daemon already has unified visibility across local processes, containers, ports, and remote machines, adding a prompt layer on top isn’t a new integration — it’s a query interface to state that already exists in structured form. This is the right sequence: build the ground truth first, layer intelligence on top second. The reverse order is how most “AI for devops” products end up as demoware.
The name
Tepegöz is the cyclops from the Book of Dede Korkut, the foundational epic of the Oghuz Turks. Tepe is forehead, göz is eye — the eye at the top. In the epic, Tepegöz is invulnerable to conventional weapons and has to be outsmarted rather than overpowered. The name carries the product: one eye, total visibility, and the thing you deal with by being cleverer than it rather than by brute force.
What this demonstrates
Systems-level product thinking in Rust. Willingness to build infrastructure instead of wrappers. An eye for the architectural decisions that determine whether a project can grow (daemon-client split, wire protocol first, no telemetry) versus projects that accumulate features until they collapse under their own weight. Personal products built with the same discipline as commercial ones.
Stack
Rust (tokio async runtime, ratatui for the TUI, daemon process management), native Docker API integration, system-level port and process introspection, SSH multiplexing, cross-platform support for macOS and Linux.
Status
v1 in active development. Single binary, daemon + TUI, local macOS and Linux targets. v2 (mobile and web clients over the existing wire protocol) and v3 (AI-driven fleet orchestration) on the roadmap.
License
MIT / Apache 2.0 dual.