@vibecontrols/vibe-plugin-ssh 2026.416.1

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.
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # @burdenoff/vibe-plugin-ssh
2
+
3
+ SSH connections & port forwarding plugin for [VibeControls Agent](https://www.npmjs.com/package/@vibecontrols/agent).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ vibe plugin install @burdenoff/vibe-plugin-ssh
9
+ ```
10
+
11
+ Or install globally alongside the agent:
12
+
13
+ ```bash
14
+ npm install -g @burdenoff/vibe-plugin-ssh
15
+ ```
16
+
17
+ Then register it:
18
+
19
+ ```bash
20
+ vibe plugin list # verify it shows up
21
+ ```
22
+
23
+ ## Features
24
+
25
+ - **SSH Connections** — Save, test, and manage SSH connection configs
26
+ - **Remote Execution** — Execute commands on remote servers via SSH
27
+ - **Port Forwarding** — Create and manage SSH port forwards (local → remote)
28
+ - **Real-time Output** — SSH command output streamed via Socket.IO events
29
+
30
+ ## API Routes
31
+
32
+ Once installed, the plugin registers these routes on the agent:
33
+
34
+ | Method | Path | Description |
35
+ | ------ | ----------------------------- | --------------------------- |
36
+ | GET | `/api/ssh/connections` | List all SSH connections |
37
+ | POST | `/api/ssh/connections` | Create a new SSH connection |
38
+ | POST | `/api/ssh/execute` | Execute a remote command |
39
+ | POST | `/api/ssh/test/:id` | Test an SSH connection |
40
+ | DELETE | `/api/ssh/connections/:id` | Delete a connection |
41
+ | GET | `/api/port-forward/` | List all port forwards |
42
+ | POST | `/api/port-forward/` | Create a port forward |
43
+ | POST | `/api/port-forward/:id/start` | Start forwarding |
44
+ | POST | `/api/port-forward/:id/stop` | Stop forwarding |
45
+ | DELETE | `/api/port-forward/:id` | Delete a forward |
46
+
47
+ ## CLI Commands
48
+
49
+ SSH and port forward CLI commands are built into the `vibe` CLI:
50
+
51
+ ```bash
52
+ vibe ssh list # List saved connections
53
+ vibe ssh add --name my-server ... # Add a connection
54
+ vibe ssh test -i <id> # Test connectivity
55
+ vibe ssh exec -i <id> -c "uptime" # Run remote command
56
+
57
+ vibe forward list # List port forwards
58
+ vibe forward create --local 5432 --remote-host db --remote-port 5432 --server my-server
59
+ vibe forward start -i <id> # Start forwarding
60
+ vibe forward stop -i <id> # Stop forwarding
61
+ ```
62
+
63
+ ## Requirements
64
+
65
+ - VibeControls Agent >= 1.1.0
66
+ - Node.js >= 18.0.0
67
+
68
+ ## License
69
+
70
+ Proprietary — Copyright Burdenoff Consultancy Services Pvt. Ltd.
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @burdenoff/vibe-plugin-ssh v3.0.0
3
+ *
4
+ * SSH connections, remote command execution, port forwarding,
5
+ * remote terminal sessions (ttyd on destination), and remote agent installation.
6
+ *
7
+ * Registers:
8
+ * - Elysia routes: /api/ssh/*, /api/port-forward/*
9
+ * - Session provider: "ssh" (for terminal proxy integration)
10
+ * - CLI commands: vibe ssh ...
11
+ *
12
+ * Install: vibe plugin install @burdenoff/vibe-plugin-ssh
13
+ */
14
+ import type { VibePlugin } from "./types.js";
15
+ export type { VibePlugin, HostServices, StorageProvider, EventBus, ServiceRegistry, SSHConnection, PortForward, SSHTerminalSession, RemoteAgentInstallJob, } from "./types.js";
16
+ export declare const vibePlugin: VibePlugin;
17
+ export default vibePlugin;
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,YAAY,CAAC;AAG3D,YAAY,EACV,UAAU,EACV,YAAY,EACZ,eAAe,EACf,QAAQ,EACR,eAAe,EACf,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAapB,eAAO,MAAM,UAAU,EAAE,UA6HxB,CAAC;AAEF,eAAe,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,118 @@
1
+ /**
2
+ * @burdenoff/vibe-plugin-ssh v3.0.0
3
+ *
4
+ * SSH connections, remote command execution, port forwarding,
5
+ * remote terminal sessions (ttyd on destination), and remote agent installation.
6
+ *
7
+ * Registers:
8
+ * - Elysia routes: /api/ssh/*, /api/port-forward/*
9
+ * - Session provider: "ssh" (for terminal proxy integration)
10
+ * - CLI commands: vibe ssh ...
11
+ *
12
+ * Install: vibe plugin install @burdenoff/vibe-plugin-ssh
13
+ */
14
+ // ---------------------------------------------------------------------------
15
+ // Module-level references for cleanup
16
+ // ---------------------------------------------------------------------------
17
+ let cleanupPortForwards;
18
+ let cleanupTerminals;
19
+ // ---------------------------------------------------------------------------
20
+ // Plugin definition
21
+ // ---------------------------------------------------------------------------
22
+ export const vibePlugin = {
23
+ name: "ssh",
24
+ version: "3.0.0",
25
+ description: "SSH connection management, remote terminals, port forwarding, and remote agent installation",
26
+ tags: ["backend", "cli", "integration", "provider"],
27
+ cliCommand: "ssh",
28
+ apiPrefix: "/api/ssh",
29
+ async onServerStart(app, hostServices) {
30
+ // Dynamically import route modules — ssh2 native deps only load when
31
+ // the plugin is actually activated.
32
+ const { createSSHRoutes } = await import("./routes/ssh.js");
33
+ const { createPortForwardRoutes, cleanupAllTunnels } = await import("./routes/port-forward.js");
34
+ const { createRemoteTerminalRoutes, cleanupAllTerminals, getTerminalInfo, listTerminalSessions, } = await import("./routes/remote-terminal.js");
35
+ const { createRemoteAgentInstallRoutes } = await import("./routes/remote-agent-install.js");
36
+ const { createSSHConfigScanRoutes } = await import("./routes/ssh-config-scan.js");
37
+ // Mount all route groups
38
+ app.use(createSSHRoutes(hostServices));
39
+ app.use(createPortForwardRoutes(hostServices));
40
+ app.use(createRemoteTerminalRoutes(hostServices));
41
+ app.use(createRemoteAgentInstallRoutes(hostServices));
42
+ app.use(createSSHConfigScanRoutes(hostServices));
43
+ // Stash cleanup functions
44
+ cleanupPortForwards = cleanupAllTunnels;
45
+ cleanupTerminals = cleanupAllTerminals;
46
+ // Register as a "session" provider so the agent's terminal proxy at
47
+ // /terminal/:sessionId/ws can find our SSH-forwarded ttyd ports.
48
+ // We only need to implement getTerminalInfo(); other SessionProvider
49
+ // methods are not called by the terminal proxy.
50
+ if (hostServices.serviceRegistry) {
51
+ const sshSessionProvider = {
52
+ name: "ssh",
53
+ getTerminalInfo: (sessionId) => getTerminalInfo(sessionId),
54
+ // Minimal stubs — the terminal proxy only calls getTerminalInfo
55
+ list: async () => {
56
+ return listTerminalSessions().map((s) => ({
57
+ id: s.id,
58
+ name: `ssh-terminal-${s.id.slice(0, 8)}`,
59
+ status: s.status === "active" ? "active" : "inactive",
60
+ provider: "ssh",
61
+ createdAt: s.startedAt,
62
+ }));
63
+ },
64
+ get: async (sessionId) => {
65
+ const sessions = listTerminalSessions();
66
+ const s = sessions.find((x) => x.id === sessionId);
67
+ if (!s)
68
+ return null;
69
+ return {
70
+ id: s.id,
71
+ name: `ssh-terminal-${s.id.slice(0, 8)}`,
72
+ status: s.status === "active" ? "active" : "inactive",
73
+ provider: "ssh",
74
+ createdAt: s.startedAt,
75
+ };
76
+ },
77
+ };
78
+ hostServices.serviceRegistry.registerProvider("session", sshSessionProvider, "ssh");
79
+ }
80
+ console.log(" Plugin 'ssh' v3.0.0 registered routes: /api/ssh, /api/port-forward, /api/ssh/terminal, /api/ssh/agent-install, /api/ssh/config-scan");
81
+ },
82
+ async onServerStop() {
83
+ if (cleanupTerminals) {
84
+ cleanupTerminals();
85
+ cleanupTerminals = undefined;
86
+ }
87
+ if (cleanupPortForwards) {
88
+ cleanupPortForwards();
89
+ cleanupPortForwards = undefined;
90
+ }
91
+ console.log(" Plugin 'ssh' cleaned up active connections and terminals");
92
+ },
93
+ onCliSetup(program) {
94
+ const ssh = program
95
+ .command("ssh")
96
+ .description("SSH connection and remote terminal management");
97
+ ssh
98
+ .command("list")
99
+ .description("List saved SSH connections")
100
+ .action(() => {
101
+ console.log("Use the agent API to list SSH connections: GET /api/ssh/connections");
102
+ });
103
+ ssh
104
+ .command("terminals")
105
+ .description("List active remote terminal sessions")
106
+ .action(() => {
107
+ console.log("Use the agent API to list terminal sessions: GET /api/ssh/terminal/sessions");
108
+ });
109
+ ssh
110
+ .command("install-jobs")
111
+ .description("List remote agent installation jobs")
112
+ .action(() => {
113
+ console.log("Use the agent API to list install jobs: GET /api/ssh/agent-install/jobs");
114
+ });
115
+ },
116
+ };
117
+ export default vibePlugin;
118
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Port-forwarding routes (Elysia + KV storage).
3
+ *
4
+ * Namespace: "ssh"
5
+ * Keys:
6
+ * "connections" → JSON array of SSHConnection objects (read-only here)
7
+ * "port-forwards" → JSON array of PortForward objects
8
+ */
9
+ import { Elysia } from "elysia";
10
+ import type { HostServices, PortForward } from "../types.js";
11
+ export declare function cleanupAllTunnels(): void;
12
+ export declare function createPortForwardRoutes(hostServices: HostServices): Elysia<"/api/port-forward", {
13
+ decorator: {};
14
+ store: {};
15
+ derive: {};
16
+ resolve: {};
17
+ }, {
18
+ typebox: {};
19
+ error: {};
20
+ }, {
21
+ schema: {};
22
+ standaloneSchema: {};
23
+ macro: {};
24
+ macroFn: {};
25
+ parser: {};
26
+ response: {};
27
+ }, {
28
+ api: {
29
+ "port-forward": {
30
+ get: {
31
+ body: unknown;
32
+ params: {};
33
+ query: unknown;
34
+ headers: unknown;
35
+ response: {
36
+ 200: {
37
+ portForwards: PortForward[];
38
+ };
39
+ };
40
+ };
41
+ };
42
+ };
43
+ } & {
44
+ api: {
45
+ "port-forward": {
46
+ post: {
47
+ body: unknown;
48
+ params: {};
49
+ query: unknown;
50
+ headers: unknown;
51
+ response: {
52
+ 200: {
53
+ error: string;
54
+ portForward?: undefined;
55
+ details?: undefined;
56
+ } | {
57
+ portForward: PortForward;
58
+ error?: undefined;
59
+ details?: undefined;
60
+ } | {
61
+ error: string;
62
+ details: string;
63
+ portForward?: undefined;
64
+ };
65
+ };
66
+ };
67
+ };
68
+ };
69
+ } & {
70
+ api: {
71
+ "port-forward": {
72
+ ":id": {
73
+ start: {
74
+ post: {
75
+ body: unknown;
76
+ params: {
77
+ id: string;
78
+ } & {};
79
+ query: unknown;
80
+ headers: unknown;
81
+ response: {
82
+ 422: {
83
+ type: "validation";
84
+ on: string;
85
+ summary?: string;
86
+ message?: string;
87
+ found?: unknown;
88
+ property?: string;
89
+ expected?: string;
90
+ };
91
+ };
92
+ };
93
+ };
94
+ };
95
+ };
96
+ };
97
+ } & {
98
+ api: {
99
+ "port-forward": {
100
+ ":id": {
101
+ stop: {
102
+ post: {
103
+ body: unknown;
104
+ params: {
105
+ id: string;
106
+ } & {};
107
+ query: unknown;
108
+ headers: unknown;
109
+ response: {
110
+ 200: {
111
+ error: string;
112
+ success?: undefined;
113
+ details?: undefined;
114
+ } | {
115
+ success: boolean;
116
+ error?: undefined;
117
+ details?: undefined;
118
+ } | {
119
+ error: string;
120
+ details: string;
121
+ success?: undefined;
122
+ };
123
+ 422: {
124
+ type: "validation";
125
+ on: string;
126
+ summary?: string;
127
+ message?: string;
128
+ found?: unknown;
129
+ property?: string;
130
+ expected?: string;
131
+ };
132
+ };
133
+ };
134
+ };
135
+ };
136
+ };
137
+ };
138
+ } & {
139
+ api: {
140
+ "port-forward": {
141
+ ":id": {
142
+ delete: {
143
+ body: unknown;
144
+ params: {
145
+ id: string;
146
+ } & {};
147
+ query: unknown;
148
+ headers: unknown;
149
+ response: {
150
+ 200: {
151
+ error: string;
152
+ success?: undefined;
153
+ details?: undefined;
154
+ } | {
155
+ success: boolean;
156
+ error?: undefined;
157
+ details?: undefined;
158
+ } | {
159
+ error: string;
160
+ details: string;
161
+ success?: undefined;
162
+ };
163
+ 422: {
164
+ type: "validation";
165
+ on: string;
166
+ summary?: string;
167
+ message?: string;
168
+ found?: unknown;
169
+ property?: string;
170
+ expected?: string;
171
+ };
172
+ };
173
+ };
174
+ };
175
+ };
176
+ };
177
+ }, {
178
+ derive: {};
179
+ resolve: {};
180
+ schema: {};
181
+ standaloneSchema: {};
182
+ response: {};
183
+ }, {
184
+ derive: {};
185
+ resolve: {};
186
+ schema: {};
187
+ standaloneSchema: {};
188
+ response: {};
189
+ }>;
190
+ //# sourceMappingURL=port-forward.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port-forward.d.ts","sourceRoot":"","sources":["../../src/routes/port-forward.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,KAAK,EACV,YAAY,EAEZ,WAAW,EAEZ,MAAM,aAAa,CAAC;AAgHrB,wBAAgB,iBAAiB,IAAI,IAAI,CAMxC;AAMD,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmQjE"}