Releases: talkincode/sshx
Releases · talkincode/sshx
Release v0.18.0
Sorry, something went wrong.
No results found
SSHX - Agent-native remote host execution over SSH
📋 What's Changed
Added
- sshx text narrates scan progress on stderr after a short grace period
(bytes, percentage, lines, elapsed, matches) and warns when a scan stops at
its --max-scan-bytes budget, naming --offset/--tail/--pattern/
--max-scan-bytes as the ways to narrow it. A slow scan closes with the same
advice. stdout stays exactly one JSON document; progress never enters it.
- sshx.text.v1 stats.expected_scan_bytes (additive): the byte budget of the
scanned window, so a caller can size a scan and spot a partial one before
trusting total_hits_exact. Omitted when the source size is unknown (journal).
- A policy block now mirrors its reason to stderr in --json mode
(sshx: blocked by safety policy (phase=admission, error_kind=blocked, executed=false, exit_code=-1)) plus the flattened reason with the guarded
alternative, so a caller that only prints stdout/stderr no longer sees a
silent refusal. The block predicate and the sshx sql --docker= alternative
are documented in README/README_CN/usage, with unit and E2E assertions.
- sshx warns when a command contains a non-leading sudo (for example
cd /data/app && sudo docker compose up -d): password auto-fill only rewrites
a leading sudo, so it announces the boundary before connecting and explains
the refusal afterwards, suggesting sudo sh -c "<command>". The auto-fill
scope is unchanged.
- Per-verb help: every subcommand now answers sshx <verb> --help with its own
usage document instead of rejecting --help as an unknown option. --help --json emits the same blocks as an sshx.help.v1 document (sshx text --help --json keeps its structured sshx.text.help.v1 document), and the
help text is defined once and shared with the global sshx --help surface.
- --quiet (alias --no-notices): suppresses human notices on stderr
(deprecation warnings, policy-block mirrors, sudo-boundary hints, scan
progress, narration) so a caller that merges the streams
(2>&1) under --json still reads exactly one parseable document. stdout,
the exit code, and the JSON result are unchanged. Like --help, it is
recognized in option position in any order, so it works before or after other
sshx options and never reaches the remote command.
- sshx sql --statement-file=PATH and statement input on stdin: a query no
longer has to be assembled as a shell string. sshx sql also accepts a
statement that opens with a SQL comment (-- header) as statement text
instead of rejecting it as an unknown option. Reading stdin waits for EOF
(like psql), so a caller whose stdin pipe stays open should pass
--statement-file instead.
- sshx plugin install <dir> [--replace] [--trust]: provision an existing local
plugin directory through the audited CLI instead of hand-placing files under
the runtime plugin root. The source is staged with sshx's own modes, validated
through the executor's loader before publishing, and --trust records the
published digest in the same step. --replace preserves the previous plugin
as a backup, symlinks and non-regular entries are refused, and the copy is
bounded (8MiB, 128 files).
Changed
-
sshx text reads remote files through a pipelined SFTP path: read-ahead
aperture plus UseConcurrentReads, so the SFTP layer keeps multiple requests
in flight for one file instead of one round trip per read. On the reporting
host the same 8 MiB window went from a median 83.0 s to 26.5 s (88.0/77.9 s →
23.8/29.1 s, alternating runs, identical bytes and lines scanned). --max-scan-bytes
still bounds both the scan and the read-ahead, and the truncation probe reads
exactly one byte past the budget.
-
sshx plugin list groups built-in capabilities and local plugins and always
names the local plugin root, so "no local plugins installed" is visible
instead of inferred; local entries report provenance, trust, validity, and
digest, and plugin show/trust/install report the same state line. A
staging directory left by an interrupted install is skipped instead of being
reported as an invalid plugin, and a publication that cannot be renamed swaps
the previous plugin back in (or reports where the recovery copy was kept).
-
Compatibility mode (sshx -h=<host> ...) now accepts the documented
--ssh-password-key=KEY option instead of forwarding it as part of the remote
command, and rejects an unrecognized option instead of forwarding it, naming
the offending token and suggesting the intended option when one is close. The guessed
--local/--remote transfer options name the real surface
(--upload=<local> --to=<remote>), and a missing upload/download destination
names --to explicitly. Remote command arguments after the first command
token, and after --, are unchanged.
-
A missing plugin, --list=, --mkdir=, --rm=, --upload= or
--download= now names the searched directory or the option that supplies the
missing value (remote path is required / local path is required diagnosed
the wrong cause).
Fixed
-
sshx text no longer looks like a hang: a 60+ second SFTP window used to emit
nothing at all, and a budget-limited scan returned partial results without
saying so.
-
sshx run --target=<name> resolves the sudo keyring reference per host, the
same way single-target verbs do: an explicit -pk still wins, but the
built-in default (master) no longer shadows a host's configured
sudo_password_key. The plan, the SSH client, the keyring lookup, and the
audit trail all resolve the same reference, so the plan reports the key that
will be used and each target's audit event names the credential it used (the
run summary records only a caller-level choice).
-
sshx apply removes its staging temp, publication temp, and unverified backup
with an absolute remover or POSIX unlink before falling back to PATH rm, so
a host whose rm is a trash-move wrapper no longer collects leaked copies of
the applied payload. Cleanup success now means the path is gone, and an
artifact that cannot be removed still reports cleanup_pending with exit 4.
-
TestApplySudoScriptEvidenceAndCleanup no longer pipes the generated
privileged script through the child's stdin or captures its output through
os/exec copier goroutines; the fixture runs the script from a file with
file-backed streams and reports a truncated report readably instead of
panicking on a nil pointer.
-
The CI Lint gate is pinned to golangci-lint v2.13.2 and .golangci.yml
uses the v2 linters.exclusions.rules schema, so an upstream release or the
v1-era key can no longer fail the job before any Go file is analysed.
🚀 Quick Install
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/talkincode/sshx/main/install.sh | bash
Windows (PowerShell):
irm https://raw.githubusercontent.com/talkincode/sshx/main/install.ps1 | iex
📦 Downloads
| Platform |
Architecture |
File |
| Linux |
x86_64 |
sshx-linux-amd64.tar.gz |
| Linux |
ARM64 |
sshx-linux-arm64.tar.gz |
| macOS |
Intel |
sshx-darwin-amd64.tar.gz |
| macOS |
Apple Silicon |
sshx-darwin-arm64.tar.gz |
| Windows |
x86_64 |
sshx-windows-amd64.zip |
| Windows |
ARM64 |
sshx-windows-arm64.zip |
Verify downloads: Use checksums.txt for integrity verification
📚 Documentation
Release v0.17.0
Sorry, something went wrong.
No results found
SSHX - Agent-native remote host execution over SSH
📋 What's Changed
Added
- sshx ros: native MikroTik RouterOS (ROS) support strictly over standard SSH
(port 22) and SFTP protocols. No ROS API service port (8728/8729) or REST port
is required. Features include:
- Command catalog mapping RouterOS paths (ip address, ip firewall, ip route,
interface, system resource, etc.) with output parsing into structured JSON.
- raw command execution for arbitrary RouterOS API paths (e.g. sshx ros -h=host raw /system/resource/print)
with optional --raw flag to bypass output parsing.
- Safety guardrails: destructive actions (/system/reset-configuration, /system/reboot,
/certificate/reset, /disk/format) are blocked without --force, and state-altering
raw mutations are blocked without --allow-write.
- Client-side dry-run: preview execution plans and mutation flags without connecting.
- SFTP configuration and file workflows: file upload, file download, file list,
script put (with --source=@path), backup download (with --cleanup), and
export download (with --compact and --cleanup).
- Introspection tools: commands, help, schema, doctor, and explain-error.
- MCP tool sshx_ros for AI agent integration with expect_plan, dry_run, and
allow_write guardrails.
🚀 Quick Install
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/talkincode/sshx/main/install.sh | bash
Windows (PowerShell):
irm https://raw.githubusercontent.com/talkincode/sshx/main/install.ps1 | iex
📦 Downloads
| Platform |
Architecture |
File |
| Linux |
x86_64 |
sshx-linux-amd64.tar.gz |
| Linux |
ARM64 |
sshx-linux-arm64.tar.gz |
| macOS |
Intel |
sshx-darwin-amd64.tar.gz |
| macOS |
Apple Silicon |
sshx-darwin-arm64.tar.gz |
| Windows |
x86_64 |
sshx-windows-amd64.zip |
| Windows |
ARM64 |
sshx-windows-arm64.zip |
Verify downloads: Use checksums.txt for integrity verification
📚 Documentation
Release v0.16.1
Sorry, something went wrong.
No results found
SSHX - Agent-native remote host execution over SSH
📋 What's Changed
Fixed
- Admission now reports why a plan was rejected instead of the generic
invalid execution plan placeholder. A missing host fails with
host is required (error_kind: config) in both the human message and the
--json envelope. Unknown --host-test targets also keep that config
reason on config_check instead of leaving it passed.
- SFTP actions with an empty path are rejected during admission as config
errors (remote path is required / local path is required), matching the
MCP adapter's pre-flight checks. Previously an empty --mkdir=, --rm=,
--download= or --list= was admitted and surfaced later as a misleading
connection failure, and an empty --upload= as a local-io error.
🚀 Quick Install
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/talkincode/sshx/main/install.sh | bash
Windows (PowerShell):
irm https://raw.githubusercontent.com/talkincode/sshx/main/install.ps1 | iex
📦 Downloads
| Platform |
Architecture |
File |
| Linux |
x86_64 |
sshx-linux-amd64.tar.gz |
| Linux |
ARM64 |
sshx-linux-arm64.tar.gz |
| macOS |
Intel |
sshx-darwin-amd64.tar.gz |
| macOS |
Apple Silicon |
sshx-darwin-arm64.tar.gz |
| Windows |
x86_64 |
sshx-windows-amd64.zip |
| Windows |
ARM64 |
sshx-windows-arm64.zip |
Verify downloads: Use checksums.txt for integrity verification
📚 Documentation
Release v0.16.0
Sorry, something went wrong.
No results found
SSHX - Agent-native remote host execution over SSH
📋 What's Changed
Added
- sshx text: bounded remote text/log dissection over SFTP or sshx-owned
journalctl. Lexical presets extract exception blocks, --help/--help --json
document the Agent workflow, and MCP exposes sshx_text. Hits are redacted;
there is no --command pipeline.
🚀 Quick Install
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/talkincode/sshx/main/install.sh | bash
Windows (PowerShell):
irm https://raw.githubusercontent.com/talkincode/sshx/main/install.ps1 | iex
📦 Downloads
| Platform |
Architecture |
File |
| Linux |
x86_64 |
sshx-linux-amd64.tar.gz |
| Linux |
ARM64 |
sshx-linux-arm64.tar.gz |
| macOS |
Intel |
sshx-darwin-amd64.tar.gz |
| macOS |
Apple Silicon |
sshx-darwin-arm64.tar.gz |
| Windows |
x86_64 |
sshx-windows-amd64.zip |
| Windows |
ARM64 |
sshx-windows-arm64.zip |
Verify downloads: Use checksums.txt for integrity verification
📚 Documentation
Release v0.15.0
Sorry, something went wrong.
No results found
SSHX - Agent-native remote host execution over SSH
📋 What's Changed
This is the first tag after v0.13.0. It also ships the previously untagged
0.14.0 execution-contract work (plan binding, evidence, timeouts, and audit
diagnostics).
Added
- Session-bound jump-host (ProxyJump-style) access via named via hops.
Connections use nested SSH channels for the invocation lifetime, with
independent host-key and auth decisions per hop, hop-aware dry-run/plan
inputs, and audit records. Local port forwarding, SOCKS, and leftover
listeners are not added. OpenSSH import maps a single-token ProxyJump
only when that alias is already a named sshx host.
🚀 Quick Install
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/talkincode/sshx/main/install.sh | bash
Windows (PowerShell):
irm https://raw.githubusercontent.com/talkincode/sshx/main/install.ps1 | iex
📦 Downloads
| Platform |
Architecture |
File |
| Linux |
x86_64 |
sshx-linux-amd64.tar.gz |
| Linux |
ARM64 |
sshx-linux-arm64.tar.gz |
| macOS |
Intel |
sshx-darwin-amd64.tar.gz |
| macOS |
Apple Silicon |
sshx-darwin-arm64.tar.gz |
| Windows |
x86_64 |
sshx-windows-amd64.zip |
| Windows |
ARM64 |
sshx-windows-arm64.zip |
Verify downloads: Use checksums.txt for integrity verification
📚 Documentation
Release v0.13.0
Sorry, something went wrong.
No results found
SSHX - Agent-native remote host execution over SSH
📋 What's Changed
Added
- --password-check/--password-list/--password-set --json emit sshx.secrets.v1.
A missing --password-check key exits non-zero (exists: false) instead of
looking like success.
- --host-add/--host-update/--host-remove/--host-test/--host-test-all/--host-import --json
emit sshx.hosts.v1 documents so agents need not scrape logger text.
--host-import --json requires --host-import=<name1,name2>.
- sshx audit query and sshx audit export: read-only filters over local
audit JSONL (--since/--until/--target/--action/--run-id/--error-kind/--bypass-only).
- sshx_run over MCP forwards JSONL target_finished events as progress
notifications when the client supplies a progressToken. --pty is
documented as out of MCP scope.
- Guarded MySQL/MariaDB engine (sshx sql --engine=mysql) behind a Dialect
interface shared with PostgreSQL and SQLite. Run-mode blocks mysql /
mariadb / mycli and redirects to sshx sql.
- Release artifacts can be signed with cosign (keyless OIDC), accompanied by
SPDX SBOMs and GitHub build provenance attestations.
- Contract freeze policy (docs/contract.md) for v1 schemas.
Changed
- --host-add without -pk no longer persists sudo_password_key=master.
The runtime sudo fallback remains master; inventory only records keys the
operator set.
- internal/sshclient/client.go is split along connect/hostkey/exec/SFTP seams
with no behavior change.
Fixed
- Piped --password-set no longer writes the password prompt onto stdout.
🚀 Quick Install
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/talkincode/sshx/main/install.sh | bash
Windows (PowerShell):
irm https://raw.githubusercontent.com/talkincode/sshx/main/install.ps1 | iex
📦 Downloads
| Platform |
Architecture |
File |
| Linux |
x86_64 |
sshx-linux-amd64.tar.gz |
| Linux |
ARM64 |
sshx-linux-arm64.tar.gz |
| macOS |
Intel |
sshx-darwin-amd64.tar.gz |
| macOS |
Apple Silicon |
sshx-darwin-arm64.tar.gz |
| Windows |
x86_64 |
sshx-windows-amd64.zip |
| Windows |
ARM64 |
sshx-windows-arm64.zip |
Verify downloads: Use checksums.txt for integrity verification
📚 Documentation
Release v0.12.0
Sorry, something went wrong.
No results found
SSHX - Agent-native remote host execution over SSH
📋 What's Changed
Changed
- Windows CI now runs the CLI surface (internal/app), the SSH core
(internal/sshclient), and internal/runtimepath in addition to the
previously covered packages, taking the Windows matrix from 91 to roughly 320
tests. Tests resolve the home directory through a portable helper so
USERPROFILE is honored, and POSIX permission assertions are guarded by
runtime.GOOS. internal/plugin, internal/skillinstall, and tests/e2e
remain excluded pending Windows symlink/permission equivalents (issue #50).
Added
- sshx_run over MCP accepts shell for parity with the CLI --shell, and
script payloads sent over MCP follow their shebang like CLI payloads do.
- sshx sql --docker=<container> now reads that container's environment for the
database role and name, so a TimescaleDB/Postgres image whose POSTGRES_USER
is not postgres no longer fails with role "postgres" does not exist.
--db and --db-user become optional in this form. Discovery is best-effort:
a container that cannot be inspected or exposes no credentials falls back to
the client defaults, and passing --db-user or --db-password-key disables
it. --db-cred-from keeps its stricter contract and still requires a password.
- sshx run script payloads now honor the script's shebang. A
#!/usr/bin/env bash payload runs under bash -s -- instead of being piped
to sh, so bash-only constructs (set -o pipefail, arrays, [[ ]]) work
instead of failing remotely with Illegal option -o pipefail. --shell=NAME
overrides the shebang; supported interpreters are sh, bash, zsh,
dash, ksh, and ash. A payload declaring any other interpreter (for
example python3) is now rejected locally as error_kind: config with no
connection, instead of being silently executed by sh. The selected
interpreter appears as action.script_runner in dry-run plans and results.
- Safety-check recall now covers recursive removal of critical system
directories (/etc, /usr, /var, …), rm --no-preserve-root,
wipefs -a, chown -R ... /, LVM pvremove/vgremove/lvremove,
zpool|zfs destroy, dd of=/dev/<disk>, systemctl kexec, and destructive
commands nested inside docker exec / docker compose exec.
Fixed
- A missing remote database client is now reported as error_kind: config
naming the binary, instead of the opaque
database operation failed during execute with status 127 that required
decoding a shell convention to understand.
- Command safety checks no longer match dangerous keywords anywhere in the raw
command string. The command line is split into shell segments and only the
token in command position is judged, following sudo/env/timeout
wrappers, sh -c payloads, and docker exec into the command that actually
runs. Read-only diagnostics such as last reboot -F,
journalctl | grep -iE 'fail|halt', iptables-save | grep -F ...,
curl ... | sha256sum, fdisk -l /dev/sda, parted /dev/sdb print, and
bare wipefs /dev/sdb are no longer blocked. Replaying 49 commands that a
real workload had blocked shows 48 were false positives; only rm -rf /
remains blocked, alongside the unchanged guarded-SQL client redirects.
iptables flag matching is now case-sensitive so -F/-X (flush / delete
chain) are distinguished from -f/-x (fragment / exact).
🚀 Quick Install
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/talkincode/sshx/main/install.sh | bash
Windows (PowerShell):
irm https://raw.githubusercontent.com/talkincode/sshx/main/install.ps1 | iex
📦 Downloads
| Platform |
Architecture |
File |
| Linux |
x86_64 |
sshx-linux-amd64.tar.gz |
| Linux |
ARM64 |
sshx-linux-arm64.tar.gz |
| macOS |
Intel |
sshx-darwin-amd64.tar.gz |
| macOS |
Apple Silicon |
sshx-darwin-arm64.tar.gz |
| Windows |
x86_64 |
sshx-windows-amd64.zip |
| Windows |
ARM64 |
sshx-windows-arm64.zip |
Verify downloads: Use checksums.txt for integrity verification
📚 Documentation
Release v0.11.0
Sorry, something went wrong.
No results found
SSHX - Agent-native remote host execution over SSH
📋 What's Changed
Added
- Source address binding matching OpenSSH -b / BindAddress / BindInterface.
--bind=<ip|iface> overrides the current invocation; named hosts persist
bind in settings.json. Interface names pick a global unicast address
matching the destination family (link-local and loopback only when the
destination is that kind). Invalid bind is error_kind: config and does
not dial. Dry-run, audit, compatibility JSON, sshx run, transfer,
host-test, MCP tools, and ssh_config import (BindAddress /
BindInterface, first value wins) all expose the field. --bind= clears
a host bind for this invocation.
🚀 Quick Install
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/talkincode/sshx/main/install.sh | bash
Windows (PowerShell):
irm https://raw.githubusercontent.com/talkincode/sshx/main/install.ps1 | iex
📦 Downloads
| Platform |
Architecture |
File |
| Linux |
x86_64 |
sshx-linux-amd64.tar.gz |
| Linux |
ARM64 |
sshx-linux-arm64.tar.gz |
| macOS |
Intel |
sshx-darwin-amd64.tar.gz |
| macOS |
Apple Silicon |
sshx-darwin-arm64.tar.gz |
| Windows |
x86_64 |
sshx-windows-amd64.zip |
| Windows |
ARM64 |
sshx-windows-arm64.zip |
Verify downloads: Use checksums.txt for integrity verification
📚 Documentation
Release v0.10.0
Sorry, something went wrong.
No results found
SSHX - Agent-native remote host execution over SSH
📋 What's Changed
Added
- Headless hosts can store secrets in an encrypted local vault instead of
the OS keyring. Set SSHX_SECRET_BACKEND=local-vault plus
SSHX_VAULT_PASSPHRASE or SSHX_VAULT_KEY_FILE (0600). The vault file is
$SSHX_HOME/vault (owner-only, scrypt + secretbox). There is no silent
fallback to a file when the keyring is missing. The vault is write-only:
--password-get is refused, MCP still exposes no password tools, and sshx
injects secrets over stdin. Dry-run and audit record secret_backend and
secret_unlock without secret values.
🚀 Quick Install
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/talkincode/sshx/main/install.sh | bash
Windows (PowerShell):
irm https://raw.githubusercontent.com/talkincode/sshx/main/install.ps1 | iex
📦 Downloads
| Platform |
Architecture |
File |
| Linux |
x86_64 |
sshx-linux-amd64.tar.gz |
| Linux |
ARM64 |
sshx-linux-arm64.tar.gz |
| macOS |
Intel |
sshx-darwin-amd64.tar.gz |
| macOS |
Apple Silicon |
sshx-darwin-arm64.tar.gz |
| Windows |
x86_64 |
sshx-windows-amd64.zip |
| Windows |
ARM64 |
sshx-windows-arm64.zip |
Verify downloads: Use checksums.txt for integrity verification
📚 Documentation
Release v0.9.0
Sorry, something went wrong.
No results found
SSHX - Agent-native remote host execution over SSH
📋 What's Changed
Added
- sshx login opens a human-only interactive session on a named host or
literal address, reusing sshx host resolution, key/password auth, and
known_hosts. Preferred form is sshx login <name> or -h=<name>;
--target= remains a long alias. Optional --sudo lands in a privileged
login shell after feeding the host sudo keyring secret on stdin. --json
is only valid with --dry-run; multi-host selectors and MCP are rejected.
POSIX TTY only; Windows returns an explicit unsupported error. Audit
records metadata, not the session transcript.
🚀 Quick Install
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/talkincode/sshx/main/install.sh | bash
Windows (PowerShell):
irm https://raw.githubusercontent.com/talkincode/sshx/main/install.ps1 | iex
📦 Downloads
| Platform |
Architecture |
File |
| Linux |
x86_64 |
sshx-linux-amd64.tar.gz |
| Linux |
ARM64 |
sshx-linux-arm64.tar.gz |
| macOS |
Intel |
sshx-darwin-amd64.tar.gz |
| macOS |
Apple Silicon |
sshx-darwin-arm64.tar.gz |
| Windows |
x86_64 |
sshx-windows-amd64.zip |
| Windows |
ARM64 |
sshx-windows-arm64.zip |
Verify downloads: Use checksums.txt for integrity verification
📚 Documentation