TL;DR: I built ntomb – The Necromancer’s Terminal,
a Halloween-themed TUI that turns boring TCP connection lists into an undead graveyard for a single process, using Kiro in a spec-first + vibe coding workflow.
- 🔗 GitHub: ntomb – The Necromancer’s Terminal
- 🎥 Demo video (3 min): Kiroween 2025 submission demo
What is ntomb?
As an SRE/DevOps engineer, I stare at ss, netstat, and /proc way too often.
They’re powerful, but when you’re debugging a single long-running process (like nginx, a Java service, or some internal API), the experience is:
- noisy
- hard to “feel”
- and definitely not spooky enough for Kiroween.
So for Kiroween 2025, I built ntomb – The Necromancer’s Terminal:
A Linux terminal UI that visualizes TCP connections for one process
as an undead graveyard of remote hosts and “ghost” connections.
Instead of a flat list of sockets, ntomb gives you a split TUI:
- Left: a graveyard of tombstones, one per remote host
- Right: details for the selected host (ports, states, counts)
- Top / bottom: header + status, with process info and update hints
It’s a small tool, but it tries to answer a very simple question:
“What is this process talking to right now,
and what does its network life feel like?”
A quick visual tour 👀
(I’ll insert real screenshots on dev.to — placeholders below.)
1. Main graveyard view
- Each tombstone on the left is a remote host.
- Selecting a host shows aggregated connection info on the right.
- Colors and symbols give you a quick sense of “how alive” things are.
2. Host details panel
For a selected host, ntomb shows:
- number of connections
- breakdown by state (ESTAB, TIME_WAIT, etc.)
- ports and maybe extra metadata (depending on snapshot)
3. Process-first view
ntomb is process-centric:
- you point it at a PID or process name
- it tracks the connections for that process only
- you can keep that view open while you send traffic or run tests
Why I built this (and why it fits Kiroween)
On paper, ntomb is:
- a tiny SRE utility
- a bit of network observability
- and a lot of terminal cosplay
For the hackathon, I submitted it to the Costume Contest:
“Build any app but show us a haunting user interface that’s polished and unforgettable.”
ntomb tries to be exactly that:
- It re-skins a familiar debugging workflow into a graveyard metaphor.
- It stays practical (real data from
ssor/proc). - But it adds enough Halloween flavor that you enjoy leaving it open.
This is something I’d actually keep in my toolbox after the hackathon—
just with a slightly less cursed theme in production. Maybe.
Stack & architecture
Under the hood, ntomb is intentionally simple:
- 🦀 Language: Rust (TUI-friendly, fast, great ecosystem)
- 🧱 TUI framework: a Rust terminal UI library (panel layout, events, rendering)
- 🌐 Data source: system-level networking info (
ss,/procor similar) - 🔁 Update loop: periodic snapshots + diffing to update the “graveyard”
The architecture is split into a few clear parts:
-
Data collection
- Run
ss/ read/procfor a specific PID - Parse into a normalized
Connectionmodel - Group by remote host and state
- Run
-
Domain model
- A
Hostaggregates manyConnections - Each host tracks: address, counts, and some derived metrics
- A
-
TUI layer
- Header (process info)
- Left panel (hosts list)
- Right panel (details)
- Keybindings for navigation / refresh
This split becomes really important when we talk about how I used Kiro.
Building ntomb inside Kiro
I didn’t just write ntomb in a regular editor and occasionally ask an LLM for help.
I tried to go all-in on Kiro and its spec-driven + vibe coding workflow.
Spec-driven development
Instead of one huge spec, I created multiple .kiro/specs/... files:
-
ntomb-core.md– core concepts:- what a connection is
- how to group them by host
- what fields and states I care about
-
ntomb-ui-layout.md– TUI structure:- panels (header, graveyard list, detail panel)
- minimum sizes and layout rules
- keybindings and navigation behavior
-
ntomb-themes.md– vibes & theming:- color tokens for “graveyard”, “ghost”, “danger”
- symbols/emojis allowed
- constraints so it stays readable in real terminals
Each spec wasn’t just a wishlist—it described:
- behavior
- constraints
- examples of what “good” looks like
From there, Kiro could generate and refactor code in a way that respected those specs.
Vibe coding on top
Once the structure felt right, I switched into more vibe coding:
- brainstorming metaphors:
- “How can we make this feel more like a necromancer’s dashboard?”
- “What should a ‘ghost connection’ look like?”
- polishing UX details:
- naming (tombstones, graveyard, ghosts)
- panel copy and status messages
- small layout tweaks to improve readability
This was the fun part:
with the big shapes locked by specs, I could safely tell Kiro:
“This looks too boring. Make it weirder,
but don’t break the layout or the data model.”
How Kiro actually helped (beyond ‘autocomplete but bigger’)
A few concrete ways Kiro made a difference:
1. TUI layout scaffolding
Designing a multi-panel TUI with decent ergonomics is non-trivial:
- header + status
- left list + right detail panel
- proper handling of resize, scroll, and selection
From my specs, Kiro generated an initial layout with:
- data structures for the UI state
- an event loop
- keybindings and focus management
I would never ask a generic model to do this in one shot—
but with clear specs, Kiro’s output was surprisingly solid.
2. Data model + parsing glue
Turning ss output or /proc into a nice internal model is:
- boring
- easy to get subtly wrong
- highly repetitive
With a spec that defined Connection and Host types, Kiro helped:
- write the parsing boilerplate
- keep field names & types consistent
- refactor when I changed the model shape
I still reviewed everything, but it took away a lot of tedious work.
3. Staying in a tight loop with hooks
I also used Kiro hooks to automate small workflows, like:
- grabbing fresh connection snapshots into JSON files
- running
cargo fmt+cargo testafter bigger refactors - rebuilding and running the TUI with one command
This meant I could stay inside Kiro for much longer stretches:
spec → code → run → tweak → repeat
instead of constantly bouncing between editor, terminal, and browser.
Spec-driven vs vibe coding (for real)
Kiroween asks a lot about “vibe coding,” but for ntomb,
the real magic was the combination:
-
Spec-driven:
- locked in architecture
- made Kiro’s behavior predictable
- safe for larger refactors
-
Vibe coding:
- perfect for UX, naming, and theming
- fun for exploring weird ideas
- low risk once the structure was stable
If I had to summarize:
Specs gave me confidence.
Vibes gave me personality.
Together, they let me ship something small but cohesive in a short hackathon window.
What I’d like to add next
If I keep working on ntomb after Kiroween, here’s what’s on my list:
- multiple processes / split views
- basic filters (states, ports, subnets)
- simple latency or error indicators
- a less Halloween-intense theme for everyday use
And of course… even more over-engineered spooky modes for next Halloween. 🧟♀️
Closing thoughts
Kiroween was the perfect excuse to:
- take a boring but important part of my job (connection debugging),
- push it through a necromancer / graveyard UI filter,
- and really lean into spec-driven development with Kiro.
If you:
- live in a terminal,
- debug network issues a lot,
- and like the idea of your tools wearing costumes,
then I hope ntomb feels like something you’d actually run during an incident…
even if you have to pretend you’re not enjoying the vibes too much.
Thanks for reading — and if you have ideas or feedback,
feel free to open an issue or PR on GitHub:



Top comments (0)