Kinjo
Browse local DNS-SD services, filter them, and run custom actions from a terminal UI.
What’s it for?
Avahi, the common Linux implementation of Bonjour / mDNS / DNS-SD, allows services to be published and discovered on a local network. Kinjo lets you browse discovered services, filter and group them, and launch configured actions for a selected service — all without leaving the terminal.
kinjo
For development or a quick look without a running Avahi setup:
kinjo --fake-discovery
Install
Homebrew (macOS and Linux):
brew install abbyssoul/abyss/kinjo
Debian / Ubuntu, from the latest GitHub release:
sudo apt install ./kinjo_*_amd64.deb
Cargo, from crates.io:
cargo install kinjo
From source:
git clone https://github.com/abbyssoul/kinjo.git
cd kinjo
cargo install --path .
How it works
Kinjo has three deliberately decoupled parts: a discovery backend that finds DNS-SD/mDNS records on the network, a small rules engine that matches services against user-defined commands, and a terminal UI that ties them together. Each part sits behind a trait, so it can be swapped or extended without touching the other two.
Two discovery backends, and room for more
Discovery is pluggable:
mdns-sd(default) — a pure-Rust backend built on themdns-sd-discoverycrate. A single browser enumerates every service type on the link via the native DNS-SD meta-query, so it needs nothing beyond network access.zeroconf— talks to the system Avahi daemon on Linux viazeroconf-tokio. It’s opt-in (cargo install kinjo --features zeroconf) since it needs the Avahi client headers to build, but it’s handy if you already runavahi-daemonand want Kinjo to use it directly.
Both backends implement the same Discovery trait and emit the same Entry
type, which is the only contract the rest of the app depends on. That seam is
intentional — a static file, an SSDP/UPnP browser, or any other service
source could be dropped in as a third backend without changing the rules
engine or the UI.
Configurable keybindings
The defaults follow Vim-style conventions (j/k to move, / to filter,
enter to run an action, ? for help — see the full list in the
README), but every built-in UI
command can be rebound. Overrides live in a TOML file at
$XDG_CONFIG_HOME/kinjo/keybindings.toml (falling back to
~/.config/kinjo/keybindings.toml), so you can move to arrow keys, Emacs
bindings, or whatever fits your muscle memory. See
docs/keybindings.md
for the complete reference and examples.
Extending it through commands
The part of Kinjo that matters most is the command system. Discovered
services carry structured fields — name, type, domain, hostname, address,
port, and TXT record values — and a command file matches on those fields to
decide what actions are available for a given service. Nothing about the
match logic or the action it triggers is hardcoded into the app: it’s all
data, read from $XDG_CONFIG_HOME/kinjo/commands/*.toml and reloaded live on
SIGHUP, no restart needed.
A command file is a match predicate plus a shell command template:
[metadata]
name = "ssh"
description = "SSH into a service"
requirements = ["ssh"]
[match.service_type]
equals = "_ssh._tcp"
[action]
description = "SSH into the selected service"
command = "ssh {hostname}"
mode = "execute"
Predicates support equals, contains, and regex against any service
field (including txt.<key>), and the same fields interpolate into the
command line, so xdg-open http://{hostname}:{port} or ssh {hostname} are
a few lines away. Multiple commands can match the same service — Kinjo shows
a picker when they do, and asks which instance to use if the fields it needs
are ambiguous. Full syntax, overlay rules, and more examples are in
docs/actions.md.
Because actions are just commands matched against whatever your network
already advertises, Kinjo works well as a jumping-off point for home labs:
today it’s mostly SSH and web UIs, but the same mechanism could just as
easily launch a VNC viewer against a discovered _rfb._tcp service, open a
psql/mysql client against a discovered database instance, tail logs on a
matching host, or trigger any other local tool — without a single line of
Rust. If your home network already broadcasts its services over mDNS, Kinjo
can already be their launcher; it’s mostly a matter of writing the right
command files.
Try it and tell me what you think
Kinjo is young and actively developed, and the command system is deliberately
open-ended — if you run a home lab with a pile of self-hosted services, I’d
genuinely like to hear what actions you end up writing, what’s awkward about
the command format, and what discovery backend you wish existed. Grab it with
kinjo --fake-discovery to poke around without any setup, then point it at
your real network:
kinjo
Bug reports, feature requests, and command file examples are all welcome on the issue tracker — and if you build something cool with it, I’d love to know.