Skip to content

Improve#2

Open
DimitriGilbert wants to merge 8 commits into
mainfrom
improve
Open

Improve#2
DimitriGilbert wants to merge 8 commits into
mainfrom
improve

Conversation

@DimitriGilbert

@DimitriGilbert DimitriGilbert commented May 19, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Backup and restore configuration functionality.
    • View and edit global settings via config command.
    • Import SSH hosts from existing SSH config files.
    • Display connection history.
    • Filter and display servers by group with tree view option.
    • Configure server timeouts and proxy jump support.
    • Skip confirmation prompts with --yes flag.
  • Improvements

    • Enhanced server validation and configuration options.
    • Completion support for new commands.

Review Change Stack

- bin/edit: fix help text from 'add' to 'edit a server'
- bin/remove: add --yes/-y flag with confirmation prompt
- bin/connect: record connection history before SSH call
- bin/doctor: add rsync to required tools check
- completely.yaml/bash: add --yes/-y to remove completion
- utils/install: add --quiet support
- utils/get_sshm0: add --quiet support
- bin/import: import servers from SSH config file (--file, --force, --dry-run, --tag)
- bin/tags: list all tags with server counts (--long for server names)
- bin/history: view connection history (--count, --server filter)
- bin/config: view/edit global config (list, get, set, plugins)
- Updated sshm0, completely.yaml, completely.bash with all new subcommands
@coderabbitai

coderabbitai Bot commented May 19, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@DimitriGilbert has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 17 minutes and 56 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f439e0c2-88b9-4a48-a359-47ef29d69c37

📥 Commits

Reviewing files that changed from the base of the PR and between e2af43d and c1bb4ee.

📒 Files selected for processing (24)
  • .gitignore
  • bin/add
  • bin/backup
  • bin/config
  • bin/connect
  • bin/cp
  • bin/doctor
  • bin/edit
  • bin/exec
  • bin/export
  • bin/history
  • bin/import
  • bin/rsync
  • bin/show
  • bin/update
  • bin/utils
  • completely.bash
  • completely.yaml
  • completely.zsh
  • documentation.md
  • readme.md
  • sshm0
  • sshm0.rc
  • utils/install
📝 Walkthrough

Walkthrough

This PR extends sshm0's server configuration model with three new fields (timeout, proxy, group), adds four new utility commands (backup, config, import, history), integrates the new fields into all server creation/editing and SSH-based commands, and expands completion support throughout the CLI.

Changes

Server configuration model expansion with timeout, proxy, and group fields, plus new utility commands

Layer / File(s) Summary
Server configuration schema and validation utilities
server.dist, bin/utils
Server template now includes sshm0_server_timeout, sshm0_server_proxy, and sshm0_server_group fields. Two new utilities: sshm0_validate_server validates required fields (IP, port, user, auth, key path when needed), and sshm0_get_proxy_args resolves proxy target strings for SSH ProxyJump.
Add and edit server workflows with new fields
bin/add, bin/edit
Both commands now accept --proxy/-J, --timeout, and --group options via CLI parsing. Interactive prompts ask for these fields when not provided. Before persisting, sshm0_validate_server is called to validate the resolved configuration; on failure, the command exits with error. Config files include all new fields.
Connection commands using timeout and proxy
bin/connect, bin/cp, bin/rsync, bin/ping, bin/show, bin/export
connect, cp, and rsync build SSH options with ConnectTimeout (default 10) and conditionally add ProxyJump when a proxy is configured. ping uses configurable timeout instead of hardcoded 5. show displays Timeout and Proxy fields. export generates SSH config comments for timeout and group.
Server list filtering by group and removal confirmation
bin/list, bin/remove
list adds --group/-g filter and --tree/--no-tree display modes; tree mode groups servers by sshm0_server_group with sorted group headers. remove adds -y/--yes and --no-yes flags to skip or enforce confirmation prompts.
New utility commands
bin/backup, bin/config, bin/import, bin/history
backup: full backup/restore via tar.gz with timestamp defaults and optional prompts. config: manage global app configuration with list/get/set/plugins actions and in-file sed updates. import: imports servers from SSH config files, supporting tags, force overwrite, and dry-run mode. history: displays connection history with optional server/count filtering and formatted timestamps.
CLI and completion support
sshm0, completely.bash, completely.yaml, utils/get_sshm0, utils/install
Main sshm0 script recognizes new subcommands. Bash and YAML completions expanded with full flag/option definitions for all subcommands including new commands and options like --group, --tree, --yes. Utility scripts add --quiet option for verbosity control.
Doctor tool requirements update
bin/doctor
Tool verification now includes rsync in the required tools list; success and failure messages updated accordingly.

