22 Commits
Author SHA1 Message Date
Sebastian UnterschützandClaude Opus 5.5 396d489187 feat(multi): tmux keys to toggle broadcast and exclude single panes
In windows opened by netssh multi, prefix S toggles broadcast for all
panes and prefix e excludes the current pane (a pane-level
synchronize-panes off, shown as [SOLO] in the border) or includes it
again. netssh sync --pane does the same from a shell.

S and e are unbound in a default tmux (E would be "spread evenly").
netssh writes the bindings to a small tmux config and sources it, binds
a key only if the user's tmux.conf does not use it (netssh's own earlier
binding is refreshed), and the bindings act only in windows marked
@netssh. multi.sync_key and multi.solo_key change the keys or turn them
off (none); also in the configurator. zellij syncs whole tabs only, so
excluding a pane is tmux-only.

testenv: the render test presses the keys through the xterm client
(send-keys -K) and checks [SOLO], that broadcast skips the excluded
pane, that S toggles, and that other windows are unaffected. The client
gets GNU grep: BusyBox grep -oF counted only one match per line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-14 13:32:32 +01:00
Sebastian UnterschützandClaude Opus 5.5 699b9469b6 test: check what a real terminal renders for multi, zellij, and the TUI
tests/16-render.sh runs tmux, zellij, and the TUI in xterm on Xvfb,
takes screenshots, and reads them back with tesseract: remote prompts
in all panes, borders and titles with the hosts, [SYNC] appearing and
disappearing, panes side by side, broadcast output in every pane and
input in one pane only without it, windows split by panes_per_window,
the status bar, and TUI marks. Screenshots stay in testenv/.artifacts.

