svamp-cli 0.1.39 → 0.1.41
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/cli.mjs +168 -26
- package/dist/commands-4_MiOQVp.mjs +1217 -0
- package/dist/commands-8UAWGJrC.mjs +1208 -0
- package/dist/commands-9DPsh6ku.mjs +1217 -0
- package/dist/commands-9rMB13FP.mjs +1214 -0
- package/dist/commands-B7yLt11i.mjs +1217 -0
- package/dist/commands-Bcdp0X-o.mjs +1217 -0
- package/dist/commands-BmirUCVt.mjs +1208 -0
- package/dist/commands-BzbYPx0f.mjs +1208 -0
- package/dist/commands-C-RtFjJl.mjs +1217 -0
- package/dist/commands-C20_f6oo.mjs +1217 -0
- package/dist/commands-CZ7KPLLJ.mjs +1217 -0
- package/dist/commands-Cnmf8znA.mjs +1196 -0
- package/dist/commands-CwC2aVzu.mjs +1217 -0
- package/dist/commands-Dd8cn8mW.mjs +1217 -0
- package/dist/commands-DwBr3sBn.mjs +1217 -0
- package/dist/commands-HLu7P96l.mjs +1214 -0
- package/dist/commands-KH5dj9dv.mjs +1214 -0
- package/dist/commands-LaNHVHjc.mjs +1217 -0
- package/dist/commands-YBW5jFpy.mjs +1217 -0
- package/dist/commands-fSZOP80Z.mjs +1217 -0
- package/dist/commands-fqBuJe1b.mjs +1217 -0
- package/dist/commands-od2hOku5.mjs +1217 -0
- package/dist/index.mjs +2 -2
- package/dist/package-BkBE6ZdN.mjs +57 -0
- package/dist/{package-BbzWWqQK.mjs → package-D6mNQtUs.mjs} +1 -1
- package/dist/run-4B1XZQB8.mjs +5426 -0
- package/dist/run-8kKykzTs.mjs +5367 -0
- package/dist/run-8mLZV2lg.mjs +1050 -0
- package/dist/run-9x7I9Ck-.mjs +5264 -0
- package/dist/run-B5o5fMMd.mjs +5369 -0
- package/dist/run-BHZNzX1F.mjs +5235 -0
- package/dist/run-BLySdZ1K.mjs +5251 -0
- package/dist/run-BOVkQfM-.mjs +1050 -0
- package/dist/run-Bd-t6s63.mjs +5373 -0
- package/dist/run-BenYqfwQ.mjs +5273 -0
- package/dist/run-Bhh05yic.mjs +5369 -0
- package/dist/run-BmL1m0Bk.mjs +1050 -0
- package/dist/run-BpjmHeht.mjs +1050 -0
- package/dist/run-C3PAp02X.mjs +5252 -0
- package/dist/run-C8GkzcfP.mjs +1050 -0
- package/dist/run-CY8Y0JPW.mjs +5287 -0
- package/dist/run-CZCKBcQ-.mjs +5244 -0
- package/dist/run-C_1x2cNU.mjs +5381 -0
- package/dist/run-CajRcN3C.mjs +1050 -0
- package/dist/run-CcSr4x2f.mjs +1050 -0
- package/dist/run-CjH1H4vq.mjs +1050 -0
- package/dist/{run-D19RL_zw.mjs → run-Ckh6JE9F.mjs} +82 -20
- package/dist/run-CqL3ZWdr.mjs +5381 -0
- package/dist/run-Csj7sJAh.mjs +1050 -0
- package/dist/run-CymDyu2b.mjs +5389 -0
- package/dist/run-D5N42sVA.mjs +1050 -0
- package/dist/run-D8mQ_fL5.mjs +1050 -0
- package/dist/run-DQ0yljWr.mjs +1050 -0
- package/dist/run-DWzA1gZ-.mjs +1050 -0
- package/dist/run-DfU2luyX.mjs +1050 -0
- package/dist/run-Di3I0USw.mjs +1050 -0
- package/dist/run-Dwm19YhI.mjs +1050 -0
- package/dist/run-E_MwVOtN.mjs +5272 -0
- package/dist/run-FPoL2-FD.mjs +5381 -0
- package/dist/run-K_S7pfZ-.mjs +1050 -0
- package/dist/run-RBufRqbs.mjs +1050 -0
- package/dist/run-YG1Pb9dY.mjs +5385 -0
- package/dist/run-jLp4pbTE.mjs +1050 -0
- package/dist/run-m3oAuSg0.mjs +1050 -0
- package/dist/run-v32uF2bP.mjs +5378 -0
- package/dist/run-vTsskoZc.mjs +5340 -0
- package/dist/run-vt26p5D7.mjs +1050 -0
- package/dist/run-vvQiCHpi.mjs +5427 -0
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as startDaemon, b as stopDaemon, d as daemonStatus } from './run-
|
|
1
|
+
import { s as startDaemon, b as stopDaemon, d as daemonStatus } from './run-YG1Pb9dY.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -6,8 +6,8 @@ import 'path';
|
|
|
6
6
|
import 'url';
|
|
7
7
|
import 'child_process';
|
|
8
8
|
import 'crypto';
|
|
9
|
-
import 'node:crypto';
|
|
10
9
|
import 'node:fs';
|
|
10
|
+
import 'node:crypto';
|
|
11
11
|
import 'node:path';
|
|
12
12
|
import 'node:child_process';
|
|
13
13
|
import '@agentclientprotocol/sdk';
|
|
@@ -28,13 +28,16 @@ async function main() {
|
|
|
28
28
|
} else if (subcommand === "daemon") {
|
|
29
29
|
if (daemonSubcommand === "start") {
|
|
30
30
|
const { spawn } = await import('child_process');
|
|
31
|
+
const extraArgs = [];
|
|
32
|
+
if (args.includes("--no-auto-continue")) extraArgs.push("--no-auto-continue");
|
|
31
33
|
const child = spawn(process.execPath, [
|
|
32
34
|
"--no-warnings",
|
|
33
35
|
"--no-deprecation",
|
|
34
36
|
...process.argv.slice(1, 2),
|
|
35
37
|
// the script path
|
|
36
38
|
"daemon",
|
|
37
|
-
"start-sync"
|
|
39
|
+
"start-sync",
|
|
40
|
+
...extraArgs
|
|
38
41
|
], {
|
|
39
42
|
detached: true,
|
|
40
43
|
stdio: "ignore",
|
|
@@ -64,7 +67,8 @@ async function main() {
|
|
|
64
67
|
}
|
|
65
68
|
process.exit(0);
|
|
66
69
|
} else if (daemonSubcommand === "start-sync") {
|
|
67
|
-
|
|
70
|
+
const noAutoContinue = args.includes("--no-auto-continue");
|
|
71
|
+
await startDaemon({ noAutoContinue });
|
|
68
72
|
process.exit(0);
|
|
69
73
|
} else if (daemonSubcommand === "stop") {
|
|
70
74
|
const cleanup = args.includes("--cleanup");
|
|
@@ -86,12 +90,14 @@ async function main() {
|
|
|
86
90
|
await handleAgentCommand();
|
|
87
91
|
} else if (subcommand === "session") {
|
|
88
92
|
await handleSessionCommand();
|
|
93
|
+
} else if (subcommand === "machine") {
|
|
94
|
+
await handleMachineCommand();
|
|
89
95
|
} else if (subcommand === "--help" || subcommand === "-h") {
|
|
90
96
|
printHelp();
|
|
91
97
|
} else if (!subcommand || subcommand === "start") {
|
|
92
98
|
await handleInteractiveCommand();
|
|
93
99
|
} else if (subcommand === "--version" || subcommand === "-v") {
|
|
94
|
-
const pkg = await import('./package-
|
|
100
|
+
const pkg = await import('./package-BkBE6ZdN.mjs').catch(() => ({ default: { version: "unknown" } }));
|
|
95
101
|
console.log(`svamp version: ${pkg.default.version}`);
|
|
96
102
|
} else {
|
|
97
103
|
console.error(`Unknown command: ${subcommand}`);
|
|
@@ -100,7 +106,7 @@ async function main() {
|
|
|
100
106
|
}
|
|
101
107
|
}
|
|
102
108
|
async function handleInteractiveCommand() {
|
|
103
|
-
const { runInteractive } = await import('./run-
|
|
109
|
+
const { runInteractive } = await import('./run-Di3I0USw.mjs');
|
|
104
110
|
const interactiveArgs = subcommand === "start" ? args.slice(1) : args;
|
|
105
111
|
let directory = process.cwd();
|
|
106
112
|
let resumeSessionId;
|
|
@@ -145,7 +151,7 @@ async function handleAgentCommand() {
|
|
|
145
151
|
return;
|
|
146
152
|
}
|
|
147
153
|
if (agentArgs[0] === "list") {
|
|
148
|
-
const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-
|
|
154
|
+
const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-YG1Pb9dY.mjs').then(function (n) { return n.i; });
|
|
149
155
|
console.log("Known agents:");
|
|
150
156
|
for (const [name, config2] of Object.entries(KNOWN_ACP_AGENTS)) {
|
|
151
157
|
console.log(` ${name.padEnd(12)} ${config2.command} ${config2.args.join(" ")} (ACP)`);
|
|
@@ -157,7 +163,7 @@ async function handleAgentCommand() {
|
|
|
157
163
|
console.log('Use "svamp agent -- <command> [args]" for a custom ACP agent.');
|
|
158
164
|
return;
|
|
159
165
|
}
|
|
160
|
-
const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-
|
|
166
|
+
const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-YG1Pb9dY.mjs').then(function (n) { return n.i; });
|
|
161
167
|
let cwd = process.cwd();
|
|
162
168
|
const filteredArgs = [];
|
|
163
169
|
for (let i = 0; i < agentArgs.length; i++) {
|
|
@@ -181,12 +187,12 @@ async function handleAgentCommand() {
|
|
|
181
187
|
console.log(`Starting ${config.agentName} agent in ${cwd}...`);
|
|
182
188
|
let backend;
|
|
183
189
|
if (KNOWN_MCP_AGENTS[config.agentName]) {
|
|
184
|
-
const { CodexMcpBackend } = await import('./run-
|
|
190
|
+
const { CodexMcpBackend } = await import('./run-YG1Pb9dY.mjs').then(function (n) { return n.j; });
|
|
185
191
|
backend = new CodexMcpBackend({ cwd, log: logFn });
|
|
186
192
|
} else {
|
|
187
|
-
const { AcpBackend } = await import('./run-
|
|
188
|
-
const { GeminiTransport } = await import('./run-
|
|
189
|
-
const { DefaultTransport } = await import('./run-
|
|
193
|
+
const { AcpBackend } = await import('./run-YG1Pb9dY.mjs').then(function (n) { return n.h; });
|
|
194
|
+
const { GeminiTransport } = await import('./run-YG1Pb9dY.mjs').then(function (n) { return n.G; });
|
|
195
|
+
const { DefaultTransport } = await import('./run-YG1Pb9dY.mjs').then(function (n) { return n.D; });
|
|
190
196
|
const transportHandler = config.agentName === "gemini" ? new GeminiTransport() : new DefaultTransport(config.agentName);
|
|
191
197
|
backend = new AcpBackend({
|
|
192
198
|
agentName: config.agentName,
|
|
@@ -304,7 +310,7 @@ async function handleSessionCommand() {
|
|
|
304
310
|
printSessionHelp();
|
|
305
311
|
return;
|
|
306
312
|
}
|
|
307
|
-
const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait } = await import('./commands-
|
|
313
|
+
const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare } = await import('./commands-CwC2aVzu.mjs');
|
|
308
314
|
const parseFlagStr = (flag, shortFlag) => {
|
|
309
315
|
for (let i = 1; i < sessionArgs.length; i++) {
|
|
310
316
|
if ((sessionArgs[i] === flag || shortFlag) && i + 1 < sessionArgs.length) {
|
|
@@ -338,7 +344,37 @@ async function handleSessionCommand() {
|
|
|
338
344
|
}
|
|
339
345
|
const message = parseFlagStr("--message");
|
|
340
346
|
const wait = hasFlag("--wait");
|
|
341
|
-
|
|
347
|
+
const isolate = hasFlag("--isolate");
|
|
348
|
+
const securityContextPath = parseFlagStr("--security-context");
|
|
349
|
+
const denyNetwork = hasFlag("--deny-network");
|
|
350
|
+
const share = [];
|
|
351
|
+
const denyRead = [];
|
|
352
|
+
const allowWrite = [];
|
|
353
|
+
const allowDomain = [];
|
|
354
|
+
for (let i = 1; i < sessionArgs.length; i++) {
|
|
355
|
+
if (sessionArgs[i] === "--share" && i + 1 < sessionArgs.length) {
|
|
356
|
+
share.push(sessionArgs[++i]);
|
|
357
|
+
} else if (sessionArgs[i] === "--deny-read" && i + 1 < sessionArgs.length) {
|
|
358
|
+
denyRead.push(sessionArgs[++i]);
|
|
359
|
+
} else if (sessionArgs[i] === "--allow-write" && i + 1 < sessionArgs.length) {
|
|
360
|
+
allowWrite.push(sessionArgs[++i]);
|
|
361
|
+
} else if (sessionArgs[i] === "--allow-domain" && i + 1 < sessionArgs.length) {
|
|
362
|
+
allowDomain.push(sessionArgs[++i]);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
const { parseShareArg } = await import('./commands-CwC2aVzu.mjs');
|
|
366
|
+
const shareEntries = share.map((s) => parseShareArg(s));
|
|
367
|
+
await sessionSpawn(agent, dir, targetMachineId, {
|
|
368
|
+
message,
|
|
369
|
+
wait,
|
|
370
|
+
isolate,
|
|
371
|
+
securityContextPath,
|
|
372
|
+
share: shareEntries.length > 0 ? shareEntries : void 0,
|
|
373
|
+
denyRead: denyRead.length > 0 ? denyRead : void 0,
|
|
374
|
+
allowWrite: allowWrite.length > 0 ? allowWrite : void 0,
|
|
375
|
+
denyNetwork,
|
|
376
|
+
allowDomain: allowDomain.length > 0 ? allowDomain : void 0
|
|
377
|
+
});
|
|
342
378
|
} else if (sessionSubcommand === "stop") {
|
|
343
379
|
if (!sessionArgs[1]) {
|
|
344
380
|
console.error("Usage: svamp session stop <session-id>");
|
|
@@ -388,6 +424,16 @@ async function handleSessionCommand() {
|
|
|
388
424
|
await sessionWait(sessionArgs[1], targetMachineId, {
|
|
389
425
|
timeout: parseFlagInt("--timeout")
|
|
390
426
|
});
|
|
427
|
+
} else if (sessionSubcommand === "share") {
|
|
428
|
+
if (!sessionArgs[1]) {
|
|
429
|
+
console.error("Usage: svamp session share <session-id> --add <email>[:<role>] | --remove <email> | --list");
|
|
430
|
+
process.exit(1);
|
|
431
|
+
}
|
|
432
|
+
await sessionShare(sessionArgs[1], targetMachineId, {
|
|
433
|
+
add: parseFlagStr("--add"),
|
|
434
|
+
remove: parseFlagStr("--remove"),
|
|
435
|
+
list: hasFlag("--list")
|
|
436
|
+
});
|
|
391
437
|
} else {
|
|
392
438
|
console.error(`Unknown session command: ${sessionSubcommand}`);
|
|
393
439
|
printSessionHelp();
|
|
@@ -395,6 +441,50 @@ async function handleSessionCommand() {
|
|
|
395
441
|
}
|
|
396
442
|
process.exit(0);
|
|
397
443
|
}
|
|
444
|
+
async function handleMachineCommand() {
|
|
445
|
+
const machineArgs = args.slice(1);
|
|
446
|
+
const machineSubcommand = machineArgs[0];
|
|
447
|
+
if (!machineSubcommand || machineSubcommand === "--help" || machineSubcommand === "-h") {
|
|
448
|
+
printMachineHelp();
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
if (machineSubcommand === "share") {
|
|
452
|
+
const { machineShare } = await import('./commands-CwC2aVzu.mjs');
|
|
453
|
+
let machineId;
|
|
454
|
+
const shareArgs = [];
|
|
455
|
+
for (let i = 1; i < machineArgs.length; i++) {
|
|
456
|
+
if ((machineArgs[i] === "--machine" || machineArgs[i] === "-m") && i + 1 < machineArgs.length) {
|
|
457
|
+
machineId = machineArgs[++i];
|
|
458
|
+
} else {
|
|
459
|
+
shareArgs.push(machineArgs[i]);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
let add;
|
|
463
|
+
let remove;
|
|
464
|
+
let configPath;
|
|
465
|
+
let list = false;
|
|
466
|
+
let showConfig = false;
|
|
467
|
+
for (let i = 0; i < shareArgs.length; i++) {
|
|
468
|
+
if (shareArgs[i] === "--add" && i + 1 < shareArgs.length) {
|
|
469
|
+
add = shareArgs[++i];
|
|
470
|
+
} else if (shareArgs[i] === "--remove" && i + 1 < shareArgs.length) {
|
|
471
|
+
remove = shareArgs[++i];
|
|
472
|
+
} else if (shareArgs[i] === "--config" && i + 1 < shareArgs.length) {
|
|
473
|
+
configPath = shareArgs[++i];
|
|
474
|
+
} else if (shareArgs[i] === "--list") {
|
|
475
|
+
list = true;
|
|
476
|
+
} else if (shareArgs[i] === "--show-config") {
|
|
477
|
+
showConfig = true;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
await machineShare(machineId, { add, remove, list, configPath, showConfig });
|
|
481
|
+
} else {
|
|
482
|
+
console.error(`Unknown machine command: ${machineSubcommand}`);
|
|
483
|
+
printMachineHelp();
|
|
484
|
+
process.exit(1);
|
|
485
|
+
}
|
|
486
|
+
process.exit(0);
|
|
487
|
+
}
|
|
398
488
|
async function loginToHypha() {
|
|
399
489
|
const serverUrl = args[1] || process.env.HYPHA_SERVER_URL;
|
|
400
490
|
if (!serverUrl) {
|
|
@@ -706,8 +796,11 @@ Usage:
|
|
|
706
796
|
svamp daemon install Install as system service (launchd/systemd/wrapper)
|
|
707
797
|
svamp session list List active sessions
|
|
708
798
|
svamp session spawn Spawn a new session on the daemon
|
|
799
|
+
svamp session share <id> Manage session sharing
|
|
709
800
|
svamp session attach <id> Attach to a session
|
|
710
801
|
svamp session --help Show all session commands
|
|
802
|
+
svamp machine share Manage machine sharing & security contexts
|
|
803
|
+
svamp machine --help Show all machine commands
|
|
711
804
|
svamp agent list List known agents
|
|
712
805
|
svamp agent <name> Start local agent session (gemini, codex)
|
|
713
806
|
svamp --version Show version
|
|
@@ -732,12 +825,13 @@ function printDaemonHelp() {
|
|
|
732
825
|
svamp daemon \u2014 Daemon management
|
|
733
826
|
|
|
734
827
|
Usage:
|
|
735
|
-
svamp daemon start
|
|
736
|
-
svamp daemon
|
|
737
|
-
svamp daemon stop
|
|
738
|
-
svamp daemon
|
|
739
|
-
svamp daemon
|
|
740
|
-
svamp daemon
|
|
828
|
+
svamp daemon start Start the daemon (detached)
|
|
829
|
+
svamp daemon start --no-auto-continue Start without auto-continuing interrupted sessions
|
|
830
|
+
svamp daemon stop Stop the daemon (sessions preserved for restart)
|
|
831
|
+
svamp daemon stop --cleanup Stop and mark all sessions as stopped
|
|
832
|
+
svamp daemon status Show daemon status
|
|
833
|
+
svamp daemon install Install as launchd service (macOS) \u2014 auto-restart on crash
|
|
834
|
+
svamp daemon uninstall Remove launchd service
|
|
741
835
|
`);
|
|
742
836
|
}
|
|
743
837
|
function printSessionHelp() {
|
|
@@ -757,10 +851,22 @@ Usage:
|
|
|
757
851
|
svamp session messages <id> [--last N] [--json] [--after N] [--limit N]
|
|
758
852
|
Show messages (alias: msgs)
|
|
759
853
|
svamp session attach <id> Attach to session (interactive)
|
|
854
|
+
svamp session share <id> --list List shared users
|
|
855
|
+
svamp session share <id> --add <email>[:<role>] Share with user
|
|
856
|
+
svamp session share <id> --remove <email> Remove shared user
|
|
760
857
|
|
|
761
858
|
Options:
|
|
762
859
|
--machine <id>, -m <id> Target a specific machine (prefix match supported)
|
|
763
860
|
|
|
861
|
+
Spawn isolation options:
|
|
862
|
+
--share <email>[:<role>] Share session (repeatable). Role: view, interact, admin
|
|
863
|
+
--security-context <path> Path to security context JSON config file
|
|
864
|
+
--isolate Force OS-level isolation even without sharing
|
|
865
|
+
--deny-read <path> Deny read access to path (repeatable)
|
|
866
|
+
--allow-write <path> Allow write access to path (repeatable)
|
|
867
|
+
--deny-network Deny all network access
|
|
868
|
+
--allow-domain <domain> Allow network access to domain (repeatable)
|
|
869
|
+
|
|
764
870
|
Agents: claude (default), gemini, codex
|
|
765
871
|
|
|
766
872
|
Session and machine IDs can be abbreviated (prefix match, like Docker).
|
|
@@ -772,13 +878,49 @@ Attach commands:
|
|
|
772
878
|
/info Show session status
|
|
773
879
|
|
|
774
880
|
Examples:
|
|
775
|
-
svamp session list --active --json
|
|
776
881
|
svamp session spawn claude -d ~/projects/myapp --message "Fix the bug" --wait
|
|
777
|
-
svamp session
|
|
778
|
-
svamp session
|
|
779
|
-
svamp session
|
|
780
|
-
svamp session
|
|
781
|
-
svamp session
|
|
882
|
+
svamp session spawn claude -d /tmp/sandbox --isolate --deny-network
|
|
883
|
+
svamp session spawn claude -d /tmp/proj --share alice@example.com:admin --deny-read /etc
|
|
884
|
+
svamp session spawn claude --security-context ./security.json
|
|
885
|
+
svamp session share abc12345 --add bob@example.com:view
|
|
886
|
+
svamp session share abc12345 --list
|
|
887
|
+
`);
|
|
888
|
+
}
|
|
889
|
+
function printMachineHelp() {
|
|
890
|
+
console.log(`
|
|
891
|
+
svamp machine \u2014 Machine management
|
|
892
|
+
|
|
893
|
+
Usage:
|
|
894
|
+
svamp machine share --list List shared users
|
|
895
|
+
svamp machine share --add <email>[:<role>] Share machine with user
|
|
896
|
+
svamp machine share --remove <email> Remove shared user
|
|
897
|
+
svamp machine share --config <path> Apply security context config
|
|
898
|
+
svamp machine share --show-config Show current security context config
|
|
899
|
+
|
|
900
|
+
Options:
|
|
901
|
+
--machine <id>, -m <id> Target a specific machine (prefix match supported)
|
|
902
|
+
|
|
903
|
+
Security context config file format (JSON):
|
|
904
|
+
{
|
|
905
|
+
"default": {
|
|
906
|
+
"role": "interact",
|
|
907
|
+
"filesystem": { "denyRead": ["/etc/shadow"], "denyWrite": ["/usr"] },
|
|
908
|
+
"network": { "allowedDomains": ["api.anthropic.com"] }
|
|
909
|
+
},
|
|
910
|
+
"users": {
|
|
911
|
+
"alice@example.com": { "role": "admin" },
|
|
912
|
+
"bob@example.com": { "role": "view", "denyAllNetwork": true }
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
The "default" entry applies to all users. Per-user entries override defaults.
|
|
917
|
+
Machine-level config is merged with session-level config at spawn time.
|
|
918
|
+
|
|
919
|
+
Examples:
|
|
920
|
+
svamp machine share --add alice@example.com:admin
|
|
921
|
+
svamp machine share --config ./security-context.json
|
|
922
|
+
svamp machine share --show-config
|
|
923
|
+
svamp machine share --list
|
|
782
924
|
`);
|
|
783
925
|
}
|
|
784
926
|
function printInteractiveHelp() {
|