docs: update README for wizard, token versions, completion install
Release / release (push) Successful in 46s

This commit is contained in:
Sebastian Unterschütz
2026-05-23 13:31:08 +02:00
parent da3a280a43
commit 8fc7896b35
+53 -26
View File
@@ -17,7 +17,8 @@ netssh -p 2222 admin@app-server-03 uptime
- **Flexible IP resolution** — configurable chain of strategies: management subnet, primary IP, or named interface - **Flexible IP resolution** — configurable chain of strategies: management subnet, primary IP, or named interface
- **Interactive TUI** — fuzzy search with live NetBox queries and 300 ms debouncing (start with `netssh`, no arguments) - **Interactive TUI** — fuzzy search with live NetBox queries and 300 ms debouncing (start with `netssh`, no arguments)
- **Persistent cache** — successful lookups are cached to `~/.cache/netssh/hosts.json` for instant shell completion - **Persistent cache** — successful lookups are cached to `~/.cache/netssh/hosts.json` for instant shell completion
- **Shell completion** — tab-complete hostnames from the cache in zsh, bash, and fish - **Setup wizard** — interactive first-run onboarding; re-run anytime with `netssh configure`
- **Shell completion** — install without sudo via `netssh completion install`
- **Default SSH user** — set a fallback username once in config instead of typing it every time - **Default SSH user** — set a fallback username once in config instead of typing it every time
## Installation ## Installation
@@ -46,12 +47,27 @@ go build -o netssh ./cmd/netssh
## Configuration ## Configuration
Create `~/.config/netssh.yaml`: ### Interactive wizard
On first run (when no config exists), `netssh` automatically starts an interactive setup wizard.
Re-run it at any time to change settings without editing the file manually:
```sh
netssh configure
```
The wizard walks through NetBox connection, SSH defaults, resolver strategies, and cache TTL,
then saves to `~/.config/netssh.yaml`.
### Manual config
`~/.config/netssh.yaml`:
```yaml ```yaml
netbox: netbox:
url: https://netbox.example.com url: https://netbox.example.com
token: your-api-token-here token: nbt_your-api-token-here # v2 token (nbt_ prefix) recommended
token_version: 2 # auto-detected from token; 1 = legacy, 2 = nbt_
resolver: resolver:
# Strategies are tried in order; the first to return an IP wins. # Strategies are tried in order; the first to return an IP wins.
@@ -73,7 +89,19 @@ ssh:
default_user: admin # used when no user is specified on the command line default_user: admin # used when no user is specified on the command line
``` ```
Any value can be overridden with environment variables (`NETSSH_NETBOX_URL`, `NETSSH_NETBOX_TOKEN`, etc.) or will be read from the config file. Any value can be overridden with environment variables (`NETSSH_NETBOX_URL`, `NETSSH_NETBOX_TOKEN`, etc.).
### API tokens
NetBox supports two token formats:
| Format | Example | Notes |
|--------|---------|-------|
| v2 (recommended) | `nbt_abc123…` | Create in NetBox → Admin → API Tokens |
| v1 (legacy) | `abc123def456…` | Older format; still works, but v2 is preferred |
`netssh` auto-detects the version from the token prefix and stores it as `token_version` in the config.
A hint is shown during `netssh configure` if a legacy v1 token is entered.
## Usage ## Usage
@@ -146,28 +174,26 @@ Strategies are tried in the configured order; the first to succeed wins.
## Shell Completion ## Shell Completion
### zsh Install completion for the current user (no sudo required):
```sh ```sh
netssh completion zsh > "${fpath[1]}/_netssh" netssh completion install # auto-detects $SHELL
netssh completion install --shell bash
netssh completion install --shell zsh
netssh completion install --shell fish
``` ```
Or add to `.zshrc`: | Shell | Install path |
|-------|-------------|
| bash | `~/.local/share/bash-completion/completions/netssh` |
| zsh | `~/.zfunc/_netssh` |
| fish | `~/.config/fish/completions/netssh.fish` |
For zsh, make sure `~/.zfunc` is in your `fpath` (add to `~/.zshrc`):
```zsh ```zsh
source <(netssh completion zsh) fpath=(~/.zfunc $fpath)
``` autoload -Uz compinit && compinit
### bash
```sh
netssh completion bash > /etc/bash_completion.d/netssh
```
### fish
```sh
netssh completion fish > ~/.config/fish/completions/netssh.fish
``` ```
Completions are served from the local cache — no network request on every `<Tab>`. Completions are served from the local cache — no network request on every `<Tab>`.
@@ -179,12 +205,13 @@ go test ./... # run all tests
go build ./... # build all packages go build ./... # build all packages
``` ```
The test suite covers the cache, NetBox client (via `httptest`), IP resolver chain, and SSH argument parser. The test suite covers the cache, NetBox client (via `httptest`), IP resolver chain, SSH argument parser, config loading, and the setup wizard.
## How it works ## How it works
1. `netssh` checks whether the first argument is a known subcommand (`search`, `cache`, `completion`). If not, it enters SSH wrapper mode. 1. `netssh` checks whether the first argument is a known subcommand (`configure`, `search`, `cache`, `completion`). If not, it enters SSH wrapper mode.
2. It parses the SSH arguments to extract the destination hostname, handling all flags that consume an extra argument (`-p`, `-i`, `-J`, …). 2. On first run or when `netbox.url` is empty, the interactive setup wizard starts automatically.
3. It checks the local cache. If the entry exists and is within the TTL, it connects immediately. 3. It parses the SSH arguments to extract the destination hostname, handling all flags that consume an extra argument (`-p`, `-i`, `-J`, …).
4. Otherwise it queries NetBox (`/api/dcim/devices/` and `/api/virtualization/virtual-machines/` in parallel), runs the result through the resolver chain, and caches the IP. 4. It checks the local cache. If the entry exists and is within the TTL, it connects immediately.
5. It calls `syscall.Exec` to replace itself with `ssh`, substituting the hostname with the resolved IP. 5. Otherwise it queries NetBox (`/api/dcim/devices/` and `/api/virtualization/virtual-machines/` in parallel), runs the result through the resolver chain, and caches the IP.
6. It calls `syscall.Exec` to replace itself with `ssh`, substituting the hostname with the resolved IP.