Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions PRODUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# NetsCLI — product contract

Written from what the repository already evidences (README, `docs/`, the
site copy, and the shipped interfaces), with the user ordering and success
criteria supplied by the maintainer. Claims that are **inferred** rather
than stated somewhere in the repo are marked `[inferred]` so they are easy
to correct rather than easy to mistake for settled.

## Purpose

Answer questions about a local network — what is on it, what is reachable,
what is listening — and return the answer as structured data rather than
text a human has to read and re-type.

The origin, from the README, was narrower: driving those questions from an
AI agent, which existing tools make awkward ("half a dozen CLI invocations,
brittle output parsing, no shared context"). The MCP server was built
first, then the TUI, CLI, and desktop app, all over one Rust core
(`netscli-core`).

**A tension worth recording.** The README and the website both lead with
the agent/MCP story, but the maintainer ranks agent-driven users *last* of
four (see Users). The code's history explains the emphasis; the priorities
below are what the product is actually for now. Where the two disagree,
this document is the current intent and the README is the origin story.

## Users

In priority order, as stated by the maintainer:

1. **Specialists** — people whose job includes networks, who know what an
ARP table is and will notice when a tool lies about one.
2. **Operations** — people running or supporting infrastructure, who need a
quick, trustworthy answer during work that is not primarily about
networking.
3. **Anyone on a home or office LAN** — non-specialists who mostly want to
see what is connected. `[inferred]` This is the group the desktop app
serves most directly; the CLI and TUI assume more.
4. **Agent-driven developers** — wiring `netscli serve` into an MCP client
so an agent can answer network questions without parsing CLI output.

The ordering matters for conflicts: when a change would make the desktop
app friendlier at the cost of a specialist's accuracy, the specialist wins.

## Success

All four of the following, as stated by the maintainer:

- **Agents answer network questions unaided.** An MCP client resolves a
real question — "what just joined the network", "is port 22 open on
192.168.1.42" — in one exchange, without correction.
- **Downloads and installs grow.** Adoption through GitHub releases and the
package managers is a signal that it is useful beyond one machine.
- **It is the tool the maintainer personally reaches for**, in place of
whatever came before.
- **No wrong answers.** The scanner never silently reports something false.

The last one is not decoration. The 0.3.1 release exists because three
separate faults *reported success while doing nothing*: ping claimed total
loss against the host's own address, a fresh install ran one probe at a
time while appearing configured for 256, and `arp --clear` printed "ARP
table cleared" after clearing nothing. A wrong answer delivered
confidently is the failure mode this product most has to avoid, because
every surface above the core inherits it.

## MVP

Already shipped and in the released product:

- One core library (`netscli-core`) with scan, ping, traceroute, discover,
sweep, DNS/reverse/mDNS, ARP, and interface enumeration.
- Four interfaces over it: CLI (`netscli`), terminal UI, desktop app
(Tauri), and MCP server (`netscli serve`, nine tools by default).
- Structured output — `--json` on the CLI, typed results across the MCP
boundary — as the primary contract, with human-readable text as a view
of it rather than the source of truth.
- Cross-platform binaries and installers for Linux, macOS, and Windows.

Out of scope for the current line `[inferred, from what the code does not
attempt]`: exploitation or intrusion of any kind, credentialed access to
discovered hosts, and continuous monitoring. The tools answer questions at
a moment in time.

## Constraints

- **Rust 1.96**, one workspace, crates versioned together but not
inheriting a workspace version — each manifest carries its own, and a
release has to touch all of them plus `package.json` and
`tauri.conf.json`. See `docs/PUBLISHING.md`.
- **Privilege boundaries are real and platform-specific.** Raw ICMP needs
administrator rights on Windows; clearing the ARP table needs them
everywhere. Where a capability is unavailable the product must say so and
fail, not degrade quietly into a different answer.
- **The MCP surface is a trust boundary.** `server/targets.rs` restricts
what an agent may scan and `server/limits.rs` caps what a scanned host can
put into a model's context. Both exist so a prompt-injected model cannot
point the scanner at strangers, and neither may be relaxed for
convenience.
- **crates.io publication is irreversible** — a version number, once used,
is spent whether or not the release was any good.
- Network safety limits (concurrency caps, target policy) are deliberate
and are not to be widened to make something faster.
4 changes: 2 additions & 2 deletions apps/netscli-gui/src/styles/tokens.css
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ button {
--border-strong: #343b49;
--text-primary: #e4e7ef;
--text-secondary: #9aa2b3;
--text-muted: #667085;
--text-muted: #7a8499;
--mint: #3eddb0;
--mint-deep: #0aae7a;
--focus-ring: color-mix(in srgb, var(--mint), transparent 35%);
Expand Down Expand Up @@ -145,7 +145,7 @@ button {
--border-strong: #c2cad6;
--text-primary: #17202b;
--text-secondary: #4d5a6b;
--text-muted: #7b8797;
--text-muted: #687484;
--mint: #008a63;
--mint-deep: #007052;
--focus-ring: color-mix(in srgb, var(--mint), transparent 24%);
Expand Down
65 changes: 65 additions & 0 deletions design-direction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Design direction — NetsCLI desktop app

Scope: the Tauri desktop app in `apps/netscli-gui`. The marketing and docs
site (`site/`) is a separate surface with its own Starlight-derived styling
and is not covered here.

Reconstructed from the shipped implementation — `src/styles/tokens.css` and
the components that consume it — rather than from an interview held before
the design existed. Anything not directly readable from the code is marked
`[inferred]`.

## Interview

**What is this, in one line?**
A desktop window over the same Rust core the CLI and TUI use, for when you
want to see what is on the network without opening a terminal.

**Who is looking at it?**
Per `PRODUCT.md`, specialists first and non-specialists third. The app is
the surface most used by the non-specialist group, but it is not allowed to
buy their comfort with a specialist's accuracy. `[inferred]` — this follows
from the stated user ordering rather than from a design note.

**What should it feel like?**
A terminal tool that happens to have a window: dense, quiet, and quick to
read, rather than a consumer app with generous whitespace. Evidence: the
compact control heights (tab strip 38px, status bar 27px), the monospace
treatment of commands and addresses, and the CLI command strip under the
results showing the equivalent `netscli …` invocation for whatever the UI
just did.

**Colour.**
Dark by default, with a light theme defined in the same token block. Near
-black backgrounds layered by elevation (`--bg-body` `#0d1015` → `--bg-base`
`#181c24` → `--bg-elevated` `#20242d`), low-contrast borders
(`--border-subtle` `#2a303b`), and a single mint accent (`--mint` `#3eddb0`)
carrying interaction and success. Cyan (`#1edcff`), red (`#ef4456`) and
amber (`#f5a524`) are reserved for state, not decoration.

Every colour is a token on `.container`; components reference tokens, never
literals. This is enforced by convention rather than by a checker
`[inferred]` — no lint rule for it exists in the repo.

**Type.**
Inter (with a Segoe UI / system fallback) for interface text; Cascadia Code
/ JetBrains Mono for anything the user could paste into a shell — commands,
IPs, MACs, ports. The split is semantic: monospace means "this is literal".

**Density and hierarchy.**
Results are tables, and the table is the primary object on screen; the form
above it and the detail pane below it are supporting. Row selection,
keyboard navigation (arrows, Home/End, Ctrl+A, shift-range) and multi-select
are first-class, because the specialist user copies rows out.

**Motion.**
Minimal and functional — progress during an operation, a toast that
auto-dismisses. No decorative animation. `[inferred]` from the absence of
any transition longer than ~120ms in the stylesheets.

**What it must never do.**
Present a result as certain when the underlying probe failed. The error
strip is unconditional and not preference-gated for this reason, and
completion toasts were deliberately narrowed to background tabs only —
announcing what is already on screen trains people to ignore the messages
that matter.
36 changes: 36 additions & 0 deletions design-tokens.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"dark": {
"surface-base": "#181c24",
"surface-body": "#0d1015",
"surface-elevated": "#20242d",
"surface-input": "#11141a",
"surface-selected": "#203738",
"border-subtle": "#2a303b",
"border-strong": "#343b49",
"text-main": "#e4e7ef",
"text-secondary": "#9aa2b3",
"text-muted": "#7a8499",
"accent": "#3eddb0",
"accent-deep": "#0aae7a",
"info": "#1edcff",
"danger": "#ef4456",
"warning": "#f5a524"
},
"light": {
"surface-base": "#f8fafc",
"surface-body": "#eef1f5",
"surface-elevated": "#ffffff",
"surface-input": "#ffffff",
"surface-selected": "#dff7ef",
"border-subtle": "#d7dde6",
"border-strong": "#c2cad6",
"text-main": "#17202b",
"text-secondary": "#4d5a6b",
"text-muted": "#687484",
"accent": "#008a63",
"accent-deep": "#007052",
"info": "#0476a8",
"danger": "#c6293d",
"warning": "#a96700"
}
}
Loading