Sequence Diagram(s)

No sequence diagrams generated. While the PR introduces several new command flows (backup, config, import, history), the changes to existing commands are primarily configuration and option handling rather than multi-component sequential workflows. The new commands are largely self-contained utilities without significant cross-component interactions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

🐰 A rabbit hops through config fields so new,
With timeout, proxy, groups in every view,
Four utility commands take their stance,
While backup, import, history enhance!
The SSH dance now smoother, stronger still—
Configuration bends to every will!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title 'Improve' is vague and does not clearly summarize the main changes in the pull request. It does not convey meaningful information about the extensive additions and modifications across multiple scripts. Use a more descriptive title that captures the primary changes, such as 'Add configuration management, backup/restore, and proxy support across CLI tools' or 'Expand sshm0 CLI with new commands and server configuration options'.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch improve

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
completely.yaml (1)

1-17: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add tags and history to top-level command completion list.

sshm0 tags and sshm0 history are defined later, but they’re missing from the root sshm0: command list.

Suggested fix
 sshm0:
 - list
 - add
 - config
 - connect
 - cp
 - edit
 - plugin
 - remove
 - rename
 - show
 - export
 - import
 - ping
 - doctor
+- tags
+- history
 - backup
 - --config-dir
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@completely.yaml` around lines 1 - 17, Update the top-level sshm0 command list
to include the missing commands by adding "tags" and "history" to the array
under the sshm0 key so the root completion includes sshm0 tags and sshm0
history; locate the sshm0 top-level list (containing list, add, config, ...) and
insert "tags" and "history" alongside the existing entries.
bin/edit (1)

367-390: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Interactive edit flow doesn’t cover timeout.

Line 367 and the interactive prompts omit timeout, so users can’t update timeout interactively in edit mode.

Suggested fix
-	if [ -z "$_arg_ip" ] && [ -z "$_arg_user" ] && [ -z "$_arg_password" ] && [ -z "$_arg_key" ] && [ -z "$_arg_auth" ] && [ -z "$_arg_port" ] && [ -z "$_arg_tag" ] && [ -z "$_arg_group" ] && [ -z "$_arg_proxy" ]; then
+	if [ -z "$_arg_ip" ] && [ -z "$_arg_user" ] && [ -z "$_arg_password" ] && [ -z "$_arg_key" ] && [ -z "$_arg_auth" ] && [ -z "$_arg_port" ] && [ -z "$_arg_tag" ] && [ -z "$_arg_timeout" ] && [ -z "$_arg_group" ] && [ -z "$_arg_proxy" ]; then
@@
 		read -rp "Tags (comma-separated) [$(IFS=,; echo "${sshm0_server_tags[*]}")]: " _arg_tag
 		_current_tags="$(IFS=,; echo "${sshm0_server_tags[*]}")"
 		_arg_tag="${_arg_tag:-$_current_tags}"
+		read -rp "Timeout in seconds [${sshm0_server_timeout:-10}]: " _arg_timeout
+		_arg_timeout="${_arg_timeout:-${sshm0_server_timeout:-10}}"
 		read -rp "Group [$sshm0_server_group]: " _arg_group
 		_arg_group="${_arg_group:-$sshm0_server_group}"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bin/edit` around lines 367 - 390, The interactive edit flow is missing the
timeout prompt so users can't change server timeout; add a prompt like the
others in the same block to read and set _arg_timeout using the existing stored
value sshm0_server_timeout as the default (e.g., read -rp "Timeout in seconds
[$sshm0_server_timeout]: " _arg_timeout;
_arg_timeout="${_arg_timeout:-$sshm0_server_timeout}"), and ensure subsequent
code that writes/uses _arg_timeout matches how other fields (like _arg_port,
_arg_proxy) are handled so the edited timeout is persisted.
🧹 Nitpick comments (1)
bin/remove (1)

