hermes-ssh 0.3.2__tar.gz → 0.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/CHANGELOG.md +13 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/PKG-INFO +32 -32
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/README.md +28 -28
- hermes_ssh-0.3.4/llms.txt +59 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/pyproject.toml +4 -4
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/__init__.py +5 -1
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/config.py +3 -1
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/handlers/machines.py +1 -1
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/manager.py +185 -61
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/models.py +4 -3
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/plugin.yaml +1 -1
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/tests/test_config.py +3 -1
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/tests/test_manager.py +118 -1
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/tests/test_tools.py +9 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/uv.lock +171 -31
- hermes_ssh-0.3.2/llms.txt +0 -207
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/.github/workflows/ci.yml +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/.gitignore +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/CONTRIBUTING.md +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/LICENSE +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/SECURITY.md +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/deploy.sh +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/approval.py +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/handlers/__init__.py +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/handlers/sessions.py +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/handlers/slash.py +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/handlers/terminal.py +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/migrate.py +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/py.typed +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/schemas.py +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/storage.py +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/src/ssh_tools/utils.py +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/tests/__init__.py +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/tests/conftest.py +0 -0
- {hermes_ssh-0.3.2 → hermes_ssh-0.3.4}/tests/test_utils.py +0 -0
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
- Relax the `cryptography` lower bound to support Hermes Agent 0.19.0's pinned 46.0.7 runtime dependency.
|
|
6
|
+
- Spool background stdout and stderr to restricted files so verbose commands cannot deadlock.
|
|
7
|
+
- Keep returned large-output files available after completed sessions are closed.
|
|
8
|
+
- Redact common inline secrets from audit logs, with metadata-only and disabled modes.
|
|
9
|
+
- Default new machine registrations to the current local user instead of root.
|
|
10
|
+
- Resolve `__version__` from installed package metadata.
|
|
11
|
+
|
|
12
|
+
## [0.3.3] - 2026-07-24
|
|
13
|
+
|
|
14
|
+
- Update development dependencies to mypy 2.3.0 and pytest 9.1.1.
|
|
15
|
+
|
|
3
16
|
## [0.3.2] - 2026-07-13
|
|
4
17
|
|
|
5
18
|
- Align the packaged Hermes manifest with the release version.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hermes-ssh
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: SSH remote execution plugin for Hermes Agent
|
|
5
5
|
Project-URL: Homepage, https://github.com/TheEpTic/hermes-plugins
|
|
6
6
|
Project-URL: Repository, https://github.com/TheEpTic/hermes-plugins
|
|
@@ -20,11 +20,11 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
20
20
|
Classifier: Topic :: System :: Systems Administration
|
|
21
21
|
Classifier: Typing :: Typed
|
|
22
22
|
Requires-Python: >=3.11
|
|
23
|
-
Requires-Dist: cryptography<49,>=
|
|
23
|
+
Requires-Dist: cryptography<49,>=46.0.7
|
|
24
24
|
Provides-Extra: dev
|
|
25
25
|
Requires-Dist: black==26.5.1; extra == 'dev'
|
|
26
|
-
Requires-Dist: mypy==
|
|
27
|
-
Requires-Dist: pytest==9.
|
|
26
|
+
Requires-Dist: mypy==2.3.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest==9.1.1; extra == 'dev'
|
|
28
28
|
Description-Content-Type: text/markdown
|
|
29
29
|
|
|
30
30
|
# hermes-ssh
|
|
@@ -37,46 +37,44 @@ SSH remote execution plugin for [Hermes Agent](https://github.com/NousResearch/h
|
|
|
37
37
|
|
|
38
38
|
Run commands on remote servers, track sessions, reuse connections — all from inside Hermes.
|
|
39
39
|
|
|
40
|
-
```
|
|
40
|
+
```text
|
|
41
41
|
/ssh web1 uptime
|
|
42
|
-
ssh_machines add name=web1 host=192.168.1.50
|
|
43
|
-
ssh_sessions list
|
|
42
|
+
ssh_machines action=add name=web1 host=192.168.1.50 user=deploy
|
|
43
|
+
ssh_sessions action=list
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
##
|
|
46
|
+
## quick start
|
|
47
|
+
|
|
48
|
+
`hermes-ssh` is for **named multi-host operations**. Hermes's core SSH backend is useful for one configured remote terminal; this plugin adds a reusable machine inventory, aliases, per-command targeting, background sessions, and audit history.
|
|
47
49
|
|
|
48
|
-
>
|
|
50
|
+
> Requires Python 3.11+, Hermes Agent, and an OpenSSH client named `ssh`.
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
Install the package into the same Python environment that runs Hermes:
|
|
51
53
|
|
|
52
54
|
```bash
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
./deploy.sh
|
|
55
|
+
python -m pip install hermes-ssh
|
|
56
|
+
hermes plugins enable hermes-ssh --no-allow-tool-override
|
|
56
57
|
```
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
### Option 2: Manual symlink
|
|
59
|
+
Run `/reset` or restart Hermes, then verify:
|
|
61
60
|
|
|
62
61
|
```bash
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
python -m pip show hermes-ssh
|
|
63
|
+
hermes plugins list --enabled --plain
|
|
65
64
|
```
|
|
66
65
|
|
|
67
|
-
|
|
66
|
+
If Hermes cannot see the package, the `python` command above was not Hermes's Python. Follow the environment procedure in the repository [AGENTS.md](../AGENTS.md).
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
For source development:
|
|
70
69
|
|
|
71
70
|
```bash
|
|
72
|
-
|
|
71
|
+
git clone https://github.com/TheEpTic/hermes-plugins.git
|
|
72
|
+
cd hermes-plugins/hermes-ssh
|
|
73
|
+
./deploy.sh
|
|
74
|
+
hermes plugins enable hermes-ssh --no-allow-tool-override
|
|
73
75
|
```
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
hermes plugins enable hermes-ssh
|
|
79
|
-
```
|
|
77
|
+
Run `/reset` or restart Hermes after changing the source tree.
|
|
80
78
|
|
|
81
79
|
## Features
|
|
82
80
|
|
|
@@ -84,7 +82,7 @@ hermes plugins enable hermes-ssh
|
|
|
84
82
|
|
|
85
83
|
Execute any command on a remote machine. Commands run through `bash -c` with `pipefail`, so pipelines work correctly.
|
|
86
84
|
|
|
87
|
-
```
|
|
85
|
+
```text
|
|
88
86
|
# Synchronous (waits for completion)
|
|
89
87
|
ssh_terminal machine=web1 command="df -h"
|
|
90
88
|
|
|
@@ -97,9 +95,9 @@ ssh_terminal machine=web1 command="make -j4" timeout=300
|
|
|
97
95
|
|
|
98
96
|
**Output truncation:** When output exceeds `max_output_chars` (default: 50,000), the full output is saved under the plugin's restricted output directory and a summary with the file path is returned. The LLM can then use `read_file` to access the complete output.
|
|
99
97
|
|
|
100
|
-
**Background commands:** Long-running commands
|
|
98
|
+
**Background commands:** Long-running commands spool stdout and stderr to restricted files, avoiding pipe-buffer deadlocks. The plugin tracks the process and lets you poll for status or retrieve output later.
|
|
101
99
|
|
|
102
|
-
```
|
|
100
|
+
```text
|
|
103
101
|
# Check if still running
|
|
104
102
|
ssh_terminal poll=<session_id>
|
|
105
103
|
|
|
@@ -115,7 +113,7 @@ ssh_sessions action=read_output session_id=<session_id>
|
|
|
115
113
|
|
|
116
114
|
Register servers once, refer to them by name or alias.
|
|
117
115
|
|
|
118
|
-
```
|
|
116
|
+
```text
|
|
119
117
|
# Add a server
|
|
120
118
|
ssh_machines action=add name=web1 host=192.168.1.50 user=deploy key=~/.ssh/id_ed25519
|
|
121
119
|
|
|
@@ -138,7 +136,7 @@ Machine names must be alphanumeric with dots, hyphens, or underscores (1-64 char
|
|
|
138
136
|
|
|
139
137
|
Every command creates a session. Sessions track the PID, machine, command count, and idle time.
|
|
140
138
|
|
|
141
|
-
```
|
|
139
|
+
```text
|
|
142
140
|
# List active sessions
|
|
143
141
|
ssh_sessions action=list
|
|
144
142
|
|
|
@@ -175,10 +173,11 @@ All settings live in `src/ssh_tools/config.py` as an `SSHConfig` dataclass:
|
|
|
175
173
|
| Setting | Default | Description |
|
|
176
174
|
|---------|---------|-------------|
|
|
177
175
|
| `default_port` | 22 | SSH port for new machines |
|
|
178
|
-
| `default_user` |
|
|
176
|
+
| `default_user` | current local user | SSH user for new machines |
|
|
179
177
|
| `connect_timeout` | 5s | SSH handshake timeout |
|
|
180
178
|
| `command_timeout` | 30s | Command execution timeout |
|
|
181
179
|
| `max_output_chars` | 50,000 | Output truncation threshold |
|
|
180
|
+
| `audit_log_mode` | redacted | `redacted`, `metadata`, or `off` |
|
|
182
181
|
| `idle_check_interval` | 60s | Seconds between idle checks |
|
|
183
182
|
| `idle_timeout_minutes` | 30m | Auto-kill after this idle time |
|
|
184
183
|
| `closed_prune_hours` | 24h | Remove closed sessions after this |
|
|
@@ -219,6 +218,7 @@ See [SECURITY.md](SECURITY.md) for the full picture.
|
|
|
219
218
|
|
|
220
219
|
- `StrictHostKeyChecking=accept-new` — accepts first-seen host keys but rejects changed keys. Set to `yes` for strict production hosts.
|
|
221
220
|
- Machine credentials are encrypted at rest in `~/.hermes/ssh-tools/machines.json`. Data directory is 0o700.
|
|
221
|
+
- Audit logs redact common inline credentials by default. Use metadata mode when command text must not be stored.
|
|
222
222
|
- All commands execute with the permissions of the Hermes agent process.
|
|
223
223
|
|
|
224
224
|
**Hardening applied:**
|
|
@@ -8,46 +8,44 @@ SSH remote execution plugin for [Hermes Agent](https://github.com/NousResearch/h
|
|
|
8
8
|
|
|
9
9
|
Run commands on remote servers, track sessions, reuse connections — all from inside Hermes.
|
|
10
10
|
|
|
11
|
-
```
|
|
11
|
+
```text
|
|
12
12
|
/ssh web1 uptime
|
|
13
|
-
ssh_machines add name=web1 host=192.168.1.50
|
|
14
|
-
ssh_sessions list
|
|
13
|
+
ssh_machines action=add name=web1 host=192.168.1.50 user=deploy
|
|
14
|
+
ssh_sessions action=list
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## quick start
|
|
18
|
+
|
|
19
|
+
`hermes-ssh` is for **named multi-host operations**. Hermes's core SSH backend is useful for one configured remote terminal; this plugin adds a reusable machine inventory, aliases, per-command targeting, background sessions, and audit history.
|
|
18
20
|
|
|
19
|
-
>
|
|
21
|
+
> Requires Python 3.11+, Hermes Agent, and an OpenSSH client named `ssh`.
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
Install the package into the same Python environment that runs Hermes:
|
|
22
24
|
|
|
23
25
|
```bash
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
./deploy.sh
|
|
26
|
+
python -m pip install hermes-ssh
|
|
27
|
+
hermes plugins enable hermes-ssh --no-allow-tool-override
|
|
27
28
|
```
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
### Option 2: Manual symlink
|
|
30
|
+
Run `/reset` or restart Hermes, then verify:
|
|
32
31
|
|
|
33
32
|
```bash
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
python -m pip show hermes-ssh
|
|
34
|
+
hermes plugins list --enabled --plain
|
|
36
35
|
```
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
If Hermes cannot see the package, the `python` command above was not Hermes's Python. Follow the environment procedure in the repository [AGENTS.md](../AGENTS.md).
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
For source development:
|
|
41
40
|
|
|
42
41
|
```bash
|
|
43
|
-
|
|
42
|
+
git clone https://github.com/TheEpTic/hermes-plugins.git
|
|
43
|
+
cd hermes-plugins/hermes-ssh
|
|
44
|
+
./deploy.sh
|
|
45
|
+
hermes plugins enable hermes-ssh --no-allow-tool-override
|
|
44
46
|
```
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
hermes plugins enable hermes-ssh
|
|
50
|
-
```
|
|
48
|
+
Run `/reset` or restart Hermes after changing the source tree.
|
|
51
49
|
|
|
52
50
|
## Features
|
|
53
51
|
|
|
@@ -55,7 +53,7 @@ hermes plugins enable hermes-ssh
|
|
|
55
53
|
|
|
56
54
|
Execute any command on a remote machine. Commands run through `bash -c` with `pipefail`, so pipelines work correctly.
|
|
57
55
|
|
|
58
|
-
```
|
|
56
|
+
```text
|
|
59
57
|
# Synchronous (waits for completion)
|
|
60
58
|
ssh_terminal machine=web1 command="df -h"
|
|
61
59
|
|
|
@@ -68,9 +66,9 @@ ssh_terminal machine=web1 command="make -j4" timeout=300
|
|
|
68
66
|
|
|
69
67
|
**Output truncation:** When output exceeds `max_output_chars` (default: 50,000), the full output is saved under the plugin's restricted output directory and a summary with the file path is returned. The LLM can then use `read_file` to access the complete output.
|
|
70
68
|
|
|
71
|
-
**Background commands:** Long-running commands
|
|
69
|
+
**Background commands:** Long-running commands spool stdout and stderr to restricted files, avoiding pipe-buffer deadlocks. The plugin tracks the process and lets you poll for status or retrieve output later.
|
|
72
70
|
|
|
73
|
-
```
|
|
71
|
+
```text
|
|
74
72
|
# Check if still running
|
|
75
73
|
ssh_terminal poll=<session_id>
|
|
76
74
|
|
|
@@ -86,7 +84,7 @@ ssh_sessions action=read_output session_id=<session_id>
|
|
|
86
84
|
|
|
87
85
|
Register servers once, refer to them by name or alias.
|
|
88
86
|
|
|
89
|
-
```
|
|
87
|
+
```text
|
|
90
88
|
# Add a server
|
|
91
89
|
ssh_machines action=add name=web1 host=192.168.1.50 user=deploy key=~/.ssh/id_ed25519
|
|
92
90
|
|
|
@@ -109,7 +107,7 @@ Machine names must be alphanumeric with dots, hyphens, or underscores (1-64 char
|
|
|
109
107
|
|
|
110
108
|
Every command creates a session. Sessions track the PID, machine, command count, and idle time.
|
|
111
109
|
|
|
112
|
-
```
|
|
110
|
+
```text
|
|
113
111
|
# List active sessions
|
|
114
112
|
ssh_sessions action=list
|
|
115
113
|
|
|
@@ -146,10 +144,11 @@ All settings live in `src/ssh_tools/config.py` as an `SSHConfig` dataclass:
|
|
|
146
144
|
| Setting | Default | Description |
|
|
147
145
|
|---------|---------|-------------|
|
|
148
146
|
| `default_port` | 22 | SSH port for new machines |
|
|
149
|
-
| `default_user` |
|
|
147
|
+
| `default_user` | current local user | SSH user for new machines |
|
|
150
148
|
| `connect_timeout` | 5s | SSH handshake timeout |
|
|
151
149
|
| `command_timeout` | 30s | Command execution timeout |
|
|
152
150
|
| `max_output_chars` | 50,000 | Output truncation threshold |
|
|
151
|
+
| `audit_log_mode` | redacted | `redacted`, `metadata`, or `off` |
|
|
153
152
|
| `idle_check_interval` | 60s | Seconds between idle checks |
|
|
154
153
|
| `idle_timeout_minutes` | 30m | Auto-kill after this idle time |
|
|
155
154
|
| `closed_prune_hours` | 24h | Remove closed sessions after this |
|
|
@@ -190,6 +189,7 @@ See [SECURITY.md](SECURITY.md) for the full picture.
|
|
|
190
189
|
|
|
191
190
|
- `StrictHostKeyChecking=accept-new` — accepts first-seen host keys but rejects changed keys. Set to `yes` for strict production hosts.
|
|
192
191
|
- Machine credentials are encrypted at rest in `~/.hermes/ssh-tools/machines.json`. Data directory is 0o700.
|
|
192
|
+
- Audit logs redact common inline credentials by default. Use metadata mode when command text must not be stored.
|
|
193
193
|
- All commands execute with the permissions of the Hermes agent process.
|
|
194
194
|
|
|
195
195
|
**Hardening applied:**
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# hermes-ssh
|
|
2
|
+
|
|
3
|
+
Named multi-host SSH operations for Hermes Agent.
|
|
4
|
+
|
|
5
|
+
## install
|
|
6
|
+
|
|
7
|
+
Install into the exact Python environment that launches `hermes`:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
/path/to/hermes-python -m pip install hermes-ssh
|
|
11
|
+
hermes plugins enable hermes-ssh --no-allow-tool-override
|
|
12
|
+
hermes plugins list --enabled --plain
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Run `/reset` or restart Hermes. Do not use the monorepo URL with `hermes plugins install`.
|
|
16
|
+
|
|
17
|
+
Requirements: Python 3.11+, Hermes Agent, and OpenSSH `ssh`.
|
|
18
|
+
|
|
19
|
+
## safe setup
|
|
20
|
+
|
|
21
|
+
Ask the user for the machine name, host, SSH user, port, and key path. Never guess root access.
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
ssh_machines action=add name=web1 host=192.0.2.10 user=deploy key=~/.ssh/id_ed25519
|
|
25
|
+
ssh_machines action=test name=web1
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## tools
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
ssh_terminal machine=web1 command="df -h"
|
|
32
|
+
ssh_terminal machine=web1 command="make -j4" background=true
|
|
33
|
+
ssh_terminal poll=<session_id>
|
|
34
|
+
ssh_terminal read_output=<session_id>
|
|
35
|
+
|
|
36
|
+
ssh_machines action=list
|
|
37
|
+
ssh_machines action=inspect name=web1
|
|
38
|
+
ssh_machines action=test name=web1
|
|
39
|
+
ssh_machines action=remove name=web1
|
|
40
|
+
|
|
41
|
+
ssh_sessions action=list
|
|
42
|
+
ssh_sessions action=kill session_id=<id>
|
|
43
|
+
ssh_sessions action=cleanup
|
|
44
|
+
ssh_sessions action=prune
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Slash command:
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
/ssh
|
|
51
|
+
/ssh web1
|
|
52
|
+
/ssh web1 uptime
|
|
53
|
+
/ssh test
|
|
54
|
+
/ssh cleanup
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Large outputs are retained under the restricted output directory and returned by path. Background output is spooled to files rather than pipes. Machine records are encrypted at rest. Audit logs redact common inline credentials by default; configuration supports `redacted`, `metadata`, and `off`.
|
|
58
|
+
|
|
59
|
+
Commands run with the remote user's permissions. Use dedicated non-root accounts and least privilege.
|
|
@@ -4,12 +4,12 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hermes-ssh"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.4"
|
|
8
8
|
description = "SSH remote execution plugin for Hermes Agent"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
11
11
|
license = "MIT"
|
|
12
|
-
dependencies = ["cryptography >=
|
|
12
|
+
dependencies = ["cryptography >= 46.0.7, < 49"]
|
|
13
13
|
authors = [
|
|
14
14
|
{ name = "TheEpTic", email = "nexus@eptic.me" },
|
|
15
15
|
]
|
|
@@ -36,8 +36,8 @@ Changelog = "https://github.com/TheEpTic/hermes-plugins/blob/main/hermes-ssh/CHA
|
|
|
36
36
|
[project.optional-dependencies]
|
|
37
37
|
dev = [
|
|
38
38
|
"black==26.5.1",
|
|
39
|
-
"mypy==
|
|
40
|
-
"pytest==9.
|
|
39
|
+
"mypy==2.3.0",
|
|
40
|
+
"pytest==9.1.1",
|
|
41
41
|
]
|
|
42
42
|
|
|
43
43
|
[tool.hatch.build.targets.wheel]
|
|
@@ -10,6 +10,7 @@ Provides:
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
12
|
import logging
|
|
13
|
+
from importlib.metadata import PackageNotFoundError, version as distribution_version
|
|
13
14
|
from typing import Any
|
|
14
15
|
|
|
15
16
|
from .handlers import handle_ssh_machines, handle_ssh_sessions, handle_ssh_terminal
|
|
@@ -17,7 +18,10 @@ from .handlers.slash import create_slash_handler
|
|
|
17
18
|
from .manager import SSHManager
|
|
18
19
|
from .schemas import SSH_MACHINES_SCHEMA, SSH_SESSIONS_SCHEMA, SSH_TERMINAL_SCHEMA
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
try:
|
|
22
|
+
__version__ = distribution_version("hermes-ssh")
|
|
23
|
+
except PackageNotFoundError:
|
|
24
|
+
__version__ = "0.0.0+local"
|
|
21
25
|
__all__ = [
|
|
22
26
|
"SSH_MACHINES_SCHEMA",
|
|
23
27
|
"SSH_SESSIONS_SCHEMA",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import contextlib
|
|
6
|
+
import getpass
|
|
6
7
|
import os
|
|
7
8
|
from dataclasses import dataclass, field
|
|
8
9
|
from pathlib import Path
|
|
@@ -19,13 +20,14 @@ class SSHConfig:
|
|
|
19
20
|
|
|
20
21
|
# SSH defaults
|
|
21
22
|
default_port: int = 22
|
|
22
|
-
default_user: str =
|
|
23
|
+
default_user: str = field(default_factory=getpass.getuser)
|
|
23
24
|
connect_timeout: int = 5
|
|
24
25
|
command_timeout: int = 30
|
|
25
26
|
strict_host_key_checking: str = "accept-new"
|
|
26
27
|
|
|
27
28
|
# Output
|
|
28
29
|
max_output_chars: int = 50_000 # save to output_dir if exceeded
|
|
30
|
+
audit_log_mode: str = "redacted" # redacted, metadata, or off
|
|
29
31
|
|
|
30
32
|
# Session management
|
|
31
33
|
idle_check_interval: int = 60 # seconds between idle checks
|
|
@@ -45,7 +45,7 @@ def handle_ssh_machines(manager: SSHManager) -> Callable[[dict[str, Any]], str]:
|
|
|
45
45
|
Machine(
|
|
46
46
|
name=params["name"],
|
|
47
47
|
host=params["host"],
|
|
48
|
-
user=params.get("user"
|
|
48
|
+
user=params.get("user") or manager.config.default_user,
|
|
49
49
|
port=params.get("port", 22),
|
|
50
50
|
key=params.get("key", ""),
|
|
51
51
|
aliases=params.get("aliases", []),
|