0ecdffbbbd
- README: build-from-source requires Go 1.25+ (matches go.mod), was 1.23+. - docs/v2-report.md: the in-app SFTP file browser was never built (no `t` action, no xfer/sshx/browser packages, pkg/sftp not a dependency). Cut the false "shipped" claims and moved it into the Deferred section. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
98 lines
4.9 KiB
Markdown
98 lines
4.9 KiB
Markdown
# dial — v2 report
|
|
|
|
A status report on `dial` after the v2 pass, written to be self-contained so it
|
|
can be pasted into a fresh chat for brainstorming. No codebase access needed to
|
|
follow it. (For the original tool, see the v1 REPORT.md; this focuses on what v2
|
|
added and where it stands.)
|
|
|
|
## What dial is (one paragraph)
|
|
|
|
`dial` is a fast, cross-platform command-line SSH tool. Its core is an
|
|
interactive host picker: it reads `~/.ssh/config`, shows a clean, static,
|
|
high-contrast, low-light-friendly list, and on selection `exec`s the real system
|
|
`ssh` client into the host (so tty/ProxyJump/agent forwarding just work). It's a
|
|
single Go binary. v2 added richer sorting/grouping and a native SSH key
|
|
generator. Optional features include a YubiKey launch gate. App data (recents,
|
|
favourites, settings) lives under `~/.ssh/.dial/` so it syncs via the user's
|
|
existing Syncthing.
|
|
|
|
## What v2 shipped
|
|
|
|
1. **Alphabetical sort.** The `s` key now cycles three modes: recently used →
|
|
most used → name. Favourites still pin to the top in every mode. Persisted.
|
|
|
|
2. **Last-connected timestamp** shown in the host preview pane ("1 hour ago" /
|
|
"never"), surfacing the recency data already tracked for sorting.
|
|
|
|
3. **Tag grouping + coloured tag pills.** A `g` toggle (independent of sort)
|
|
groups the list into sections: a Favourites section, one section per tag
|
|
(alphabetical), then Untagged. Tag pills are coloured deterministically per
|
|
tag from the theme's high-contrast palette. **Decision made:** grouping is an
|
|
independent toggle (not a 4th sort mode), and a multi-tagged host appears
|
|
under its *first* tag only, so the list stays a clean permutation with no
|
|
duplicated rows.
|
|
|
|
4. **`dial keygen`.** A new subcommand that generates SSH keys **natively in Go**
|
|
(no `ssh-keygen` dependency): ed25519 by default, `--rsa` for RSA-4096.
|
|
Optional passphrase (default none). It keeps the `.pub` file (the old shell
|
|
script deleted it), writes the private key `0600`, and can append a matching
|
|
`Host` block to `~/.ssh/config` — backing the file up first and refusing to
|
|
duplicate an existing alias. It's a rebuild of an old `create_ssh_keypair.sh`,
|
|
fixing that script's macOS-only `sed`, key-deletion, and unquoted-append bugs.
|
|
|
|
## Architecture (packages)
|
|
|
|
Existing v1 packages: `sshconf` (read-only config parser), `store`
|
|
(`~/.ssh/.dial/` persistence), `picker` (the TUI), `connect` (exec-into-ssh),
|
|
`yubikey` (gate + recovery code), `theme` (styling). v2 added:
|
|
|
|
- `internal/keygen` — native key generation (crypto + `x/crypto/ssh`), key-file
|
|
writing with correct perms, and safe `~/.ssh/config` appends.
|
|
|
|
Host *selection* stayed decoupled from the *action*, which keeps room to add new
|
|
per-host actions (e.g. the deferred SFTP browser) without disturbing the picker.
|
|
|
|
## Current state
|
|
|
|
- **Complete and green.** All packages build; `go vet` clean; unit tests pass
|
|
for `sshconf`, `store`, `yubikey`, `picker`, `keygen`.
|
|
- **Cross-compiles** to all five targets (macOS arm64/amd64, Linux amd64/arm64,
|
|
Windows amd64).
|
|
- **Live-verified via tmux**: keygen verified end-to-end (valid ed25519, correct
|
|
perms, config append with backup); picker navigation, sort cycling, tag
|
|
grouping, and favourites toggling all exercised.
|
|
|
|
## Known limitations / not yet exercised
|
|
|
|
- **YubiKey gate is hardware-untested** — the challenge-response and recovery-code
|
|
logic have unit coverage, but the gate has not been exercised against a
|
|
physical YubiKey + `ykman` on real hardware.
|
|
- Still unsigned binaries (Gatekeeper/SmartScreen warnings); no CI/releases.
|
|
|
|
## Deferred (explicitly out of this pass)
|
|
|
|
- **In-app SFTP file browser.** Planned for v2 (see `dial-v2-plan.md` §3) — a
|
|
dual-pane push/pull browser opened with `t`, built on an in-process SFTP stack
|
|
(`pkg/sftp` + `golang.org/x/crypto/ssh`). **Not built.** No `t` action, no
|
|
transfer/connection packages, and `pkg/sftp` is not a dependency. This is the
|
|
largest deferred item and would be the natural centrepiece of a v3.
|
|
- Idle-timeout gate option; distribution/signing/package managers; multi-select
|
|
actions across hosts; per-host notes; fuzzy search.
|
|
|
|
## Open questions & directions to brainstorm
|
|
|
|
1. **SFTP browser — build it next?** It was the headline v2 plan but slipped.
|
|
Worth scoping as the v3 centrepiece, and if so, what's the cheapest way to
|
|
smoke-test the connection layer against a real sshd (a throwaway VM? a
|
|
container running sshd? a known host)?
|
|
2. **Grouping refinements** — should multi-tagged hosts optionally appear under
|
|
*every* tag? Should there be a per-tag filter shortcut or colour legend?
|
|
3. **Distribution** — Homebrew tap / Scoop / `install.sh` / signed releases via
|
|
CI: worth doing now that the feature set is broad?
|
|
|
|
## How to build / try
|
|
|
|
- Build: `make build` (native) or `make dist` (all platforms). Requires Go 1.25+.
|
|
- Keys: `dial keygen` (no external deps).
|
|
- YubiKey gate: `dial yubikey enable` (requires Yubico's `ykman`).
|