225-225: ⚡ Quick win

Add success feedback and error handling.

The removal executes silently (especially when using --yes), and there's no error checking on the rm command. Adding feedback improves UX consistency since line 227 already prints an error for "not found" cases.

✨ Proposed enhancement
-	rm "$(sshm0_server_config_path "$_arg_name")";
+	if rm "$(sshm0_server_config_path "$_arg_name")"; then
+		echo "Server '$_arg_name' removed successfully."
+	else
+		echo "Failed to remove server '$_arg_name'." >&2
+		exit 1
+	fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bin/remove` at line 225, The removal call using rm
"$(sshm0_server_config_path "$_arg_name")" currently runs silently and lacks
error handling; update the block that calls sshm0_server_config_path with
_arg_name (and respects the --yes flow) to test rm's success and report back:
first check whether the target exists, run rm and capture its exit status, on
non-zero exit print a clear error (including the path and exit/status message)
similar to the existing "not found" error, and on success print a confirmation
like "Removed <path>"; ensure errors from rm are not swallowed so callers and CI
see failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@bin/add`:
- Around line 384-386: The interactive add flow currently reads _arg_group and
_arg_proxy but never prompts for the new timeout field; add a read prompt for
the timeout (e.g., read -rp "Timeout [<default>]: " _arg_timeout) in the same
interactive block where _arg_group and _arg_proxy are read, ensure the variable
name matches the rest of the script (use _arg_timeout) and handle empty input as
the default value the script expects so subsequent logic that uses _arg_timeout
sees the intended value.

In `@bin/backup`:
- Around line 264-265: The script currently runs the tar command (tar -czf
"$_output" -C "$(dirname "$SSHM0_CONFIG_DIR")" "$(basename
"$SSHM0_CONFIG_DIR")") and then unconditionally calls log "Backup created:
$_output" 1; change this so you check tar's exit status and only call log on
success. Concretely, run the tar command, capture its exit code ($? or use &&),
and if it succeeds call log "Backup created: $_output" 1; if it fails, call log
with an error message including the tar exit code and/or stderr and exit with a
non-zero status so failures are not reported as successful backups.
- Line 252: The tar extraction at tar -xzf "$_arg_restore" -C "$(dirname
"$SSHM0_CONFIG_DIR")" allows path traversal; before extracting, validate the
archive members (use tar -tzf "$_arg_restore") and reject any entry that is
absolute (starts with '/') or contains '..' path segments or leads outside the
intended directory, or alternatively extract into a temporary directory and move
only normalized, whitelisted paths into the target; then run the actual
extraction to the safe directory (dirname "$SSHM0_CONFIG_DIR") only after
verification to ensure no member can write outside the config dir.

In `@bin/config`:
- Around line 276-277: The code uses eval to read a variable by name (setting
_eval_val via eval "echo \"\${$_arg_key}\"") which risks executing
user-controlled content; instead validate _arg_key against a safe variable-name
pattern (e.g. ^[A-Za-z_][A-Za-z0-9_]*$) and then perform indirect expansion to
read the variable value (use the ${!_arg_key} form) and keep the existing
non-empty check on _eval_val; ensure you bail or error if the key validation
fails.
- Around line 292-296: Validate that _arg_key is a safe shell variable name
(e.g. match ^[A-Za-z_][A-Za-z0-9_]*$) and fail early if it does not, then
shell-escape _arg_value before writing to _config_file; replace constructing
_entry directly with something like: verify _arg_key with a regex and exit
non-zero on failure, compute an escaped value via printf '%q' "$_arg_value" (or
an equivalent escaping routine) and then build the entry from the validated key
and escaped value, and finally use the validated key when checking/updating the
file (grep/sed) so you never write raw/unescaped values or malformed keys into
_config_file.

In `@bin/export`:
- Around line 274-275: The export output omits the sshm0_server_proxy field;
update the export generation (where the timeout is echoed, e.g., the echo
printing "# Timeout: ${sshm0_server_timeout:-10}s") to also emit the proxy as a
comment immediately after that line by echoing the sshm0_server_proxy value
(e.g., "# Proxy: ${sshm0_server_proxy}") so the exported SSH config includes the
proxy reference for consistency with sshm0 show (note: keep it as a comment
since it is a reference, not a real SSH directive).

