@judaharagao/opencode-ssh 1.0.0

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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +184 -0
  3. package/dist/config/defaults.d.ts +11 -0
  4. package/dist/config/defaults.d.ts.map +1 -0
  5. package/dist/config/defaults.js +23 -0
  6. package/dist/config/defaults.js.map +1 -0
  7. package/dist/config/schema.d.ts +51 -0
  8. package/dist/config/schema.d.ts.map +1 -0
  9. package/dist/config/schema.js +41 -0
  10. package/dist/config/schema.js.map +1 -0
  11. package/dist/display/formatter.d.ts +41 -0
  12. package/dist/display/formatter.d.ts.map +1 -0
  13. package/dist/display/formatter.js +179 -0
  14. package/dist/display/formatter.js.map +1 -0
  15. package/dist/display/stream.d.ts +38 -0
  16. package/dist/display/stream.d.ts.map +1 -0
  17. package/dist/display/stream.js +102 -0
  18. package/dist/display/stream.js.map +1 -0
  19. package/dist/hooks.d.ts +13 -0
  20. package/dist/hooks.d.ts.map +1 -0
  21. package/dist/hooks.js +151 -0
  22. package/dist/hooks.js.map +1 -0
  23. package/dist/index.d.ts +7 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +19 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/security/allowlist.d.ts +23 -0
  28. package/dist/security/allowlist.d.ts.map +1 -0
  29. package/dist/security/allowlist.js +105 -0
  30. package/dist/security/allowlist.js.map +1 -0
  31. package/dist/security/blocklist.d.ts +35 -0
  32. package/dist/security/blocklist.d.ts.map +1 -0
  33. package/dist/security/blocklist.js +351 -0
  34. package/dist/security/blocklist.js.map +1 -0
  35. package/dist/security/policy.d.ts +40 -0
  36. package/dist/security/policy.d.ts.map +1 -0
  37. package/dist/security/policy.js +133 -0
  38. package/dist/security/policy.js.map +1 -0
  39. package/dist/security/validator.d.ts +32 -0
  40. package/dist/security/validator.d.ts.map +1 -0
  41. package/dist/security/validator.js +152 -0
  42. package/dist/security/validator.js.map +1 -0
  43. package/dist/ssh/audit.d.ts +47 -0
  44. package/dist/ssh/audit.d.ts.map +1 -0
  45. package/dist/ssh/audit.js +126 -0
  46. package/dist/ssh/audit.js.map +1 -0
  47. package/dist/ssh/connection.d.ts +73 -0
  48. package/dist/ssh/connection.d.ts.map +1 -0
  49. package/dist/ssh/connection.js +210 -0
  50. package/dist/ssh/connection.js.map +1 -0
  51. package/dist/ssh/executor.d.ts +49 -0
  52. package/dist/ssh/executor.d.ts.map +1 -0
  53. package/dist/ssh/executor.js +275 -0
  54. package/dist/ssh/executor.js.map +1 -0
  55. package/dist/ssh/manager.d.ts +43 -0
  56. package/dist/ssh/manager.d.ts.map +1 -0
  57. package/dist/ssh/manager.js +98 -0
  58. package/dist/ssh/manager.js.map +1 -0
  59. package/dist/ssh/sanitizer.d.ts +41 -0
  60. package/dist/ssh/sanitizer.d.ts.map +1 -0
  61. package/dist/ssh/sanitizer.js +108 -0
  62. package/dist/ssh/sanitizer.js.map +1 -0
  63. package/dist/tools.d.ts +7 -0
  64. package/dist/tools.d.ts.map +1 -0
  65. package/dist/tools.js +584 -0
  66. package/dist/tools.js.map +1 -0
  67. package/package.json +64 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Judah Aragao
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,184 @@
1
+ # opencode-ssh
2
+
3
+ SSH access plugin for OpenCode — secure remote command execution with command blocking and audit.
4
+
5
+ ## Features
6
+
7
+ - 🔐 **SSH Session Management** — Connect to multiple remote servers simultaneously
8
+ - ⚡ **Real-time Command Execution** — Execute commands with live output streaming
9
+ - 🛡️ **Security-First Design** — Destructive commands blocked 100%, risky commands require approval every time
10
+ - 📋 **Full Audit Trail** — Every command is logged with timestamps, results, and details
11
+ - 🔒 **Three Security Modes** — Full, Restricted, or Read-Only
12
+ - 📤 **File Transfer** — Upload and download files via SCP/SFTP
13
+ - 🎯 **Command Safety Checker** — Preview command safety before execution
14
+ - ⚙️ **Configurable Policies** — Add custom blocklist/allowlist patterns
15
+
16
+ ## Installation
17
+
18
+ Add to your `opencode.json`:
19
+
20
+ ```json
21
+ {
22
+ "plugin": ["@judaharagao/opencode-ssh"]
23
+ }
24
+ ```
25
+
26
+ Or with configuration:
27
+
28
+ ```json
29
+ {
30
+ "plugin": [
31
+ ["@judaharagao/opencode-ssh", {
32
+ "mode": "full",
33
+ "max_sessions": 5,
34
+ "default_timeout": 30,
35
+ "audit_enabled": true
36
+ }]
37
+ ]
38
+ }
39
+ ```
40
+
41
+ ## Configuration Options
42
+
43
+ | Option | Type | Default | Description |
44
+ |--------|------|---------|-------------|
45
+ | `mode` | `"full"` \| `"restricted"` \| `"read_only"` | `"full"` | Security mode for command execution |
46
+ | `max_sessions` | number | `5` | Maximum concurrent SSH sessions |
47
+ | `default_timeout` | number | `30` | Default command timeout in seconds |
48
+ | `audit_enabled` | boolean | `true` | Enable audit logging |
49
+ | `blocklist_extra` | string[] | `[]` | Additional regex patterns to block |
50
+ | `allowlist` | string[] | `[]` | Additional allowed patterns (restricted mode) |
51
+
52
+ ## Security Modes
53
+
54
+ ### Full Mode
55
+ All commands are allowed except those in the blocklist. Destructive commands are always blocked. Risky commands require approval.
56
+
57
+ ### Restricted Mode
58
+ Only commands in the allowlist + read-only commands are allowed. Risky and destructive commands are blocked.
59
+
60
+ ### Read-Only Mode
61
+ Only read-only commands (ls, cat, grep, docker ps, etc.) are allowed. No write operations.
62
+
63
+ ## Commands (Tools)
64
+
65
+ ### `ssh.connect`
66
+ Establish an SSH connection to a remote server.
67
+
68
+ ```
69
+ ssh.connect(host="192.168.1.100", username="admin", auth_method="key")
70
+ ```
71
+
72
+ ### `ssh.disconnect`
73
+ Close an SSH session.
74
+
75
+ ```
76
+ ssh.disconnect(session_id="ssh-abc123")
77
+ ```
78
+
79
+ ### `ssh.list_sessions`
80
+ List all active SSH sessions.
81
+
82
+ ```
83
+ ssh.list_sessions()
84
+ ```
85
+
86
+ ### `ssh.exec`
87
+ Execute a command on a remote server.
88
+
89
+ ```
90
+ ssh.exec(session_id="prod-server", command="docker ps -a")
91
+ ```
92
+
93
+ ### `ssh.exec_batch`
94
+ Execute multiple commands in sequence.
95
+
96
+ ```
97
+ ssh.exec_batch(session_id="prod-server", commands="cd /app\nls -la\ndocker ps")
98
+ ```
99
+
100
+ ### `ssh.upload`
101
+ Upload a file via SCP.
102
+
103
+ ```
104
+ ssh.upload(session_id="prod-server", local_path="./config.yml", remote_path="/app/config.yml")
105
+ ```
106
+
107
+ ### `ssh.download`
108
+ Download a file via SCP.
109
+
110
+ ```
111
+ ssh.download(session_id="prod-server", remote_path="/var/log/app.log", local_path="./app.log")
112
+ ```
113
+
114
+ ### `ssh.check_command`
115
+ Check if a command is safe (dry-run).
116
+
117
+ ```
118
+ ssh.check_command(command="rm -rf /tmp/cache")
119
+ ```
120
+
121
+ ### `ssh.security_policy`
122
+ View or modify the security policy.
123
+
124
+ ```
125
+ ssh.security_policy(action="view")
126
+ ssh.security_policy(action="add_blocklist", pattern="custom-dangerous-.*")
127
+ ```
128
+
129
+ ### `ssh.audit_log`
130
+ View the command audit trail.
131
+
132
+ ```
133
+ ssh.audit_log(limit=20)
134
+ ssh.audit_log(session_id="prod-server", command_filter="docker")
135
+ ```
136
+
137
+ ## Security
138
+
139
+ ### Destructive Commands (100% Blocked)
140
+ These commands are **permanently blocked** with no exceptions:
141
+
142
+ - `rm -rf /`, `rm -rf ~`, `rm -rf .*`
143
+ - `mkfs`, `dd if=/dev/zero`
144
+ - Fork bombs (`:(){:|:&};:`)
145
+ - `chmod -R 777 /`, `chmod -R 000 /`
146
+ - `shutdown`, `reboot`, `init 0/6`
147
+ - `kill -9 1`, `killall`
148
+ - `iptables -F`, `ufw disable`
149
+ - `wget/curl | sh|bash`
150
+
151
+ ### Risky Commands (Approval Required Every Time)
152
+ These commands require your explicit approval each time:
153
+
154
+ - `DROP TABLE`, `DELETE FROM`, `TRUNCATE`
155
+ - `sudo su`, `sudo -i`
156
+ - `systemctl stop/disable`
157
+ - `kill -9`, `kill -15`
158
+ - `npm uninstall -g`, `apt remove/purge`
159
+ - `userdel`, `groupdel`
160
+ - `iptables -A/-D`
161
+
162
+ ### Credential Safety
163
+ - Passwords and SSH keys are **never** stored in logs or output
164
+ - Session info only contains host, username, and port
165
+ - Credentials are held in memory only during the session
166
+ - All sessions are destroyed when the plugin is disposed
167
+
168
+ ## Audit Log
169
+
170
+ All commands are logged in `.opencode-ssh/audit.jsonl` with:
171
+
172
+ - Timestamp
173
+ - Session ID (host@user)
174
+ - Command executed
175
+ - Result (success/blocked/approved/error)
176
+ - Exit code
177
+ - Duration
178
+ - Matched security rule (if any)
179
+
180
+ View the audit log with `ssh.audit_log`.
181
+
182
+ ## License
183
+
184
+ MIT
@@ -0,0 +1,11 @@
1
+ import { type SshPluginConfigType } from "./schema.js";
2
+ /**
3
+ * Get merged configuration with user overrides.
4
+ */
5
+ export declare function resolveConfig(userConfig?: Record<string, unknown>): SshPluginConfigType;
6
+ /**
7
+ * Get the SSH data directory path for a project.
8
+ * Stores sessions, audit logs, and policy files.
9
+ */
10
+ export declare function getSshDataDir(projectDir: string): string;
11
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEtE;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,mBAAmB,CAYvF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAExD"}
@@ -0,0 +1,23 @@
1
+ import { DEFAULT_CONFIG } from "./schema.js";
2
+ /**
3
+ * Get merged configuration with user overrides.
4
+ */
5
+ export function resolveConfig(userConfig) {
6
+ if (!userConfig)
7
+ return { ...DEFAULT_CONFIG };
8
+ const merged = { ...DEFAULT_CONFIG };
9
+ for (const [key, value] of Object.entries(userConfig)) {
10
+ if (value !== undefined && value !== null) {
11
+ merged[key] = value;
12
+ }
13
+ }
14
+ return merged;
15
+ }
16
+ /**
17
+ * Get the SSH data directory path for a project.
18
+ * Stores sessions, audit logs, and policy files.
19
+ */
20
+ export function getSshDataDir(projectDir) {
21
+ return `${projectDir}/.opencode-ssh`;
22
+ }
23
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA4B,MAAM,aAAa,CAAA;AAEtE;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,UAAoC;IAChE,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,GAAG,cAAc,EAAE,CAAA;IAE7C,MAAM,MAAM,GAA4B,EAAE,GAAG,cAAc,EAAE,CAAA;IAE7D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACtD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QACrB,CAAC;IACH,CAAC;IAED,OAAO,MAA6B,CAAA;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,UAAkB;IAC9C,OAAO,GAAG,UAAU,gBAAgB,CAAA;AACtC,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Security mode for SSH command execution.
4
+ * - "full": All commands allowed except blocklist
5
+ * - "restricted": Only allowlist + read-only commands
6
+ * - "read_only": Only read-only commands (ls, cat, grep, etc.)
7
+ */
8
+ export declare const SecurityMode: z.ZodEnum<["full", "restricted", "read_only"]>;
9
+ export type SecurityMode = z.infer<typeof SecurityMode>;
10
+ /**
11
+ * Configuration schema for the opencode-ssh plugin.
12
+ */
13
+ export declare const SshPluginConfig: z.ZodObject<{
14
+ /** Security mode for command execution */
15
+ mode: z.ZodDefault<z.ZodEnum<["full", "restricted", "read_only"]>>;
16
+ /** Maximum concurrent SSH sessions */
17
+ max_sessions: z.ZodDefault<z.ZodNumber>;
18
+ /** Default command timeout in seconds */
19
+ default_timeout: z.ZodDefault<z.ZodNumber>;
20
+ /** Whether to enable audit logging */
21
+ audit_enabled: z.ZodDefault<z.ZodBoolean>;
22
+ /** Additional command patterns to block (regex strings) */
23
+ blocklist_extra: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
24
+ /** Additional command patterns to allow (used in restricted mode) */
25
+ allowlist: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
26
+ /** Path to SSH config file (~/.ssh/config) */
27
+ ssh_config_path: z.ZodOptional<z.ZodString>;
28
+ /** Auto-connect on plugin boot (requires saved session) */
29
+ auto_connect: z.ZodDefault<z.ZodBoolean>;
30
+ }, "strict", z.ZodTypeAny, {
31
+ mode: "full" | "restricted" | "read_only";
32
+ max_sessions: number;
33
+ default_timeout: number;
34
+ audit_enabled: boolean;
35
+ blocklist_extra: string[];
36
+ allowlist: string[];
37
+ auto_connect: boolean;
38
+ ssh_config_path?: string | undefined;
39
+ }, {
40
+ mode?: "full" | "restricted" | "read_only" | undefined;
41
+ max_sessions?: number | undefined;
42
+ default_timeout?: number | undefined;
43
+ audit_enabled?: boolean | undefined;
44
+ blocklist_extra?: string[] | undefined;
45
+ allowlist?: string[] | undefined;
46
+ ssh_config_path?: string | undefined;
47
+ auto_connect?: boolean | undefined;
48
+ }>;
49
+ export type SshPluginConfigType = z.infer<typeof SshPluginConfig>;
50
+ export declare const DEFAULT_CONFIG: SshPluginConfigType;
51
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;GAKG;AACH,eAAO,MAAM,YAAY,gDAA8C,CAAA;AACvE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AAEvD;;GAEG;AACH,eAAO,MAAM,eAAe;IAExB,0CAA0C;;IAG1C,sCAAsC;;IAGtC,yCAAyC;;IAGzC,sCAAsC;;IAGtC,2DAA2D;;IAG3D,qEAAqE;;IAGrE,8CAA8C;;IAG9C,2DAA2D;;;;;;;;;;;;;;;;;;;;EAGpD,CAAA;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAEjE,eAAO,MAAM,cAAc,EAAE,mBAQ5B,CAAA"}
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Security mode for SSH command execution.
4
+ * - "full": All commands allowed except blocklist
5
+ * - "restricted": Only allowlist + read-only commands
6
+ * - "read_only": Only read-only commands (ls, cat, grep, etc.)
7
+ */
8
+ export const SecurityMode = z.enum(["full", "restricted", "read_only"]);
9
+ /**
10
+ * Configuration schema for the opencode-ssh plugin.
11
+ */
12
+ export const SshPluginConfig = z
13
+ .object({
14
+ /** Security mode for command execution */
15
+ mode: SecurityMode.default("full"),
16
+ /** Maximum concurrent SSH sessions */
17
+ max_sessions: z.number().int().min(1).max(50).default(5),
18
+ /** Default command timeout in seconds */
19
+ default_timeout: z.number().int().min(1).max(600).default(30),
20
+ /** Whether to enable audit logging */
21
+ audit_enabled: z.boolean().default(true),
22
+ /** Additional command patterns to block (regex strings) */
23
+ blocklist_extra: z.array(z.string()).default([]),
24
+ /** Additional command patterns to allow (used in restricted mode) */
25
+ allowlist: z.array(z.string()).default([]),
26
+ /** Path to SSH config file (~/.ssh/config) */
27
+ ssh_config_path: z.string().optional(),
28
+ /** Auto-connect on plugin boot (requires saved session) */
29
+ auto_connect: z.boolean().default(false),
30
+ })
31
+ .strict();
32
+ export const DEFAULT_CONFIG = {
33
+ mode: "full",
34
+ max_sessions: 5,
35
+ default_timeout: 30,
36
+ audit_enabled: true,
37
+ blocklist_extra: [],
38
+ allowlist: [],
39
+ auto_connect: false,
40
+ };
41
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC,CAAA;AAGvE;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC;KAC7B,MAAM,CAAC;IACN,0CAA0C;IAC1C,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC;IAElC,sCAAsC;IACtC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAExD,yCAAyC;IACzC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAE7D,sCAAsC;IACtC,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAExC,2DAA2D;IAC3D,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAEhD,qEAAqE;IACrE,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAE1C,8CAA8C;IAC9C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAEtC,2DAA2D;IAC3D,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CACzC,CAAC;KACD,MAAM,EAAE,CAAA;AAIX,MAAM,CAAC,MAAM,cAAc,GAAwB;IACjD,IAAI,EAAE,MAAM;IACZ,YAAY,EAAE,CAAC;IACf,eAAe,EAAE,EAAE;IACnB,aAAa,EAAE,IAAI;IACnB,eAAe,EAAE,EAAE;IACnB,SAAS,EAAE,EAAE;IACb,YAAY,EAAE,KAAK;CACpB,CAAA"}
@@ -0,0 +1,41 @@
1
+ import type { ExecResult } from "../ssh/executor.js";
2
+ import type { SshConnectionInfo } from "../ssh/connection.js";
3
+ /**
4
+ * Format an SSH execution result for display in the terminal.
5
+ */
6
+ export declare function formatExecResult(result: ExecResult): string;
7
+ /**
8
+ * Format a session list for display.
9
+ */
10
+ export declare function formatSessionList(sessions: SshConnectionInfo[]): string;
11
+ /**
12
+ * Format a connection success message.
13
+ */
14
+ export declare function formatConnectResult(sessionId: string, host: string, port: number, username: string, alias?: string): string;
15
+ /**
16
+ * Format a disconnection message.
17
+ */
18
+ export declare function formatDisconnectResult(sessionId: string): string;
19
+ /**
20
+ * Format a blocked command message.
21
+ */
22
+ export declare function formatBlockedCommand(command: string, reason: string, level: "destructive" | "risky"): string;
23
+ /**
24
+ * Format a command check result (dry-run validation).
25
+ */
26
+ export declare function formatCheckResult(command: string, validation: {
27
+ safe: boolean;
28
+ level: string;
29
+ reason?: string;
30
+ matched_rule?: string;
31
+ }): string;
32
+ /**
33
+ * Format a security policy for display.
34
+ */
35
+ export declare function formatSecurityPolicy(policy: {
36
+ mode: string;
37
+ extraBlocklist: string[];
38
+ customAllowlist: string[];
39
+ updatedAt: string;
40
+ }): string;
41
+ //# sourceMappingURL=formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/display/formatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAE7D;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CA+C3D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAsBvE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,CAWR;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,aAAa,GAAG,OAAO,GAC7B,MAAM,CAqBR;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GACnF,MAAM,CAmBR;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,MAAM,CAuCT"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Format an SSH execution result for display in the terminal.
3
+ */
4
+ export function formatExecResult(result) {
5
+ const lines = [];
6
+ // ── Header with session and command info ──
7
+ const durationStr = result.duration < 1000
8
+ ? `${result.duration}ms`
9
+ : `${(result.duration / 1000).toFixed(1)}s`;
10
+ const exitIcon = result.exitCode === 0 ? "✅" : "❌";
11
+ lines.push(`### SSH Execution [${result.sessionId}]`);
12
+ lines.push("");
13
+ // Command
14
+ lines.push(`**$ ${result.command}**`);
15
+ if (result.validation.level === "risky") {
16
+ lines.push(`⚠️ *Risky command — executed with user approval*`);
17
+ }
18
+ lines.push("");
19
+ // stdout
20
+ if (result.stdout) {
21
+ const trimmed = result.stdout.trim();
22
+ if (trimmed.length > 0) {
23
+ lines.push("**Output:**");
24
+ lines.push("```");
25
+ lines.push(trimmed);
26
+ lines.push("```");
27
+ }
28
+ }
29
+ // stderr
30
+ if (result.stderr) {
31
+ const trimmed = result.stderr.trim();
32
+ if (trimmed.length > 0) {
33
+ lines.push("**Errors:**");
34
+ lines.push("```");
35
+ lines.push(trimmed);
36
+ lines.push("```");
37
+ }
38
+ }
39
+ // Footer with exit code and duration
40
+ lines.push(`${exitIcon} Exit: ${result.exitCode ?? "?"} | Duration: ${durationStr}`);
41
+ return lines.join("\n");
42
+ }
43
+ /**
44
+ * Format a session list for display.
45
+ */
46
+ export function formatSessionList(sessions) {
47
+ if (sessions.length === 0) {
48
+ return "📋 No active SSH sessions.";
49
+ }
50
+ const lines = [`## Active SSH Sessions (${sessions.length})\n`];
51
+ for (const session of sessions) {
52
+ const status = session.connected ? "🟢 Connected" : "🔴 Disconnected";
53
+ const alias = session.config.alias ? ` (${session.config.alias})` : "";
54
+ const uptime = session.connectedAt
55
+ ? formatUptime(new Date(session.connectedAt))
56
+ : "N/A";
57
+ lines.push(`- **${session.id}**${alias}: ${session.config.username}@${session.config.host}:${session.config.port} — ${status}`);
58
+ lines.push(` Uptime: ${uptime} | Auth: ${session.config.authMethod}`);
59
+ lines.push("");
60
+ }
61
+ return lines.join("\n");
62
+ }
63
+ /**
64
+ * Format a connection success message.
65
+ */
66
+ export function formatConnectResult(sessionId, host, port, username, alias) {
67
+ const aliasStr = alias ? ` ("${alias}")` : "";
68
+ return [
69
+ `## SSH Connected${aliasStr}`,
70
+ "",
71
+ `- **Session:** \`${sessionId}\``,
72
+ `- **Host:** ${username}@${host}:${port}`,
73
+ `- **Status:** 🟢 Connected`,
74
+ "",
75
+ `Use \`ssh.exec\` with session_id=\`${sessionId}\` to run commands.`,
76
+ ].join("\n");
77
+ }
78
+ /**
79
+ * Format a disconnection message.
80
+ */
81
+ export function formatDisconnectResult(sessionId) {
82
+ return `## SSH Disconnected\n\nSession \`${sessionId}\` has been closed.`;
83
+ }
84
+ /**
85
+ * Format a blocked command message.
86
+ */
87
+ export function formatBlockedCommand(command, reason, level) {
88
+ if (level === "destructive") {
89
+ return [
90
+ "## 🚫 Command Blocked (Destructive)",
91
+ "",
92
+ `**Command:** \`${command}\``,
93
+ `**Reason:** ${reason}`,
94
+ "",
95
+ "This command is **permanently blocked** and cannot be overridden.",
96
+ "Destructive commands are blocked for your safety.",
97
+ ].join("\n");
98
+ }
99
+ return [
100
+ "## ⚠️ Command Requires Approval",
101
+ "",
102
+ `**Command:** \`${command}\``,
103
+ `**Reason:** ${reason}`,
104
+ "",
105
+ "This command has been classified as risky and requires your approval.",
106
+ ].join("\n");
107
+ }
108
+ /**
109
+ * Format a command check result (dry-run validation).
110
+ */
111
+ export function formatCheckResult(command, validation) {
112
+ const icon = validation.safe ? "✅" : validation.level === "destructive" ? "🚫" : "⚠️";
113
+ const lines = [
114
+ `## Command Safety Check`,
115
+ "",
116
+ `**Command:** \`${command}\``,
117
+ `**Status:** ${icon} ${validation.safe ? "Safe" : validation.level === "destructive" ? "BLOCKED" : "Requires Approval"}`,
118
+ ];
119
+ if (validation.reason) {
120
+ lines.push(`**Reason:** ${validation.reason}`);
121
+ }
122
+ if (validation.matched_rule) {
123
+ lines.push(`**Rule:** ${validation.matched_rule}`);
124
+ }
125
+ return lines.join("\n");
126
+ }
127
+ /**
128
+ * Format a security policy for display.
129
+ */
130
+ export function formatSecurityPolicy(policy) {
131
+ const lines = [
132
+ "## SSH Security Policy",
133
+ "",
134
+ `**Mode:** \`${policy.mode}\``,
135
+ `**Last Updated:** ${policy.updatedAt}`,
136
+ "",
137
+ ];
138
+ if (policy.extraBlocklist.length > 0) {
139
+ lines.push("### Extra Blocklist Patterns");
140
+ for (const p of policy.extraBlocklist) {
141
+ lines.push(`- \`${p}\``);
142
+ }
143
+ lines.push("");
144
+ }
145
+ if (policy.customAllowlist.length > 0) {
146
+ lines.push("### Custom Allowlist Patterns");
147
+ for (const p of policy.customAllowlist) {
148
+ lines.push(`- \`${p}\``);
149
+ }
150
+ lines.push("");
151
+ }
152
+ lines.push("### Mode Description");
153
+ switch (policy.mode) {
154
+ case "full":
155
+ lines.push("All commands allowed except those in the blocklist.");
156
+ break;
157
+ case "restricted":
158
+ lines.push("Only commands in the allowlist + read-only commands are allowed.");
159
+ break;
160
+ case "read_only":
161
+ lines.push("Only read-only commands are allowed (ls, cat, grep, etc.).");
162
+ break;
163
+ }
164
+ return lines.join("\n");
165
+ }
166
+ // ── Helpers ──
167
+ function formatUptime(connectedAt) {
168
+ const now = Date.now();
169
+ const diff = now - connectedAt.getTime();
170
+ const seconds = Math.floor(diff / 1000);
171
+ const minutes = Math.floor(seconds / 60);
172
+ const hours = Math.floor(minutes / 60);
173
+ if (hours > 0)
174
+ return `${hours}h ${minutes % 60}m`;
175
+ if (minutes > 0)
176
+ return `${minutes}m ${seconds % 60}s`;
177
+ return `${seconds}s`;
178
+ }
179
+ //# sourceMappingURL=formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/display/formatter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Real-time SSH output stream handler.
3
+ * Formats and prepares output chunks for display as they arrive.
4
+ */
5
+ export interface StreamChunk {
6
+ /** Type of output */
7
+ type: "stdout" | "stderr" | "info" | "error";
8
+ /** The data chunk */
9
+ data: string;
10
+ /** Timestamp */
11
+ timestamp: number;
12
+ /** Session identifier */
13
+ sessionId: string;
14
+ }
15
+ /**
16
+ * Create a stream handler that collects and formats output chunks.
17
+ */
18
+ export declare function createStreamHandler(sessionId: string): {
19
+ chunks: StreamChunk[];
20
+ onStdout: (data: string) => void;
21
+ onStderr: (data: string) => void;
22
+ onInfo: (data: string) => void;
23
+ onError: (data: string) => void;
24
+ getOutput: () => {
25
+ stdout: string;
26
+ stderr: string;
27
+ };
28
+ formatOutput: () => string;
29
+ };
30
+ /**
31
+ * Format a progress indicator for long-running commands.
32
+ */
33
+ export declare function formatProgress(sessionId: string, command: string, elapsed: number): string;
34
+ /**
35
+ * Format a timeout warning.
36
+ */
37
+ export declare function formatTimeout(sessionId: string, command: string, timeout: number): string;
38
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/display/stream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,qBAAqB;IACrB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;IAC5C,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG;IACtD,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,SAAS,EAAE,MAAM;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACnD,YAAY,EAAE,MAAM,MAAM,CAAA;CAC3B,CAgFA;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAO1F;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAUzF"}