OCR reads three preprocessing variants (plain, stretched for dim gray,
brightest channel for colored text) and normalizes characters that
DejaVu Sans Mono makes ambiguous (1/l, C/().

The screenshots showed tmux cutting the session name in the status bar
to "[netssh-pv"; netssh multi now widens status-left-length for its
own session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-14 13:14:34 +01:00
Sebastian UnterschützandClaude Opus 5.5 a31aab4110 feat: netssh multi — several hosts side by side in tmux or zellij
netssh multi opens one pane per host in a tmux window or zellij tab.
Hosts come from names, tag:TAG (NetBox and static hosts), cluster:NAME
(NetBox virtualization clusters; devices by default, --kind vm|all),
and groups from the config (@name, nested, with cycle detection).
Every pane runs netssh HOST, so lookup, rules, and jump hosts apply.

- tmux: a new window inside tmux, else a new session that is attached;
  tiled layout, pane borders with the host and a [SYNC] marker.
- zellij: a generated grid layout; a new tab inside zellij, else a new
  session.
- --sync broadcasts typing to all panes; netssh sync toggles it in the
  current tmux window or zellij tab.
- TUI: Space marks hosts, Ctrl+A marks all, Enter opens them together.
- Configurator: multiplexer, panes per window, groups.

NetBox SearchAll gains a cluster filter (name to cluster IDs per
instance), and cache entries keep the host's cluster for completion
and an offline fallback. Panes skip the 24-hour background refresh
(checked once by multi) and get HOME/XDG paths but no NETSSH_* values,
which would expose tokens in the process list.

testenv/tests/15-multi.sh checks real tmux and zellij sessions,
including a broadcast command arriving on all three cluster nodes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-14 12:45:05 +01:00
Sebastian UnterschützandClaude Opus 5.5 dbb99bdded test: add a local Docker test environment for all features
testenv/ starts two real NetBox 4.7 instances (v2 and v1 token), SSH
targets on public, mgmt, and prod networks, a jump host, an IPv6-only
host, a static host, and a client with ssh, sftp, scp, tmux, zellij,
bash, zsh, and fish. A seed script fills NetBox through the REST API.

141 end-to-end checks cover cache and refresh filters, connecting,
all resolver strategies, multiple instances, shortcuts and rewrites,
SSH options and rules, static hosts, sftp/scp incl. IPv6 and jump
hosts, tunnels, local notes and NetBox comments, completion and shell
hooks, the TUI (driven through tmux), the configurator, and uninstall.

Local only: testenv/up.sh, test.sh, shell.sh, down.sh. Not part of
CI/CD.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-14 12:30:24 +01:00
Sebastian UnterschützandClaude Opus 5.5 a950a82552 feat: hostname resolver strategy and static hosts
Add the hostname resolver strategy. It connects by the NetBox name
instead of an IP, with resolver.hostname_domain appended to names
without a dot. Its position in the chain decides whether it is always
used or only as a fallback (e.g. [primary_ip, hostname]); names that
are not valid DNS hostnames fall through to the next strategy.

Add static hosts under hosts: for machines that are not in NetBox,
with address, user, port, tags, and their own SSH options. They are
checked before NetBox (by name or shortcut), never expire, survive
cache refresh and clear, and work without any NetBox configured. The
cache overlays them after every load and stores only their last use,
so they appear in completion, aliases, the TUI and its recent list.
SSH options merge global, static host, then rules; rules can match
kind: static. Manage them with netssh hosts list|add|remove and in
netssh configure, which can now also continue without NetBox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 23:46:13 +01:00
Sebastian UnterschützandClaude Opus 5.5 2be9f19cc2 docs: expand README with reference, recipes, and troubleshooting
Add a table of contents, a quick start, a full configuration reference
with defaults, the environment variables, a table of files and
directories, a command overview, details on rule matching and how
option layers combine (with real --dry-run output), recipes, a
troubleshooting table, and the project layout. Update How it works for
sftp, scp, tunnel, and forwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 23:30:23 +01:00
Sebastian UnterschützandClaude Opus 5.5 b7fa71fe45 feat: sftp, scp, and named port forwards
Add netssh sftp and netssh scp. Both resolve the host like a connection
does (cache, shortcuts and rewrites, instance/host, default user and
port, SSH options and rules, --jump/--no-jump, --dry-run) and get shell
completion. The per-client flag tables handle the differences from ssh:
the port is -P, -l is a bandwidth limit (the default user goes in as
-o User=), and IPv6 addresses are bracketed in host:path. All remote
scp operands must name the same host.

Add named port forwards under ssh.forwards (global, per instance, per
rule; a more specific layer replaces a forward of the same name),
netssh tunnel HOST NAME|SPEC... (ssh -N with ExitOnForwardFailure) and
netssh --forward NAME. Specs such as 8080:localhost:80 work without
configuration. Forwards are editable in netssh configure and completed
in the shell; the TUI opens SFTP with ctrl+o and a tunnel with ctrl+t.

Host resolution moves out of runSSHWrapper into resolveTarget, shared
by ssh, sftp, scp, tunnel, and the TUI.

Options added by netssh are now inserted before the first operand or
"--": after "--", ssh read them as the destination, and scp stops
reading options at the first operand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 23:05:07 +01:00
Sebastian UnterschützandClaude Opus 5.5 878701aba7 feat(shortcuts): regex rewrite rules for host shortcuts
shortcuts.rewrites applies regex replacements after the domain suffix
is stripped, e.g. ^([a-z]+)[0-9]+- -> $1 turns fsn1-bx1.hoster.de into
fsnbx1. The shortcut works for connecting (cached hosts), shell
aliases, and Tab completion, where it is offered when the full name
does not match the typed text. Rules are editable in netssh configure,
and netssh alias --test HOSTNAME shows a name's shortcut and the cached
hosts it matches.

The shortcut lookup only ran when domains or strip_hyphens were set;
it now also runs for rewrite-only configurations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 22:42:13 +01:00
Sebastian UnterschützandClaude Opus 5.5 d51c040d9f feat(configure): edit every config option in the configurator
After the NetBox instances, netssh configure now opens a menu with all
sections: SSH defaults, global SSH options (jump host, host key
checking, target, address family, extra args, -o options), SSH rules,
resolver & cache (including the cache file), shortcuts & command alias,
and completion.max_results. SSH options can also be set per instance.

The wizard rebuilt the config from its own fields, so re-running it
dropped global SSH options, ssh.rules and completion.max_results from
the file. It now edits a copy of the loaded config, and save validates
SSH options and rules before writing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 22:42:13 +01:00
Sebastian UnterschützandClaude Opus 5.5 091f5cc518 fix(completion): offer unique hostnames without instance prefix
bash (and zsh without a matcher) only accept candidates that start with
the typed text, so "fsn1-bx1<Tab>" found nothing when every candidate
was qualified as "prod/…". Hostnames that exist in only one instance
are now offered bare; names present in several instances stay
qualified. Connecting to a bare name still checks every instance for
ambiguity, so the connection behavior is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 11:44:54 +01:00
Sebastian UnterschützandClaude Opus 5.5 6711b610f1 docs: document SSH options, uninstall, and zsh completion for v0.0.21
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 11:23:31 +01:00
Sebastian Unterschütz 7f53b90266 feat: search multiple NetBox instances with isolated host identities
Release / release (push) Successful in 5m16s
2026-10-27 23:14:42 +01:00
Sebastian Unterschütz fa7446e5f7 Fix host resolution and concurrent cache updates 2026-10-27 22:23:59 +01:00
Sebastian Unterschütz 34503de68e Enable shell completion for configured command aliases
Release / release (push) Successful in 5m8s
2026-10-27 19:19:42 +01:00
Sebastian Unterschütz fa4509038b Package installer in releases and expand Renovate dependency updates
Release / release (push) Successful in 4m41s
2026-10-27 18:38:54 +01:00
Sebastian Unterschütz 4b28d441b0 Improve installer updates and dependency checks and add command aliases
Release / release (push) Successful in 7m57s
2026-10-27 18:10:44 +01:00
Sebastian Unterschütz 12cc64fdd9 Add local and NetBox server notes and improve reliability
Release / release (push) Successful in 6m52s
2026-10-27 17:51:59 +01:00
Sebastian Unterschütz fa646f25a6 feat: add alias file generation and management for shell hooks
Release / release (push) Successful in 49s
- **Aliases**: Generate shell alias files (`aliases.sh` for bash/zsh, `netssh.fish` for fish) from cached hosts. Regenerate on each shell startup and cache refresh to keep aliases updated.
- **Hooks**: Extend shell hook functionality to include alias file support. Install and uninstall commands updated for bash, zsh, and fish.
- **Tests**: Add unit tests to verify alias file generation, path resolution, and idempotent hook installation.
- **Docs**: Update README with instructions for alias file usage, installation, and relation to hooks.
2026-05-27 23:08:30 +02:00
Sebastian Unterschütz 7c902cab3a feat: introduce shortcuts and shell hook support
Release / release (push) Successful in 50s
- **Shortcuts**: Add hostname normalization with domain stripping and hyphen folding. Include alias generation for cached hosts.
- **Shell Hook**: Automate 24h cache refresh trigger with shell startup hook. Add install/uninstall commands for bash, zsh, and fish.
- **Wizard**: Extend setup wizard to configure shortcuts (domains, hyphen stripping) and default SSH port.
- **Cache**: Add `GetByShortcut` for resolving hosts via normalized shortcuts. Implement `NeedsRefresh` / `SetRefreshed` logic for refresh timestamps.
- **Tests**: Comprehensive unit tests for shortcuts, hook installation, cache refresh, and alias generation.
- **Docs**: Update README with shortcuts, shell hook, and default SSH port configuration.
2026-05-27 22:53:24 +02:00
Sebastian Unterschütz d127a3b957 feat: enhance host resolution, filtering, and cache management
Release / release (push) Successful in 49s
- **Strategies**: Add resolver strategy input validation and parsing in setup wizard. Support comma-separated input with known strategy mapping.
- **Client**: Extend Search and SearchAll to include kind and tag filters. Add pagination for full cache refresh handling large datasets.
- **Cache**: Introduce `RecentlyUsed` and `MarkUsed`. Persist `LastUsed` timestamps for entries.
- **TUI**: Add recent hosts view, tag/kind filters, and inline editor for user/port override.
- **Tests**: Comprehensive unit tests for new features, including strategy validation, cache behavior, and client filtering.
- **Docs**: Update README with new TUI features and cache subcommands.
2026-05-23 17:06:24 +02:00
Sebastian Unterschütz 8fc7896b35 docs: update README for wizard, token versions, completion install
Release / release (push) Successful in 46s
2026-05-23 13:31:08 +02:00
Sebastian Unterschütz 8ef4bbec16 Add core modules (SSH args parser, cache, resolver, NetBox client) with tests
Release / release (push) Failing after 51s
2026-05-23 12:38:41 +02:00