supbuddy 3.0.4 → 3.0.5
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/dist/bin.js +2 -2
- package/dist/lib.d.ts +75 -0
- package/dist/lib.js +393 -0
- package/package.json +5 -2
package/dist/bin.js
CHANGED
|
@@ -9196,9 +9196,9 @@ var require_mime_db = __commonJS({
|
|
|
9196
9196
|
}
|
|
9197
9197
|
});
|
|
9198
9198
|
|
|
9199
|
-
// ../../node_modules/mime-types/index.js
|
|
9199
|
+
// ../../node_modules/accepts/node_modules/mime-types/index.js
|
|
9200
9200
|
var require_mime_types = __commonJS({
|
|
9201
|
-
"../../node_modules/mime-types/index.js"(exports) {
|
|
9201
|
+
"../../node_modules/accepts/node_modules/mime-types/index.js"(exports) {
|
|
9202
9202
|
"use strict";
|
|
9203
9203
|
var db = require_mime_db();
|
|
9204
9204
|
var extname = __require("path").extname;
|
package/dist/lib.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
interface Attach {
|
|
2
|
+
url?: string;
|
|
3
|
+
token?: string;
|
|
4
|
+
stateDir?: string;
|
|
5
|
+
timeoutMs?: number;
|
|
6
|
+
}
|
|
7
|
+
declare class DaemonClient {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
private token;
|
|
10
|
+
private timeoutMs;
|
|
11
|
+
private id;
|
|
12
|
+
constructor(baseUrl: string, token: string, timeoutMs?: number);
|
|
13
|
+
private rpc;
|
|
14
|
+
call(tool: string, args?: object): Promise<any>;
|
|
15
|
+
stream(tool: string, args: object, onEvent: (e: any) => void, signal?: AbortSignal): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
declare function connect(a: Attach): Promise<DaemonClient>;
|
|
18
|
+
|
|
19
|
+
interface DaemonInfo {
|
|
20
|
+
pid: number;
|
|
21
|
+
socketPort: number;
|
|
22
|
+
mcpPort: number;
|
|
23
|
+
stateDir: string;
|
|
24
|
+
bootToken: string;
|
|
25
|
+
startedAt: string;
|
|
26
|
+
/** Port of the Socket.IO native-relay server (socketPort + 1 by default). */
|
|
27
|
+
relayPort: number;
|
|
28
|
+
/** App version that spawned this daemon (== the worker's version). Stamped from
|
|
29
|
+
* SUPBUDDY_APP_VERSION when a Tauri GUI ≥3.0.3 spawns it. Optional: a headless
|
|
30
|
+
* `supbuddy daemon` or an older GUI omits it. The Tauri sidecar restarts a
|
|
31
|
+
* daemon whose version differs from the app, so a GUI update reloads the worker. */
|
|
32
|
+
version?: string;
|
|
33
|
+
}
|
|
34
|
+
declare function readDaemonInfo(stateDir: string): Promise<DaemonInfo | null>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* MUST match packages/core/store.ts getAppSupportDir() — the CLI/daemon/GUI
|
|
38
|
+
* share one state dir (two-writer corruption + docs-drift hazard otherwise).
|
|
39
|
+
*/
|
|
40
|
+
declare function defaultStateDir(): string;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* completions.ts — the command tree + shell-completion generators.
|
|
44
|
+
*
|
|
45
|
+
* COMMAND_TREE is the single source of truth for what commands/subcommands the
|
|
46
|
+
* CLI accepts. It powers `supbuddy completion zsh` today, and will feed the
|
|
47
|
+
* interactive `supbuddy shell` REPL (ghost-text autosuggest) next.
|
|
48
|
+
*
|
|
49
|
+
* Keep this in sync with the dispatch in bin.ts + the `case`/`sub ===` handling
|
|
50
|
+
* in commands.ts when commands change.
|
|
51
|
+
*/
|
|
52
|
+
/** command → its subcommands (empty = no subcommands). */
|
|
53
|
+
declare const COMMAND_TREE: Record<string, string[]>;
|
|
54
|
+
/** Flags accepted (almost) everywhere. */
|
|
55
|
+
declare const GLOBAL_FLAGS: string[];
|
|
56
|
+
declare const TOP_LEVEL: string[];
|
|
57
|
+
/**
|
|
58
|
+
* Which `<module>:<action>` combos take a single resolvable target as their
|
|
59
|
+
* first arg, and where the candidate list comes from. Used by the interactive
|
|
60
|
+
* picker's "smart args" step (pick a project/mapping instead of erroring on a
|
|
61
|
+
* missing arg). Only single-target actions are listed; multi-arg actions
|
|
62
|
+
* (e.g. `scripts start <project> <script>`) are intentionally omitted for now.
|
|
63
|
+
*/
|
|
64
|
+
type ArgSource = 'projects' | 'mappings' | 'agents' | 'clients';
|
|
65
|
+
declare const ARG_SOURCE: Record<string, ArgSource>;
|
|
66
|
+
declare function argSourceFor(module: string, action: string): ArgSource | null;
|
|
67
|
+
/**
|
|
68
|
+
* Short, human descriptions for modules and `module:action` combos — surfaced by
|
|
69
|
+
* the interactive picker so you know what each does. Keep concise (one line).
|
|
70
|
+
*/
|
|
71
|
+
declare const DESCRIPTIONS: Record<string, string>;
|
|
72
|
+
/** Description for a module, or a `module action` combo (falls back to ''). */
|
|
73
|
+
declare function describe(module: string, action?: string): string;
|
|
74
|
+
|
|
75
|
+
export { ARG_SOURCE, type ArgSource, type Attach, COMMAND_TREE, DESCRIPTIONS, DaemonClient, type DaemonInfo, GLOBAL_FLAGS, TOP_LEVEL, argSourceFor, connect, defaultStateDir, describe, readDaemonInfo };
|
package/dist/lib.js
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __supbuddyCreateRequire } from 'module';
|
|
3
|
+
const require = __supbuddyCreateRequire(import.meta.url);
|
|
4
|
+
|
|
5
|
+
// src/daemon-json.ts
|
|
6
|
+
import fs from "fs/promises";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import { execFileSync } from "child_process";
|
|
9
|
+
function isDaemonInfo(o) {
|
|
10
|
+
return !!o && typeof o === "object" && typeof o.pid === "number" && typeof o.socketPort === "number" && typeof o.mcpPort === "number" && typeof o.stateDir === "string" && typeof o.bootToken === "string" && typeof o.startedAt === "string" && typeof o.relayPort === "number" && (o.version === void 0 || typeof o.version === "string");
|
|
11
|
+
}
|
|
12
|
+
function daemonJsonPath(stateDir) {
|
|
13
|
+
return path.join(stateDir, "daemon.json");
|
|
14
|
+
}
|
|
15
|
+
async function readDaemonInfo(stateDir) {
|
|
16
|
+
try {
|
|
17
|
+
const raw = JSON.parse(await fs.readFile(daemonJsonPath(stateDir), "utf-8"));
|
|
18
|
+
return isDaemonInfo(raw) ? raw : null;
|
|
19
|
+
} catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function isPidAlive(pid) {
|
|
24
|
+
try {
|
|
25
|
+
process.kill(pid, 0);
|
|
26
|
+
return true;
|
|
27
|
+
} catch (e) {
|
|
28
|
+
return e?.code === "EPERM";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/state-dir.ts
|
|
33
|
+
import os from "os";
|
|
34
|
+
import path2 from "path";
|
|
35
|
+
function defaultStateDir() {
|
|
36
|
+
const override = process.env.SUPBUDDY_STATE_DIR;
|
|
37
|
+
if (override) return override;
|
|
38
|
+
const home = os.homedir();
|
|
39
|
+
if (process.platform === "darwin") return path2.join(home, "Library", "Application Support", "Supbuddy");
|
|
40
|
+
if (process.platform === "win32") return path2.join(process.env.APPDATA ?? path2.join(home, "AppData", "Roaming"), "Supbuddy");
|
|
41
|
+
return path2.join(process.env.XDG_CONFIG_HOME ?? path2.join(home, ".config"), "Supbuddy");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// src/client.ts
|
|
45
|
+
var DaemonClient = class {
|
|
46
|
+
constructor(baseUrl, token, timeoutMs = 15e3) {
|
|
47
|
+
this.baseUrl = baseUrl;
|
|
48
|
+
this.token = token;
|
|
49
|
+
this.timeoutMs = timeoutMs;
|
|
50
|
+
}
|
|
51
|
+
baseUrl;
|
|
52
|
+
token;
|
|
53
|
+
timeoutMs;
|
|
54
|
+
id = 1;
|
|
55
|
+
async rpc(method, params) {
|
|
56
|
+
const res = await fetch(`${this.baseUrl}/mcp`, {
|
|
57
|
+
method: "POST",
|
|
58
|
+
headers: {
|
|
59
|
+
Authorization: `Bearer ${this.token}`,
|
|
60
|
+
"Content-Type": "application/json",
|
|
61
|
+
Accept: "application/json, text/event-stream"
|
|
62
|
+
},
|
|
63
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: this.id++, method, params }),
|
|
64
|
+
signal: AbortSignal.timeout(this.timeoutMs)
|
|
65
|
+
});
|
|
66
|
+
if (res.status === 401) throw Object.assign(new Error("unauthorized"), { code: 401 });
|
|
67
|
+
if (!res.ok) throw new Error(`mcp http ${res.status}`);
|
|
68
|
+
const j = await res.json();
|
|
69
|
+
if (j.error) throw new Error(j.error.message ?? "mcp error");
|
|
70
|
+
return j.result;
|
|
71
|
+
}
|
|
72
|
+
async call(tool, args = {}) {
|
|
73
|
+
const result = await this.rpc("tools/call", { name: tool, arguments: args });
|
|
74
|
+
const text = result?.content?.[0]?.text;
|
|
75
|
+
if (typeof text !== "string") return result;
|
|
76
|
+
try {
|
|
77
|
+
return JSON.parse(text);
|
|
78
|
+
} catch {
|
|
79
|
+
return text;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async stream(tool, args, onEvent, signal) {
|
|
83
|
+
const res = await fetch(`${this.baseUrl}/mcp`, {
|
|
84
|
+
method: "POST",
|
|
85
|
+
headers: {
|
|
86
|
+
Authorization: `Bearer ${this.token}`,
|
|
87
|
+
"Content-Type": "application/json",
|
|
88
|
+
Accept: "text/event-stream"
|
|
89
|
+
},
|
|
90
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: this.id++, method: "tools/call", params: { name: tool, arguments: args } }),
|
|
91
|
+
signal
|
|
92
|
+
});
|
|
93
|
+
if (!res.ok || !res.body) throw new Error(`mcp stream ${res.status}`);
|
|
94
|
+
const reader = res.body.getReader();
|
|
95
|
+
const dec = new TextDecoder();
|
|
96
|
+
let buf = "";
|
|
97
|
+
for (; ; ) {
|
|
98
|
+
let value;
|
|
99
|
+
let done;
|
|
100
|
+
try {
|
|
101
|
+
;
|
|
102
|
+
({ value, done } = await reader.read());
|
|
103
|
+
} catch (e) {
|
|
104
|
+
if (e?.name === "AbortError") return;
|
|
105
|
+
throw e;
|
|
106
|
+
}
|
|
107
|
+
if (done) break;
|
|
108
|
+
buf += dec.decode(value, { stream: true });
|
|
109
|
+
let i;
|
|
110
|
+
while ((i = buf.indexOf("\n\n")) >= 0) {
|
|
111
|
+
const frame = buf.slice(0, i);
|
|
112
|
+
buf = buf.slice(i + 2);
|
|
113
|
+
const line = frame.split("\n").find((l) => l.startsWith("data:"));
|
|
114
|
+
if (line) {
|
|
115
|
+
try {
|
|
116
|
+
onEvent(JSON.parse(line.slice(5).trim()));
|
|
117
|
+
} catch {
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
async function connect(a) {
|
|
125
|
+
const timeoutMs = a.timeoutMs ?? 15e3;
|
|
126
|
+
if (a.url) {
|
|
127
|
+
return new DaemonClient(a.url.replace(/\/+$/, ""), a.token ?? "", timeoutMs);
|
|
128
|
+
}
|
|
129
|
+
const dir = a.stateDir ?? defaultStateDir();
|
|
130
|
+
const info = await readDaemonInfo(dir);
|
|
131
|
+
if (!info) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
"No Supbuddy daemon is running. Open the Supbuddy app, or start one with `supbuddy daemon --detach`."
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
const token = a.token ?? info.bootToken;
|
|
137
|
+
for (let p = info.mcpPort; p <= info.mcpPort + 5; p++) {
|
|
138
|
+
const client = new DaemonClient(`http://127.0.0.1:${p}`, token, timeoutMs);
|
|
139
|
+
try {
|
|
140
|
+
await client.call("get_health");
|
|
141
|
+
return client;
|
|
142
|
+
} catch (e) {
|
|
143
|
+
if (e?.code === 401 || e?.name === "TimeoutError" || e?.name === "SyntaxError" || /abort|timeout|ETIMEDOUT|ECONNREFUSED|ECONNRESET|fetch failed|JSON/i.test(String(e?.message ?? e))) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
throw e;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const stale = !isPidAlive(info.pid);
|
|
150
|
+
if (stale) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`The Supbuddy daemon recorded in ${dir} (pid ${info.pid}) is no longer running \u2014 its state file is stale. Open the Supbuddy app (or run \`supbuddy daemon --detach\`) to restart it.`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
throw new Error(
|
|
156
|
+
`Could not reach the Supbuddy daemon at 127.0.0.1:${info.mcpPort} (pid ${info.pid} is running but not answering \u2014 it may still be starting up, or its control server failed to bind). Try again in a moment, or restart the Supbuddy app.`
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// src/completions.ts
|
|
161
|
+
var COMMAND_TREE = {
|
|
162
|
+
status: [],
|
|
163
|
+
proxy: ["status", "start", "stop", "restart"],
|
|
164
|
+
map: ["ls", "add", "get", "set", "enable", "disable", "rm", "restore"],
|
|
165
|
+
project: ["ls", "add", "get", "scan", "set", "enable", "disable", "rm", "restore", "env", "env-read", "set-supabase-path", "refresh-context"],
|
|
166
|
+
projects: [],
|
|
167
|
+
supabase: ["start", "stop", "restart", "status", "config", "init", "backups", "restore", "cancel", "force-recreate", "restart-container", "analytics"],
|
|
168
|
+
logs: ["requests", "audit", "get"],
|
|
169
|
+
compose: ["up", "down", "restart", "status", "logs"],
|
|
170
|
+
isolation: ["switch", "pending-migrations"],
|
|
171
|
+
migrate: ["start", "finish"],
|
|
172
|
+
ca: ["status", "install", "uninstall"],
|
|
173
|
+
env: ["copy", "write"],
|
|
174
|
+
settings: ["get", "set"],
|
|
175
|
+
mcp: ["add", "ls", "revoke", "approvals"],
|
|
176
|
+
account: [],
|
|
177
|
+
caps: [],
|
|
178
|
+
scripts: ["ls", "start", "restart", "stop", "logs", "bookmark"],
|
|
179
|
+
addons: ["seed", "scaffold"],
|
|
180
|
+
bundle: ["export", "import", "validate"],
|
|
181
|
+
connect: ["preview", "targets", "diff", "apply", "write", "test", "dismiss-drift"],
|
|
182
|
+
trust: ["status", "install", "remove", "detect", "test"],
|
|
183
|
+
tailscale: ["status", "set-key", "remove-key", "test"],
|
|
184
|
+
dns: ["status"],
|
|
185
|
+
pf: ["status", "enable", "disable", "reload"],
|
|
186
|
+
// bin.ts-handled commands
|
|
187
|
+
daemon: [],
|
|
188
|
+
stop: [],
|
|
189
|
+
service: ["install", "uninstall", "status"],
|
|
190
|
+
tui: [],
|
|
191
|
+
dash: [],
|
|
192
|
+
shell: [],
|
|
193
|
+
selftest: [],
|
|
194
|
+
completion: ["zsh"],
|
|
195
|
+
help: []
|
|
196
|
+
};
|
|
197
|
+
var GLOBAL_FLAGS = ["--json", "--details", "--follow", "--url", "--timeout", "--yes", "--quiet", "--state-dir", "--worker-port", "--detach"];
|
|
198
|
+
var TOP_LEVEL = Object.keys(COMMAND_TREE);
|
|
199
|
+
var ARG_SOURCE = {
|
|
200
|
+
"project:get": "projects",
|
|
201
|
+
"project:set": "projects",
|
|
202
|
+
"project:enable": "projects",
|
|
203
|
+
"project:disable": "projects",
|
|
204
|
+
"project:rm": "projects",
|
|
205
|
+
"project:restore": "projects",
|
|
206
|
+
"project:env": "projects",
|
|
207
|
+
"project:refresh-context": "projects",
|
|
208
|
+
"supabase:start": "projects",
|
|
209
|
+
"supabase:stop": "projects",
|
|
210
|
+
"supabase:restart": "projects",
|
|
211
|
+
"supabase:status": "projects",
|
|
212
|
+
"supabase:init": "projects",
|
|
213
|
+
"compose:up": "projects",
|
|
214
|
+
"compose:restart": "projects",
|
|
215
|
+
"compose:down": "projects",
|
|
216
|
+
"compose:status": "projects",
|
|
217
|
+
"scripts:ls": "projects",
|
|
218
|
+
"migrate:start": "projects",
|
|
219
|
+
"migrate:finish": "projects",
|
|
220
|
+
"connect:preview": "projects",
|
|
221
|
+
"connect:targets": "projects",
|
|
222
|
+
"connect:diff": "projects",
|
|
223
|
+
"connect:apply": "projects",
|
|
224
|
+
"connect:write": "projects",
|
|
225
|
+
"connect:test": "projects",
|
|
226
|
+
"connect:dismiss-drift": "projects",
|
|
227
|
+
"map:get": "mappings",
|
|
228
|
+
"map:set": "mappings",
|
|
229
|
+
"map:enable": "mappings",
|
|
230
|
+
"map:disable": "mappings",
|
|
231
|
+
"map:rm": "mappings",
|
|
232
|
+
"map:restore": "mappings",
|
|
233
|
+
"mcp:revoke": "clients",
|
|
234
|
+
"mcp:add": "agents"
|
|
235
|
+
};
|
|
236
|
+
function argSourceFor(module, action) {
|
|
237
|
+
return ARG_SOURCE[`${module}:${action}`] ?? null;
|
|
238
|
+
}
|
|
239
|
+
var DESCRIPTIONS = {
|
|
240
|
+
// modules
|
|
241
|
+
status: "daemon + proxy health",
|
|
242
|
+
proxy: "reverse-proxy control",
|
|
243
|
+
map: "domain \u2192 port mappings",
|
|
244
|
+
project: "registered dev projects",
|
|
245
|
+
supabase: "local Supabase lifecycle",
|
|
246
|
+
compose: "docker compose services",
|
|
247
|
+
scripts: "project dev scripts",
|
|
248
|
+
logs: "request + audit logs",
|
|
249
|
+
isolation: "host / thin isolation",
|
|
250
|
+
migrate: "vm \u2192 thin migration",
|
|
251
|
+
ca: "CA certificate trust",
|
|
252
|
+
env: "env-file helpers",
|
|
253
|
+
settings: "global settings",
|
|
254
|
+
mcp: "register Supbuddy into coding agents + manage MCP clients",
|
|
255
|
+
account: "account info",
|
|
256
|
+
caps: "client capabilities",
|
|
257
|
+
addons: "add-on compose services",
|
|
258
|
+
bundle: "export / import projects",
|
|
259
|
+
connect: "connection strings + env",
|
|
260
|
+
trust: "bundled-runtime CA trust",
|
|
261
|
+
tailscale: "Tailscale split-DNS",
|
|
262
|
+
dns: "local DNS status",
|
|
263
|
+
pf: "port-forwarding (pfctl)",
|
|
264
|
+
daemon: "run the headless daemon",
|
|
265
|
+
stop: "stop a running daemon",
|
|
266
|
+
service: "start-on-login service",
|
|
267
|
+
tui: "live dashboard",
|
|
268
|
+
completion: "shell completion script",
|
|
269
|
+
// proxy
|
|
270
|
+
"proxy:status": "show proxy status",
|
|
271
|
+
"proxy:start": "start the proxy (sudo)",
|
|
272
|
+
"proxy:stop": "stop the proxy",
|
|
273
|
+
"proxy:restart": "restart the proxy",
|
|
274
|
+
// map
|
|
275
|
+
"map:ls": "list mappings",
|
|
276
|
+
"map:add": "add a mapping",
|
|
277
|
+
"map:get": "show a mapping",
|
|
278
|
+
"map:set": "update a mapping",
|
|
279
|
+
"map:enable": "enable a mapping",
|
|
280
|
+
"map:disable": "disable a mapping",
|
|
281
|
+
"map:rm": "delete a mapping",
|
|
282
|
+
"map:restore": "restore from trash",
|
|
283
|
+
// project
|
|
284
|
+
"project:ls": "list projects",
|
|
285
|
+
"project:add": "register a project",
|
|
286
|
+
"project:get": "show project details",
|
|
287
|
+
"project:scan": "scan for services",
|
|
288
|
+
"project:set": "update name/domain",
|
|
289
|
+
"project:enable": "enable a project",
|
|
290
|
+
"project:disable": "disable a project",
|
|
291
|
+
"project:rm": "delete a project",
|
|
292
|
+
"project:restore": "restore from trash",
|
|
293
|
+
"project:env": "list env files",
|
|
294
|
+
"project:env-read": "read an env file",
|
|
295
|
+
"project:set-supabase-path": "set supabase config dir",
|
|
296
|
+
"project:refresh-context": "refresh project context",
|
|
297
|
+
// supabase
|
|
298
|
+
"supabase:start": "start Supabase",
|
|
299
|
+
"supabase:stop": "stop Supabase",
|
|
300
|
+
"supabase:restart": "restart Supabase",
|
|
301
|
+
"supabase:status": "show Supabase status",
|
|
302
|
+
"supabase:config": "read/write config.toml",
|
|
303
|
+
"supabase:init": "init Supabase",
|
|
304
|
+
"supabase:backups": "list backups",
|
|
305
|
+
"supabase:restore": "restore a backup",
|
|
306
|
+
"supabase:cancel": "cancel a start",
|
|
307
|
+
"supabase:force-recreate": "force-recreate containers",
|
|
308
|
+
"supabase:restart-container": "restart one container",
|
|
309
|
+
"supabase:analytics": "analytics on/off",
|
|
310
|
+
// compose
|
|
311
|
+
"compose:up": "start services",
|
|
312
|
+
"compose:restart": "restart services",
|
|
313
|
+
"compose:down": "tear down services",
|
|
314
|
+
"compose:status": "service status",
|
|
315
|
+
"compose:logs": "tail service logs",
|
|
316
|
+
// scripts
|
|
317
|
+
"scripts:ls": "list project scripts",
|
|
318
|
+
"scripts:start": "start a script",
|
|
319
|
+
"scripts:restart": "restart a script",
|
|
320
|
+
"scripts:stop": "stop a script",
|
|
321
|
+
"scripts:logs": "tail script logs",
|
|
322
|
+
"scripts:bookmark": "bookmark a script",
|
|
323
|
+
// logs
|
|
324
|
+
"logs:requests": "request logs (tail)",
|
|
325
|
+
"logs:audit": "audit log stream",
|
|
326
|
+
"logs:get": "one request log entry",
|
|
327
|
+
// isolation / migrate
|
|
328
|
+
"isolation:switch": "switch host/thin",
|
|
329
|
+
"isolation:pending-migrations": "list pending migrations",
|
|
330
|
+
"migrate:start": "begin vm\u2192thin migration",
|
|
331
|
+
"migrate:finish": "finish migration",
|
|
332
|
+
// ca / env / settings
|
|
333
|
+
"ca:status": "CA install status",
|
|
334
|
+
"ca:install": "install the CA",
|
|
335
|
+
"ca:uninstall": "uninstall the CA",
|
|
336
|
+
"env:copy": "copy a var between files",
|
|
337
|
+
"env:write": "write/delete env vars",
|
|
338
|
+
"settings:get": "show settings",
|
|
339
|
+
"settings:set": "update settings (json)",
|
|
340
|
+
// mcp / addons / bundle
|
|
341
|
+
"mcp:add": "add Supbuddy to a coding agent (--write/--print/--prompt)",
|
|
342
|
+
"mcp:ls": "list registered MCP clients",
|
|
343
|
+
"mcp:revoke": "revoke an MCP client token",
|
|
344
|
+
"mcp:approvals": "approve/cancel a queued destructive plan",
|
|
345
|
+
"addons:seed": "seed addon data",
|
|
346
|
+
"addons:scaffold": "scaffold addon services",
|
|
347
|
+
"bundle:export": "export a project bundle",
|
|
348
|
+
"bundle:import": "import a bundle",
|
|
349
|
+
"bundle:validate": "validate a bundle",
|
|
350
|
+
// connect / trust / tailscale / dns / pf
|
|
351
|
+
"connect:preview": "preview connection",
|
|
352
|
+
"connect:targets": "list env targets",
|
|
353
|
+
"connect:diff": "diff env vs target",
|
|
354
|
+
"connect:apply": "apply env to target",
|
|
355
|
+
"connect:write": "write connection",
|
|
356
|
+
"connect:test": "test connectivity",
|
|
357
|
+
"connect:dismiss-drift": "dismiss drift warning",
|
|
358
|
+
"trust:status": "trust status",
|
|
359
|
+
"trust:install": "install runtime trust",
|
|
360
|
+
"trust:remove": "remove runtime trust",
|
|
361
|
+
"trust:detect": "detect runtime tools",
|
|
362
|
+
"trust:test": "test trust",
|
|
363
|
+
"tailscale:status": "Tailscale status",
|
|
364
|
+
"tailscale:set-key": "set API key",
|
|
365
|
+
"tailscale:remove-key": "remove API key",
|
|
366
|
+
"tailscale:test": "test connection",
|
|
367
|
+
"dns:status": "DNS server status",
|
|
368
|
+
"pf:status": "port-forwarding status",
|
|
369
|
+
"pf:enable": "enable port-forwarding",
|
|
370
|
+
"pf:disable": "disable port-forwarding",
|
|
371
|
+
"pf:reload": "reload pf rules",
|
|
372
|
+
// service
|
|
373
|
+
"service:install": "install login service",
|
|
374
|
+
"service:uninstall": "uninstall service",
|
|
375
|
+
"service:status": "service status"
|
|
376
|
+
};
|
|
377
|
+
function describe(module, action) {
|
|
378
|
+
if (action) return DESCRIPTIONS[`${module}:${action}`] ?? "";
|
|
379
|
+
return DESCRIPTIONS[module] ?? "";
|
|
380
|
+
}
|
|
381
|
+
export {
|
|
382
|
+
ARG_SOURCE,
|
|
383
|
+
COMMAND_TREE,
|
|
384
|
+
DESCRIPTIONS,
|
|
385
|
+
DaemonClient,
|
|
386
|
+
GLOBAL_FLAGS,
|
|
387
|
+
TOP_LEVEL,
|
|
388
|
+
argSourceFor,
|
|
389
|
+
connect,
|
|
390
|
+
defaultStateDir,
|
|
391
|
+
describe,
|
|
392
|
+
readDaemonInfo
|
|
393
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supbuddy",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.5",
|
|
4
4
|
"description": "Run multiple Supabase projects at once on custom local domains with HTTPS. A headless CLI and daemon (proxy, DNS, Supabase/Compose lifecycle, MCP) for macOS and Linux.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"supabase",
|
|
@@ -26,7 +26,10 @@
|
|
|
26
26
|
"supbuddy": "./dist/bin.js"
|
|
27
27
|
},
|
|
28
28
|
"exports": {
|
|
29
|
-
"./lib":
|
|
29
|
+
"./lib": {
|
|
30
|
+
"types": "./dist/lib.d.ts",
|
|
31
|
+
"default": "./dist/lib.js"
|
|
32
|
+
}
|
|
30
33
|
},
|
|
31
34
|
"files": [
|
|
32
35
|
"dist",
|