@burdenoff/vibe-plugin-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.
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/@burdenoff/vibe-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,25 @@
1
+ import type { FastifyInstance } from "fastify";
2
+ import type { Command } from "commander";
3
+ /**
4
+ * @burdenoff/vibe-plugin-ssh
5
+ *
6
+ * SSH connections, remote command execution, and port forwarding plugin
7
+ * for the VibeControls Agent. This plugin registers:
8
+ *
9
+ * - Fastify routes: /api/ssh/*, /api/port-forward/*
10
+ * - CLI commands: vibe ssh list|add|remove|test|exec
11
+ * vibe forward list|create|start|stop|delete
12
+ *
13
+ * Install: vibe plugin install @burdenoff/vibe-plugin-ssh
14
+ */
15
+ export interface VibePlugin {
16
+ name: string;
17
+ version: string;
18
+ description?: string;
19
+ onCliSetup?: (program: Command) => void | Promise<void>;
20
+ onServerStart?: (app: FastifyInstance) => void | Promise<void>;
21
+ onServerStop?: (app: FastifyInstance) => void | Promise<void>;
22
+ }
23
+ export declare const vibePlugin: VibePlugin;
24
+ export default vibePlugin;
25
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC;;;;;;;;;;;GAWG;AAGH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D;AAED,eAAO,MAAM,UAAU,EAAE,UAsBxB,CAAC;AAEF,eAAe,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
1
+ export const vibePlugin = {
2
+ name: "ssh",
3
+ version: "1.0.0",
4
+ description: "SSH connections & port forwarding for VibeControls Agent",
5
+ async onServerStart(app) {
6
+ // Dynamically import ssh2 — this is the whole point of the plugin:
7
+ // ssh2 (with native cpu-features) is only loaded when the plugin is installed.
8
+ const { sshRoutes } = await import("./routes/ssh.js");
9
+ const { portForwardRoutes } = await import("./routes/port-forward.js");
10
+ await app.register(sshRoutes, { prefix: "/api/ssh" });
11
+ await app.register(portForwardRoutes, { prefix: "/api/port-forward" });
12
+ console.log(" 🔌 Plugin 'ssh' registered routes: /api/ssh, /api/port-forward");
13
+ },
14
+ onCliSetup(program) {
15
+ // SSH CLI commands are registered by the agent's built-in CLI for now.
16
+ // In a future version, the CLI commands will also move into this plugin.
17
+ // For now, the plugin only contributes server-side routes.
18
+ },
19
+ };
20
+ export default vibePlugin;
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA0BA,MAAM,CAAC,MAAM,UAAU,GAAe;IACpC,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE,0DAA0D;IAEvE,KAAK,CAAC,aAAa,CAAC,GAAoB;QACtC,mEAAmE;QACnE,+EAA+E;QAC/E,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACtD,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;QAEvE,MAAM,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QACtD,MAAM,GAAG,CAAC,QAAQ,CAAC,iBAAiB,EAAE,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAEvE,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;IAClF,CAAC;IAED,UAAU,CAAC,OAAgB;QACzB,uEAAuE;QACvE,yEAAyE;QACzE,2DAA2D;IAC7D,CAAC;CACF,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { FastifyPluginAsync } from "fastify";
2
+ export declare const portForwardRoutes: FastifyPluginAsync;
3
+ //# 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,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAgB7C,eAAO,MAAM,iBAAiB,EAAE,kBAuP/B,CAAC"}
@@ -0,0 +1,202 @@
1
+ import crypto from "node:crypto";
2
+ import { Client } from "ssh2";
3
+ import { createServer } from "net";
4
+ import { readFileSync } from "fs";
5
+ // Store active connections and servers
6
+ const activeConnections = new Map();
7
+ export const portForwardRoutes = async (fastify) => {
8
+ // Get all port forwards
9
+ fastify.get("/", async (_request, _reply) => {
10
+ const portForwards = fastify.db.getAllPortForwards();
11
+ return { portForwards };
12
+ });
13
+ // Create new port forward
14
+ fastify.post("/", async (request, reply) => {
15
+ const { localPort, remoteHost, remotePort, connectionId } = request.body;
16
+ try {
17
+ const existing = fastify.db
18
+ .getAllPortForwards()
19
+ .find((pf) => pf.localPort === localPort && pf.status === "active");
20
+ if (existing) {
21
+ return reply.code(409).send({ error: "Local port is already in use" });
22
+ }
23
+ const connectionConfig = fastify.db.getSSHConnection(connectionId);
24
+ if (!connectionConfig) {
25
+ return reply.code(404).send({ error: "SSH connection not found" });
26
+ }
27
+ const portForward = fastify.db.createPortForward({
28
+ id: crypto.randomUUID(),
29
+ localPort,
30
+ remoteHost,
31
+ remotePort,
32
+ serverName: connectionConfig.serverName,
33
+ connectionId,
34
+ status: "inactive",
35
+ });
36
+ return { portForward };
37
+ }
38
+ catch (error) {
39
+ return reply.code(500).send({
40
+ error: "Failed to create port forward",
41
+ details: error instanceof Error ? error.message : "Unknown error",
42
+ });
43
+ }
44
+ });
45
+ // Start port forwarding
46
+ fastify.post("/:id/start", async (request, reply) => {
47
+ const { id } = request.params;
48
+ try {
49
+ const portForward = fastify.db.getPortForward(id);
50
+ if (!portForward) {
51
+ return reply.code(404).send({ error: "Port forward not found" });
52
+ }
53
+ if (portForward.status === "active") {
54
+ return reply
55
+ .code(400)
56
+ .send({ error: "Port forward is already active" });
57
+ }
58
+ const connectionConfig = portForward.connectionId
59
+ ? fastify.db.getSSHConnection(portForward.connectionId)
60
+ : fastify.db.getSSHConnectionByName(portForward.serverName);
61
+ if (!connectionConfig) {
62
+ return reply.code(404).send({ error: "SSH connection not found" });
63
+ }
64
+ const sshClient = new Client();
65
+ const server = createServer((localSocket) => {
66
+ sshClient.forwardOut("localhost", portForward.localPort, portForward.remoteHost, portForward.remotePort, (err, stream) => {
67
+ if (err) {
68
+ localSocket.end();
69
+ console.error("Forward error:", err);
70
+ return;
71
+ }
72
+ localSocket.pipe(stream).pipe(localSocket);
73
+ localSocket.on("close", () => {
74
+ stream.end();
75
+ });
76
+ stream.on("close", () => {
77
+ localSocket.end();
78
+ });
79
+ });
80
+ });
81
+ return new Promise((resolve) => {
82
+ sshClient.on("ready", () => {
83
+ server.listen(portForward.localPort, () => {
84
+ activeConnections.set(id, { client: sshClient, server });
85
+ fastify.db.updatePortForward(id, {
86
+ status: "active",
87
+ connectionId: id,
88
+ });
89
+ fastify.io.emit("portforward:started", {
90
+ id,
91
+ localPort: portForward.localPort,
92
+ });
93
+ resolve({
94
+ success: true,
95
+ message: `Port forwarding started on localhost:${portForward.localPort}`,
96
+ });
97
+ });
98
+ server.on("error", (err) => {
99
+ sshClient.end();
100
+ resolve(reply.code(500).send({
101
+ error: "Failed to start local server",
102
+ details: err.message,
103
+ }));
104
+ });
105
+ });
106
+ sshClient.on("error", (err) => {
107
+ resolve(reply.code(500).send({
108
+ error: "SSH connection failed",
109
+ details: err.message,
110
+ }));
111
+ });
112
+ const connectConfig = {
113
+ host: connectionConfig.host,
114
+ port: connectionConfig.port,
115
+ username: connectionConfig.username,
116
+ };
117
+ if (connectionConfig.privateKeyPath) {
118
+ connectConfig.privateKey = readFileSync(connectionConfig.privateKeyPath);
119
+ }
120
+ else if (connectionConfig.password) {
121
+ connectConfig.password = connectionConfig.password;
122
+ }
123
+ sshClient.connect(connectConfig);
124
+ });
125
+ }
126
+ catch (error) {
127
+ return reply.code(500).send({
128
+ error: "Failed to start port forward",
129
+ details: error instanceof Error ? error.message : "Unknown error",
130
+ });
131
+ }
132
+ });
133
+ // Stop port forwarding
134
+ fastify.post("/:id/stop", async (request, reply) => {
135
+ const { id } = request.params;
136
+ try {
137
+ const portForward = fastify.db.getPortForward(id);
138
+ if (!portForward) {
139
+ return reply.code(404).send({ error: "Port forward not found" });
140
+ }
141
+ if (portForward.status !== "active") {
142
+ return reply.code(400).send({ error: "Port forward is not active" });
143
+ }
144
+ const active = activeConnections.get(id);
145
+ if (active) {
146
+ active.server.close();
147
+ active.client.end();
148
+ activeConnections.delete(id);
149
+ }
150
+ fastify.db.updatePortForward(id, {
151
+ status: "inactive",
152
+ connectionId: undefined,
153
+ });
154
+ fastify.io.emit("portforward:stopped", {
155
+ id,
156
+ localPort: portForward.localPort,
157
+ });
158
+ return { success: true };
159
+ }
160
+ catch (error) {
161
+ return reply.code(500).send({
162
+ error: "Failed to stop port forward",
163
+ details: error instanceof Error ? error.message : "Unknown error",
164
+ });
165
+ }
166
+ });
167
+ // Delete port forward
168
+ fastify.delete("/:id", async (request, reply) => {
169
+ const { id } = request.params;
170
+ try {
171
+ const portForward = fastify.db.getPortForward(id);
172
+ if (!portForward) {
173
+ return reply.code(404).send({ error: "Port forward not found" });
174
+ }
175
+ if (portForward.status === "active") {
176
+ const active = activeConnections.get(id);
177
+ if (active) {
178
+ active.server.close();
179
+ active.client.end();
180
+ activeConnections.delete(id);
181
+ }
182
+ }
183
+ fastify.db.deletePortForward(id);
184
+ return { success: true };
185
+ }
186
+ catch (error) {
187
+ return reply.code(500).send({
188
+ error: "Failed to delete port forward",
189
+ details: error instanceof Error ? error.message : "Unknown error",
190
+ });
191
+ }
192
+ });
193
+ // Cleanup on server close
194
+ fastify.addHook("onClose", async () => {
195
+ for (const [, { client, server }] of activeConnections) {
196
+ server.close();
197
+ client.end();
198
+ }
199
+ activeConnections.clear();
200
+ });
201
+ };
202
+ //# sourceMappingURL=port-forward.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port-forward.js","sourceRoot":"","sources":["../../src/routes/port-forward.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { FastifyPluginAsync } from "fastify";
2
+ export declare const sshRoutes: FastifyPluginAsync;
3
+ //# sourceMappingURL=ssh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh.d.ts","sourceRoot":"","sources":["../../src/routes/ssh.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAoB7C,eAAO,MAAM,SAAS,EAAE,kBAsOvB,CAAC"}
@@ -0,0 +1,184 @@
1
+ import crypto from "node:crypto";
2
+ import { Client } from "ssh2";
3
+ import { readFileSync } from "fs";
4
+ export const sshRoutes = async (fastify) => {
5
+ // Get all SSH connections
6
+ fastify.get("/connections", async (_request, _reply) => {
7
+ const connections = fastify.db.getAllSSHConnections();
8
+ const safeConnections = connections.map((conn) => ({
9
+ ...conn,
10
+ password: undefined,
11
+ privateKeyPath: conn.privateKeyPath ? "***" : undefined,
12
+ }));
13
+ return { connections: safeConnections };
14
+ });
15
+ // Create SSH connection config
16
+ fastify.post("/connections", async (request, reply) => {
17
+ const { serverName, host, port = 22, username, privateKeyPath, password, } = request.body;
18
+ try {
19
+ const connection = fastify.db.createSSHConnection({
20
+ id: crypto.randomUUID(),
21
+ serverName,
22
+ host,
23
+ port,
24
+ username,
25
+ privateKeyPath,
26
+ password,
27
+ });
28
+ return {
29
+ connection: {
30
+ ...connection,
31
+ password: undefined,
32
+ privateKeyPath: connection.privateKeyPath ? "***" : undefined,
33
+ },
34
+ };
35
+ }
36
+ catch (error) {
37
+ return reply.code(500).send({
38
+ error: "Failed to create SSH connection",
39
+ details: error instanceof Error ? error.message : "Unknown error",
40
+ });
41
+ }
42
+ });
43
+ // Execute command on remote server
44
+ fastify.post("/execute", async (request, reply) => {
45
+ const { connectionId, command, workingDirectory } = request.body;
46
+ try {
47
+ const connectionConfig = fastify.db.getSSHConnection(connectionId);
48
+ if (!connectionConfig) {
49
+ return reply.code(404).send({ error: "SSH connection not found" });
50
+ }
51
+ const conn = new Client();
52
+ let output = "";
53
+ let errorOutput = "";
54
+ return new Promise((resolve) => {
55
+ conn.on("ready", () => {
56
+ const fullCommand = workingDirectory
57
+ ? `cd ${workingDirectory} && ${command}`
58
+ : command;
59
+ conn.exec(fullCommand, (err, stream) => {
60
+ if (err) {
61
+ conn.end();
62
+ return resolve(reply.code(500).send({
63
+ error: "Failed to execute command",
64
+ details: err.message,
65
+ }));
66
+ }
67
+ stream.on("close", (code) => {
68
+ conn.end();
69
+ resolve({
70
+ output,
71
+ errorOutput,
72
+ exitCode: code,
73
+ success: code === 0,
74
+ });
75
+ });
76
+ stream.on("data", (data) => {
77
+ output += data.toString();
78
+ fastify.io.emit("ssh:output", {
79
+ connectionId,
80
+ data: data.toString(),
81
+ type: "stdout",
82
+ });
83
+ });
84
+ stream.stderr.on("data", (data) => {
85
+ errorOutput += data.toString();
86
+ fastify.io.emit("ssh:output", {
87
+ connectionId,
88
+ data: data.toString(),
89
+ type: "stderr",
90
+ });
91
+ });
92
+ });
93
+ });
94
+ conn.on("error", (err) => {
95
+ resolve(reply.code(500).send({
96
+ error: "SSH connection failed",
97
+ details: err.message,
98
+ }));
99
+ });
100
+ const connectConfig = {
101
+ host: connectionConfig.host,
102
+ port: connectionConfig.port,
103
+ username: connectionConfig.username,
104
+ };
105
+ if (connectionConfig.privateKeyPath) {
106
+ connectConfig.privateKey = readFileSync(connectionConfig.privateKeyPath);
107
+ }
108
+ else if (connectionConfig.password) {
109
+ connectConfig.password = connectionConfig.password;
110
+ }
111
+ conn.connect(connectConfig);
112
+ });
113
+ }
114
+ catch (error) {
115
+ return reply.code(500).send({
116
+ error: "Failed to execute SSH command",
117
+ details: error instanceof Error ? error.message : "Unknown error",
118
+ });
119
+ }
120
+ });
121
+ // Test SSH connection
122
+ fastify.post("/test/:connectionId", async (request, reply) => {
123
+ const { connectionId } = request.params;
124
+ try {
125
+ const connectionConfig = fastify.db.getSSHConnection(connectionId);
126
+ if (!connectionConfig) {
127
+ return reply.code(404).send({ error: "SSH connection not found" });
128
+ }
129
+ const conn = new Client();
130
+ return new Promise((resolve) => {
131
+ conn.on("ready", () => {
132
+ conn.end();
133
+ resolve({ success: true, message: "Connection successful" });
134
+ });
135
+ conn.on("error", (err) => {
136
+ resolve(reply.code(500).send({
137
+ success: false,
138
+ error: "Connection failed",
139
+ details: err.message,
140
+ }));
141
+ });
142
+ const connectConfig = {
143
+ host: connectionConfig.host,
144
+ port: connectionConfig.port,
145
+ username: connectionConfig.username,
146
+ readyTimeout: 10000,
147
+ };
148
+ if (connectionConfig.privateKeyPath) {
149
+ connectConfig.privateKey = readFileSync(connectionConfig.privateKeyPath);
150
+ }
151
+ else if (connectionConfig.password) {
152
+ connectConfig.password = connectionConfig.password;
153
+ }
154
+ conn.connect(connectConfig);
155
+ });
156
+ }
157
+ catch (error) {
158
+ return reply.code(500).send({
159
+ success: false,
160
+ error: "Failed to test connection",
161
+ details: error instanceof Error ? error.message : "Unknown error",
162
+ });
163
+ }
164
+ });
165
+ // Delete SSH connection
166
+ fastify.delete("/connections/:id", async (request, reply) => {
167
+ const { id } = request.params;
168
+ try {
169
+ const connection = fastify.db.getSSHConnection(id);
170
+ if (!connection) {
171
+ return reply.code(404).send({ error: "Connection not found" });
172
+ }
173
+ fastify.db.deleteSSHConnection(id);
174
+ return { success: true };
175
+ }
176
+ catch (error) {
177
+ return reply.code(500).send({
178
+ error: "Failed to delete connection",
179
+ details: error instanceof Error ? error.message : "Unknown error",
180
+ });
181
+ }
182
+ });
183
+ };
184
+ //# sourceMappingURL=ssh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh.js","sourceRoot":"","sources":["../../src/routes/ssh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Type declarations for Fastify decorations provided by the vibe-agent host.
3
+ * These are available at runtime when the plugin is loaded by the agent.
4
+ */
5
+ import "fastify";
6
+ import type { Server as SocketIOServer } from "socket.io";
7
+ declare module "fastify" {
8
+ interface FastifyInstance {
9
+ db: any;
10
+ io: SocketIOServer;
11
+ }
12
+ }
13
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,WAAW,CAAC;AAG1D,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,eAAe;QACvB,EAAE,EAAE,GAAG,CAAC;QACR,EAAE,EAAE,cAAc,CAAC;KACpB;CACF"}
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Type declarations for Fastify decorations provided by the vibe-agent host.
3
+ * These are available at runtime when the plugin is loaded by the agent.
4
+ */
5
+ import "fastify";
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,SAAS,CAAC"}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@burdenoff/vibe-plugin-ssh",
3
+ "version": "1.0.0",
4
+ "main": "./dist/index.js",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=18.0.0"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "lint": "eslint ./src",
12
+ "format": "npx prettier . --write",
13
+ "format:check": "npx prettier . --check",
14
+ "type:check": "tsc --noEmit",
15
+ "clean": "rimraf dist",
16
+ "prebuild": "npm run clean",
17
+ "prepublishOnly": "npm run build",
18
+ "sanity": "npm run format:check && npm run lint && npm run type:check && npm run build"
19
+ },
20
+ "keywords": [
21
+ "vibecontrols",
22
+ "vibe",
23
+ "vibe-plugin",
24
+ "ssh",
25
+ "port-forward",
26
+ "remote-development"
27
+ ],
28
+ "author": {
29
+ "name": "Vignesh T.V",
30
+ "email": "vignesh@burdenoff.com",
31
+ "url": "https://github.com/tvvignesh"
32
+ },
33
+ "license": "SEE LICENSE IN LICENSE",
34
+ "description": "SSH connections & port forwarding plugin for VibeControls Agent",
35
+ "dependencies": {
36
+ "ssh2": "^1.16.0"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^24.0.11",
40
+ "@types/ssh2": "^1.15.5",
41
+ "commander": "^14.0.3",
42
+ "eslint": "^9.30.1",
43
+ "fastify": "^5.7.4",
44
+ "prettier": "^3.6.2",
45
+ "rimraf": "^6.0.1",
46
+ "socket.io": "^4.8.3",
47
+ "typescript": "^5.8.3"
48
+ },
49
+ "peerDependencies": {
50
+ "@burdenoff/vibe-agent": ">=1.1.0"
51
+ },
52
+ "peerDependenciesMeta": {
53
+ "@burdenoff/vibe-agent": {
54
+ "optional": true
55
+ }
56
+ },
57
+ "trustedDependencies": [
58
+ "cpu-features",
59
+ "ssh2"
60
+ ],
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "git+https://github.com/algoshred/vibe-plugin-ssh.git"
64
+ },
65
+ "bugs": {
66
+ "url": "https://github.com/algoshred/vibe-plugin-ssh/issues"
67
+ },
68
+ "homepage": "https://vibecontrols.com",
69
+ "publishConfig": {
70
+ "access": "public",
71
+ "registry": "https://registry.npmjs.org/"
72
+ },
73
+ "files": [
74
+ "dist/**/*",
75
+ "README.md",
76
+ "LICENSE"
77
+ ]
78
+ }