In `@bin/history`:
- Around line 107-117: The --count/-n parsing currently assigns _arg_count in
the branches for -n|--count, --count=* and -n* without validating it, which
leads to shell errors when non-numeric values are used; update the parsing to
validate that _arg_count matches a positive-integer regex (e.g. '^[1-9][0-9]*$')
after assignment (or centralize validation after option parsing) and call die
with a clear message if validation fails, ensuring all branches that set
_arg_count (the -n|--count handler, the --count=* handler, and the -n* handler)
use this validation before _arg_count is used later.

In `@bin/import`:
- Around line 359-367: The current Host parsing treats the entire "Host ..."
line as a single name and fails on multiple names or glob patterns; change the
logic around _flush_host and _host_name to split the string after "Host " into
separate tokens, trim each token, and iterate over them instead of assigning the
whole remainder to _host_name; for each token, skip any that are '*' or contain
shell glob characters (e.g., '*', '?', '[') or patterns like '*.' and only
assign valid plain hostnames to _host_name and call _flush_host (or process) per
valid token so aliases like "Host a b" or patterns "web-*" don't abort the
import.
- Around line 321-346: The current import logic writes server config files
without validating required fields (e.g., _host_user, _host_hostname/_host_name)
and auth combinations (_auth vs _key/password), causing unusable configs; before
printing to _tmpcfg and moving it to sshm0_server_config_path, add validation
checks that ensure _host_name and _host_user are non-empty, verify _auth is one
of the supported values and that corresponding credentials are present (e.g., if
_auth indicates key, ensure _key is non-empty; if password, ensure a password is
provided), reject or normalize invalid tag input from _arg_tag similarly, and
exit with die and cleanup of _tmpcfg on validation failure so the printf block
and mv are only executed when fields are valid.

In `@bin/utils`:
- Around line 122-128: sshm0_get_proxy_args can emit a malformed "user@ip:port"
when proxy fields are empty; change it to validate the loaded proxy profile
before echoing by checking that sshm0_server_user, sshm0_server_ip and
sshm0_server_port are non-empty after sshm0_load_server "$sshm0_server_proxy"
and return failure if any are missing (i.e., only build and print
"${sshm0_server_user}@${sshm0_server_ip}:${sshm0_server_port}" when all three
variables are set), keeping the existing early exits on load failures.
- Around line 88-120: The centralized validator sshm0_validate_server currently
misses timeout validation—update its signature to accept a 6th argument
(_timeout) and validate it as a numeric, non-negative integer in an acceptable
range (e.g., integer >= 0 or >=1 depending on desired semantics) to prevent
injecting invalid values into SSH ConnectTimeout; if invalid, print a clear
error and return non-zero. Then update the callers (bin/add and bin/edit) to
pass the timeout as the 6th parameter when calling sshm0_validate_server so
validation runs for saved server entries.

In `@sshm0`:
- Line 13: The subcommand declarations for parseArger (the one-of list in the
parser directive) and the user-facing help text are out of sync: the parser
includes "remove" while the declaration on the parseArger line shown omits it,
and the help text near the help block (around the existing "what to do"
description) also omits several supported commands ("config", "import",
"history", "backup", "remove"). Update the parseArger one-of list to include any
missing subcommands (add "remove" if absent) and update the help text string to
enumerate the exact same set of subcommands used by the runtime parser (ensure
"config", "import", "history", "backup", and "remove" are listed), keeping the
canonical set of commands consistent between the parseArger directive and the
help output.

In `@utils/install`:
- Around line 137-144: The --quiet) case currently only checks argument count
and can consume option-like tokens; update the guard in the --quiet) branch to
also reject $2 when it begins with '-' or is not a numeric level: replace the
existing if [ $# -lt 2 ]; then ... else ... block with a check like if [ $# -lt
2 ] || [ "${2#-}" != "$2" ] || ! printf '%s' "$2" | grep -Eq '^[0-9]+$'; then
decrement _verbose_level as before; else assign _verbose_level="-$2", shift, and
continue. Refer to the --quiet) case and the _verbose_level variable to locate
and apply this change.

---

Outside diff comments:
In `@bin/edit`:
- Around line 367-390: The interactive edit flow is missing the timeout prompt
so users can't change server timeout; add a prompt like the others in the same
block to read and set _arg_timeout using the existing stored value
sshm0_server_timeout as the default (e.g., read -rp "Timeout in seconds
[$sshm0_server_timeout]: " _arg_timeout;
_arg_timeout="${_arg_timeout:-$sshm0_server_timeout}"), and ensure subsequent
code that writes/uses _arg_timeout matches how other fields (like _arg_port,
_arg_proxy) are handled so the edited timeout is persisted.

In `@completely.yaml`:
- Around line 1-17: Update the top-level sshm0 command list to include the
missing commands by adding "tags" and "history" to the array under the sshm0 key
so the root completion includes sshm0 tags and sshm0 history; locate the sshm0
top-level list (containing list, add, config, ...) and insert "tags" and
"history" alongside the existing entries.

---

Nitpick comments:
In `@bin/remove`:
- Line 225: The removal call using rm "$(sshm0_server_config_path "$_arg_name")"
currently runs silently and lacks error handling; update the block that calls
sshm0_server_config_path with _arg_name (and respects the --yes flow) to test
rm's success and report back: first check whether the target exists, run rm and
capture its exit status, on non-zero exit print a clear error (including the
path and exit/status message) similar to the existing "not found" error, and on
success print a confirmation like "Removed <path>"; ensure errors from rm are
not swallowed so callers and CI see failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1d9d77af-1ca9-4ff2-9954-25affcc48d25

📥 Commits

Reviewing files that changed from the base of the PR and between 21beafc and e2af43d.

⛔ Files ignored due to path filters (1)
  • bin/tags is excluded by !**/tags, !**/TAGS
📒 Files selected for processing (22)
  • bin/add
  • bin/backup
  • bin/config
  • bin/connect
  • bin/cp
  • bin/doctor
  • bin/edit
  • bin/export
  • bin/history
  • bin/import
  • bin/list
  • bin/ping
  • bin/remove
  • bin/rsync
  • bin/show
  • bin/utils
  • completely.bash
  • completely.yaml
  • server.dist
  • sshm0
  • utils/get_sshm0
  • utils/install

Comment thread bin/add
Comment thread bin/backup
Comment thread bin/backup
Comment thread bin/config Outdated
Comment thread bin/config Outdated
Comment thread bin/import Outdated
Comment thread bin/utils
Comment thread bin/utils
Comment thread sshm0 Outdated
Comment thread utils/install
- bin/utils: add sshm0_validate_server and sshm0_get_proxy_args
- bin/add: add --timeout, --proxy/-J, --group/-g options
- bin/edit: pass through timeout, proxy, group to add
- bin/connect: use server timeout and ProxyJump
- bin/cp, bin/rsync: use timeout and proxy
- bin/ping: use server timeout instead of hardcoded 5
- bin/show: display timeout, proxy, group
- bin/export: output timeout comment, ProxyJump, group comment
- bin/list: add --group filter and --tree view
- bin/backup: create/restore tar.gz backups
- server.dist: add timeout, proxy, group fields
- completions: add all new options
- bin/exec: run commands on multiple servers (--tag, --group, --parallel)
- bin/update: self-update via git (--check, --force)
- bin/utils: add sshm0_encrypt_password/decrypt_password using openssl
- bin/add: encrypt passwords at rest with enc: prefix
- bin/connect/cp/rsync: decrypt passwords before use
- bin/show: display (encrypted) for encrypted passwords
- completely.zsh: full Zsh completion support for all subcommands
- sshm0.rc: detect shell type (bash/zsh) for completion
- utils/install: handle zshrc files
- documentation.md: rewrite with accurate help for all 20 subcommands
- readme.md: document all new features (import, tags, history, config,
  groups, timeout, ProxyJump, backup, exec, update, encryption, Zsh)
- sshm0: ensure all 20 subcommands registered
- completely.yaml/bash: add plugin case, rsync section, all subcommands
- bin/doctor: add optional openssl check
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant