agenshield 0.1.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 (184) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +201 -0
  3. package/README.md +91 -0
  4. package/package.json +61 -0
  5. package/src/cli.d.ts +25 -0
  6. package/src/cli.d.ts.map +1 -0
  7. package/src/cli.js +78 -0
  8. package/src/cli.js.map +1 -0
  9. package/src/commands/daemon.d.ts +11 -0
  10. package/src/commands/daemon.d.ts.map +1 -0
  11. package/src/commands/daemon.js +107 -0
  12. package/src/commands/daemon.js.map +1 -0
  13. package/src/commands/dev.d.ts +15 -0
  14. package/src/commands/dev.d.ts.map +1 -0
  15. package/src/commands/dev.js +387 -0
  16. package/src/commands/dev.js.map +1 -0
  17. package/src/commands/doctor.d.ts +11 -0
  18. package/src/commands/doctor.d.ts.map +1 -0
  19. package/src/commands/doctor.js +129 -0
  20. package/src/commands/doctor.js.map +1 -0
  21. package/src/commands/index.d.ts +12 -0
  22. package/src/commands/index.d.ts.map +1 -0
  23. package/src/commands/index.js +12 -0
  24. package/src/commands/index.js.map +1 -0
  25. package/src/commands/setup.d.ts +13 -0
  26. package/src/commands/setup.d.ts.map +1 -0
  27. package/src/commands/setup.js +203 -0
  28. package/src/commands/setup.js.map +1 -0
  29. package/src/commands/status.d.ts +11 -0
  30. package/src/commands/status.d.ts.map +1 -0
  31. package/src/commands/status.js +63 -0
  32. package/src/commands/status.js.map +1 -0
  33. package/src/commands/uninstall.d.ts +11 -0
  34. package/src/commands/uninstall.d.ts.map +1 -0
  35. package/src/commands/uninstall.js +164 -0
  36. package/src/commands/uninstall.js.map +1 -0
  37. package/src/detect/index.d.ts +9 -0
  38. package/src/detect/index.d.ts.map +1 -0
  39. package/src/detect/index.js +9 -0
  40. package/src/detect/index.js.map +1 -0
  41. package/src/dev-tui/DevApp.d.ts +13 -0
  42. package/src/dev-tui/DevApp.d.ts.map +1 -0
  43. package/src/dev-tui/DevApp.js +118 -0
  44. package/src/dev-tui/DevApp.js.map +1 -0
  45. package/src/dev-tui/DevSetupApp.d.ts +22 -0
  46. package/src/dev-tui/DevSetupApp.d.ts.map +1 -0
  47. package/src/dev-tui/DevSetupApp.js +407 -0
  48. package/src/dev-tui/DevSetupApp.js.map +1 -0
  49. package/src/dev-tui/components/ActionMenu.d.ts +11 -0
  50. package/src/dev-tui/components/ActionMenu.d.ts.map +1 -0
  51. package/src/dev-tui/components/ActionMenu.js +25 -0
  52. package/src/dev-tui/components/ActionMenu.js.map +1 -0
  53. package/src/dev-tui/components/ActionResult.d.ts +12 -0
  54. package/src/dev-tui/components/ActionResult.d.ts.map +1 -0
  55. package/src/dev-tui/components/ActionResult.js +27 -0
  56. package/src/dev-tui/components/ActionResult.js.map +1 -0
  57. package/src/dev-tui/components/DevConfirm.d.ts +22 -0
  58. package/src/dev-tui/components/DevConfirm.d.ts.map +1 -0
  59. package/src/dev-tui/components/DevConfirm.js +73 -0
  60. package/src/dev-tui/components/DevConfirm.js.map +1 -0
  61. package/src/dev-tui/components/DevModeSelect.d.ts +12 -0
  62. package/src/dev-tui/components/DevModeSelect.d.ts.map +1 -0
  63. package/src/dev-tui/components/DevModeSelect.js +69 -0
  64. package/src/dev-tui/components/DevModeSelect.js.map +1 -0
  65. package/src/dev-tui/components/LogViewer.d.ts +11 -0
  66. package/src/dev-tui/components/LogViewer.d.ts.map +1 -0
  67. package/src/dev-tui/components/LogViewer.js +18 -0
  68. package/src/dev-tui/components/LogViewer.js.map +1 -0
  69. package/src/dev-tui/components/PathPrompt.d.ts +13 -0
  70. package/src/dev-tui/components/PathPrompt.d.ts.map +1 -0
  71. package/src/dev-tui/components/PathPrompt.js +48 -0
  72. package/src/dev-tui/components/PathPrompt.js.map +1 -0
  73. package/src/dev-tui/components/StatusBar.d.ts +13 -0
  74. package/src/dev-tui/components/StatusBar.d.ts.map +1 -0
  75. package/src/dev-tui/components/StatusBar.js +36 -0
  76. package/src/dev-tui/components/StatusBar.js.map +1 -0
  77. package/src/dev-tui/index.d.ts +7 -0
  78. package/src/dev-tui/index.d.ts.map +1 -0
  79. package/src/dev-tui/index.js +5 -0
  80. package/src/dev-tui/index.js.map +1 -0
  81. package/src/dev-tui/runner.d.ts +17 -0
  82. package/src/dev-tui/runner.d.ts.map +1 -0
  83. package/src/dev-tui/runner.js +53 -0
  84. package/src/dev-tui/runner.js.map +1 -0
  85. package/src/dev-tui/state.d.ts +34 -0
  86. package/src/dev-tui/state.d.ts.map +1 -0
  87. package/src/dev-tui/state.js +77 -0
  88. package/src/dev-tui/state.js.map +1 -0
  89. package/src/index.d.ts +15 -0
  90. package/src/index.d.ts.map +1 -0
  91. package/src/index.js +19 -0
  92. package/src/index.js.map +1 -0
  93. package/src/setup-server/index.d.ts +8 -0
  94. package/src/setup-server/index.d.ts.map +1 -0
  95. package/src/setup-server/index.js +7 -0
  96. package/src/setup-server/index.js.map +1 -0
  97. package/src/setup-server/routes.d.ts +22 -0
  98. package/src/setup-server/routes.d.ts.map +1 -0
  99. package/src/setup-server/routes.js +279 -0
  100. package/src/setup-server/routes.js.map +1 -0
  101. package/src/setup-server/server.d.ts +16 -0
  102. package/src/setup-server/server.d.ts.map +1 -0
  103. package/src/setup-server/server.js +125 -0
  104. package/src/setup-server/server.js.map +1 -0
  105. package/src/setup-server/sse.d.ts +31 -0
  106. package/src/setup-server/sse.d.ts.map +1 -0
  107. package/src/setup-server/sse.js +76 -0
  108. package/src/setup-server/sse.js.map +1 -0
  109. package/src/setup-server/static.d.ts +11 -0
  110. package/src/setup-server/static.d.ts.map +1 -0
  111. package/src/setup-server/static.js +33 -0
  112. package/src/setup-server/static.js.map +1 -0
  113. package/src/utils/daemon.d.ts +63 -0
  114. package/src/utils/daemon.d.ts.map +1 -0
  115. package/src/utils/daemon.js +377 -0
  116. package/src/utils/daemon.js.map +1 -0
  117. package/src/utils/find-test-harness.d.ts +5 -0
  118. package/src/utils/find-test-harness.d.ts.map +1 -0
  119. package/src/utils/find-test-harness.js +23 -0
  120. package/src/utils/find-test-harness.js.map +1 -0
  121. package/src/utils/index.d.ts +8 -0
  122. package/src/utils/index.d.ts.map +1 -0
  123. package/src/utils/index.js +8 -0
  124. package/src/utils/index.js.map +1 -0
  125. package/src/utils/privileges.d.ts +51 -0
  126. package/src/utils/privileges.d.ts.map +1 -0
  127. package/src/utils/privileges.js +125 -0
  128. package/src/utils/privileges.js.map +1 -0
  129. package/src/utils/sudo-env.d.ts +27 -0
  130. package/src/utils/sudo-env.d.ts.map +1 -0
  131. package/src/utils/sudo-env.js +63 -0
  132. package/src/utils/sudo-env.js.map +1 -0
  133. package/src/wizard/App.d.ts +6 -0
  134. package/src/wizard/App.d.ts.map +1 -0
  135. package/src/wizard/App.js +215 -0
  136. package/src/wizard/App.js.map +1 -0
  137. package/src/wizard/Uninstall.d.ts +16 -0
  138. package/src/wizard/Uninstall.d.ts.map +1 -0
  139. package/src/wizard/Uninstall.js +163 -0
  140. package/src/wizard/Uninstall.js.map +1 -0
  141. package/src/wizard/components/AdvancedConfig.d.ts +42 -0
  142. package/src/wizard/components/AdvancedConfig.d.ts.map +1 -0
  143. package/src/wizard/components/AdvancedConfig.js +131 -0
  144. package/src/wizard/components/AdvancedConfig.js.map +1 -0
  145. package/src/wizard/components/Confirm.d.ts +31 -0
  146. package/src/wizard/components/Confirm.d.ts.map +1 -0
  147. package/src/wizard/components/Confirm.js +148 -0
  148. package/src/wizard/components/Confirm.js.map +1 -0
  149. package/src/wizard/components/Header.d.ts +6 -0
  150. package/src/wizard/components/Header.d.ts.map +1 -0
  151. package/src/wizard/components/Header.js +11 -0
  152. package/src/wizard/components/Header.js.map +1 -0
  153. package/src/wizard/components/ModeSelect.d.ts +12 -0
  154. package/src/wizard/components/ModeSelect.d.ts.map +1 -0
  155. package/src/wizard/components/ModeSelect.js +74 -0
  156. package/src/wizard/components/ModeSelect.js.map +1 -0
  157. package/src/wizard/components/PasscodeSetup.d.ts +16 -0
  158. package/src/wizard/components/PasscodeSetup.d.ts.map +1 -0
  159. package/src/wizard/components/PasscodeSetup.js +119 -0
  160. package/src/wizard/components/PasscodeSetup.js.map +1 -0
  161. package/src/wizard/components/ProgressBar.d.ts +12 -0
  162. package/src/wizard/components/ProgressBar.d.ts.map +1 -0
  163. package/src/wizard/components/ProgressBar.js +18 -0
  164. package/src/wizard/components/ProgressBar.js.map +1 -0
  165. package/src/wizard/components/StepList.d.ts +12 -0
  166. package/src/wizard/components/StepList.d.ts.map +1 -0
  167. package/src/wizard/components/StepList.js +37 -0
  168. package/src/wizard/components/StepList.js.map +1 -0
  169. package/src/wizard/components/Summary.d.ts +12 -0
  170. package/src/wizard/components/Summary.d.ts.map +1 -0
  171. package/src/wizard/components/Summary.js +44 -0
  172. package/src/wizard/components/Summary.js.map +1 -0
  173. package/src/wizard/engine.d.ts +29 -0
  174. package/src/wizard/engine.d.ts.map +1 -0
  175. package/src/wizard/engine.js +866 -0
  176. package/src/wizard/engine.js.map +1 -0
  177. package/src/wizard/index.d.ts +8 -0
  178. package/src/wizard/index.d.ts.map +1 -0
  179. package/src/wizard/index.js +8 -0
  180. package/src/wizard/index.js.map +1 -0
  181. package/src/wizard/types.d.ts +190 -0
  182. package/src/wizard/types.d.ts.map +1 -0
  183. package/src/wizard/types.js +193 -0
  184. package/src/wizard/types.js.map +1 -0
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Setup command
3
+ *
4
+ * Runs the interactive setup wizard to sandbox a target application.
5
+ * Supports presets (openclaw, custom) and configurable naming.
6
+ * With --ui flag, launches a web-based setup wizard.
7
+ */
8
+ import { Command } from 'commander';
9
+ /**
10
+ * Create the setup command
11
+ */
12
+ export declare function createSetupCommand(): Command;
13
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/commands/setup.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8HpC;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CA+E5C"}
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Setup command
3
+ *
4
+ * Runs the interactive setup wizard to sandbox a target application.
5
+ * Supports presets (openclaw, custom) and configurable naming.
6
+ * With --ui flag, launches a web-based setup wizard.
7
+ */
8
+ import { Command } from 'commander';
9
+ import React from 'react';
10
+ import { render } from 'ink';
11
+ import { WizardApp } from '../wizard/index.js';
12
+ import { formatPresetList, getPreset } from '@agenshield/sandbox';
13
+ import { createWizardEngine } from '../wizard/engine.js';
14
+ /**
15
+ * Run the setup wizard (CLI/Ink mode)
16
+ */
17
+ async function runSetup() {
18
+ const { waitUntilExit } = render(React.createElement(WizardApp));
19
+ await waitUntilExit();
20
+ }
21
+ /**
22
+ * Run the setup wizard in web UI mode
23
+ */
24
+ async function runSetupWebUI(wizardOptions) {
25
+ const { createSetupServer } = await import('../setup-server/index.js');
26
+ console.log('');
27
+ console.log(' Starting Web UI Setup Wizard...');
28
+ console.log('');
29
+ // Create wizard engine and run detection phase BEFORE server starts
30
+ const engine = createWizardEngine(wizardOptions);
31
+ const detectionResult = await engine.runDetectionPhase();
32
+ if (!detectionResult.success) {
33
+ console.error(` Detection failed: ${detectionResult.error}`);
34
+ process.exit(1);
35
+ }
36
+ if (engine.context.presetDetection?.found) {
37
+ console.log(` Detected: ${engine.context.preset?.name ?? 'Unknown target'}`);
38
+ }
39
+ else if (engine.context.targetInstallable) {
40
+ console.log(` No target found — Web UI will offer installation.`);
41
+ }
42
+ else {
43
+ console.error(' No supported target found. Use --target custom --entry-point <path> for custom applications.');
44
+ process.exit(1);
45
+ }
46
+ console.log('');
47
+ // Acquire sudo credentials now (in the terminal) before opening the browser,
48
+ // so the setup phase can use cached credentials without a TTY prompt.
49
+ if (!wizardOptions.dryRun) {
50
+ const { ensureSudoAccess } = await import('../utils/privileges.js');
51
+ ensureSudoAccess();
52
+ }
53
+ // Create and start the setup server on a different port than daemon (5200)
54
+ const server = createSetupServer(engine);
55
+ const port = 5200; // Setup wizard uses 5200, daemon uses 5200
56
+ const url = await server.start(port);
57
+ console.log(` Setup wizard is running at: ${url}`);
58
+ console.log('');
59
+ console.log(' Opening browser...');
60
+ console.log(' (If the browser does not open, visit the URL above manually)');
61
+ console.log('');
62
+ // Open browser (macOS)
63
+ try {
64
+ const { exec } = await import('node:child_process');
65
+ exec(`open "${url}"`);
66
+ }
67
+ catch {
68
+ // Non-fatal — user can open the URL manually
69
+ }
70
+ // Wait for setup to complete or be cancelled (SIGINT/SIGTERM)
71
+ const completionOrSignal = Promise.race([
72
+ server.waitForCompletion(),
73
+ new Promise((resolve) => {
74
+ process.on('SIGINT', resolve);
75
+ process.on('SIGTERM', resolve);
76
+ }),
77
+ ]);
78
+ await completionOrSignal;
79
+ console.log(' Setup complete! Shutting down server...');
80
+ await server.stop();
81
+ // Stop any existing daemon first
82
+ console.log(' Stopping any existing daemon...');
83
+ const { startDaemon, stopDaemon } = await import('../utils/daemon.js');
84
+ await stopDaemon();
85
+ // Kill any process on port 5200 (daemon port)
86
+ try {
87
+ const { execSync } = await import('node:child_process');
88
+ execSync('lsof -i :5200 -t 2>/dev/null | xargs kill -9 2>/dev/null || true', { encoding: 'utf-8' });
89
+ await new Promise(r => setTimeout(r, 500));
90
+ }
91
+ catch { /* ignore */ }
92
+ // Start the daemon on port 5200
93
+ console.log(' Starting daemon...');
94
+ const daemonResult = await startDaemon();
95
+ if (daemonResult.success) {
96
+ console.log(` Daemon started (PID: ${daemonResult.pid})`);
97
+ console.log(` Dashboard available at: http://localhost:5200`);
98
+ }
99
+ else {
100
+ console.warn(` Warning: ${daemonResult.message}`);
101
+ }
102
+ // Force exit after grace period
103
+ setTimeout(() => process.exit(0), 500).unref();
104
+ }
105
+ /**
106
+ * Build WizardOptions from CLI options
107
+ */
108
+ function buildWizardOptions(options) {
109
+ const wizardOptions = {};
110
+ if (options['target'])
111
+ wizardOptions.targetPreset = options['target'];
112
+ if (options['entryPoint'])
113
+ wizardOptions.entryPoint = options['entryPoint'];
114
+ if (options['baseName'])
115
+ wizardOptions.baseName = options['baseName'];
116
+ if (options['prefix'])
117
+ wizardOptions.prefix = options['prefix'];
118
+ if (options['baseUid'])
119
+ wizardOptions.baseUid = options['baseUid'];
120
+ if (options['dryRun'])
121
+ wizardOptions.dryRun = true;
122
+ if (options['skipConfirm'])
123
+ wizardOptions.skipConfirm = true;
124
+ if (options['verbose'])
125
+ wizardOptions.verbose = true;
126
+ return wizardOptions;
127
+ }
128
+ /**
129
+ * Create the setup command
130
+ */
131
+ export function createSetupCommand() {
132
+ const cmd = new Command('setup')
133
+ .description('Run the setup wizard to sandbox a target application')
134
+ .option('--target <preset>', 'Target preset to use: openclaw, custom (default: auto-detect)')
135
+ .option('--entry-point <path>', 'Entry point for custom target (Node.js file)')
136
+ .option('--base-name <name>', 'Base name for users/groups (default: agenshield)')
137
+ .option('--prefix <prefix>', 'Use a custom prefix for users/groups (for testing)')
138
+ .option('--base-uid <uid>', 'Base UID for created users', parseInt)
139
+ .option('--dry-run', 'Show what would be done without making changes')
140
+ .option('--skip-confirm', 'Skip confirmation prompts')
141
+ .option('-v, --verbose', 'Show verbose output')
142
+ .option('--list-presets', 'List available presets and exit')
143
+ .option('--cli', 'Use terminal/Ink UI instead of web browser')
144
+ .action(async (options) => {
145
+ // Handle --list-presets
146
+ if (options.listPresets) {
147
+ console.log(formatPresetList());
148
+ return;
149
+ }
150
+ // Validate --target option
151
+ if (options.target) {
152
+ const preset = getPreset(options.target);
153
+ if (!preset) {
154
+ console.error(`Error: Unknown preset '${options.target}'`);
155
+ console.error('');
156
+ console.error(formatPresetList());
157
+ process.exit(1);
158
+ }
159
+ // Custom preset requires --entry-point
160
+ if (options.target === 'custom' && !options.entryPoint) {
161
+ console.error('Error: --entry-point is required when using --target custom');
162
+ console.error('');
163
+ console.error('Example:');
164
+ console.error(' agenshield setup --target custom --entry-point /path/to/my-app/dist/index.js');
165
+ process.exit(1);
166
+ }
167
+ }
168
+ // Default to Web UI unless --cli is specified or env var opts out
169
+ if (!options.cli && process.env['AGENSHIELD_WEBUI_REQUESTED'] !== 'false') {
170
+ delete process.env['AGENSHIELD_WEBUI_REQUESTED'];
171
+ await runSetupWebUI(buildWizardOptions(options));
172
+ return;
173
+ }
174
+ // Store options in environment for wizard to pick up
175
+ if (options.target) {
176
+ process.env['AGENSHIELD_TARGET'] = options.target;
177
+ }
178
+ if (options.entryPoint) {
179
+ process.env['AGENSHIELD_ENTRY_POINT'] = options.entryPoint;
180
+ }
181
+ if (options.baseName) {
182
+ process.env['AGENSHIELD_BASE_NAME'] = options.baseName;
183
+ }
184
+ if (options.prefix) {
185
+ process.env['AGENSHIELD_PREFIX'] = options.prefix;
186
+ }
187
+ if (options.baseUid) {
188
+ process.env['AGENSHIELD_BASE_UID'] = String(options.baseUid);
189
+ }
190
+ if (options.dryRun) {
191
+ process.env['AGENSHIELD_DRY_RUN'] = 'true';
192
+ }
193
+ if (options.skipConfirm) {
194
+ process.env['AGENSHIELD_SKIP_CONFIRM'] = 'true';
195
+ }
196
+ if (options.verbose) {
197
+ process.env['AGENSHIELD_VERBOSE'] = 'true';
198
+ }
199
+ await runSetup();
200
+ });
201
+ return cmd;
202
+ }
203
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/commands/setup.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGzD;;GAEG;AACH,KAAK,UAAU,QAAQ;IACrB,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;IACjE,MAAM,aAAa,EAAE,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,aAAa,CAAC,aAA4B;IACvD,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;IAEvE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,oEAAoE;IACpE,MAAM,MAAM,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;IACjD,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,iBAAiB,EAAE,CAAC;IAEzD,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,uBAAuB,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,KAAK,EAAE,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,IAAI,gBAAgB,EAAE,CAAC,CAAC;IAChF,CAAC;SAAM,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;IACrE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,gGAAgG,CAAC,CAAC;QAChH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,6EAA6E;IAC7E,sEAAsE;IACtE,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;QACpE,gBAAgB,EAAE,CAAC;IACrB,CAAC;IAED,2EAA2E;IAC3E,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,2CAA2C;IAC9D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAErC,OAAO,CAAC,GAAG,CAAC,iCAAiC,GAAG,EAAE,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,uBAAuB;IACvB,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACpD,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,6CAA6C;IAC/C,CAAC;IAED,8DAA8D;IAC9D,MAAM,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;QACtC,MAAM,CAAC,iBAAiB,EAAE;QAC1B,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAC5B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC9B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACjC,CAAC,CAAC;KACH,CAAC,CAAC;IAEH,MAAM,kBAAkB,CAAC;IACzB,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;IACzD,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IAEpB,iCAAiC;IACjC,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACjD,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACvE,MAAM,UAAU,EAAE,CAAC;IAEnB,8CAA8C;IAC9C,IAAI,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACxD,QAAQ,CAAC,kEAAkE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QACpG,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAExB,gCAAgC;IAChC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACpC,MAAM,YAAY,GAAG,MAAM,WAAW,EAAE,CAAC;IACzC,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,0BAA0B,YAAY,CAAC,GAAG,GAAG,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IACjE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,cAAc,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,gCAAgC;IAChC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,OAAgC;IAC1D,MAAM,aAAa,GAAkB,EAAE,CAAC;IACxC,IAAI,OAAO,CAAC,QAAQ,CAAC;QAAE,aAAa,CAAC,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAW,CAAC;IAChF,IAAI,OAAO,CAAC,YAAY,CAAC;QAAE,aAAa,CAAC,UAAU,GAAG,OAAO,CAAC,YAAY,CAAW,CAAC;IACtF,IAAI,OAAO,CAAC,UAAU,CAAC;QAAE,aAAa,CAAC,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAW,CAAC;IAChF,IAAI,OAAO,CAAC,QAAQ,CAAC;QAAE,aAAa,CAAC,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAW,CAAC;IAC1E,IAAI,OAAO,CAAC,SAAS,CAAC;QAAE,aAAa,CAAC,OAAO,GAAG,OAAO,CAAC,SAAS,CAAW,CAAC;IAC7E,IAAI,OAAO,CAAC,QAAQ,CAAC;QAAE,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC;IACnD,IAAI,OAAO,CAAC,aAAa,CAAC;QAAE,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC;IAC7D,IAAI,OAAO,CAAC,SAAS,CAAC;QAAE,aAAa,CAAC,OAAO,GAAG,IAAI,CAAC;IACrD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;SAC7B,WAAW,CAAC,sDAAsD,CAAC;SACnE,MAAM,CAAC,mBAAmB,EAAE,+DAA+D,CAAC;SAC5F,MAAM,CAAC,sBAAsB,EAAE,8CAA8C,CAAC;SAC9E,MAAM,CAAC,oBAAoB,EAAE,kDAAkD,CAAC;SAChF,MAAM,CAAC,mBAAmB,EAAE,oDAAoD,CAAC;SACjF,MAAM,CAAC,kBAAkB,EAAE,4BAA4B,EAAE,QAAQ,CAAC;SAClE,MAAM,CAAC,WAAW,EAAE,gDAAgD,CAAC;SACrE,MAAM,CAAC,gBAAgB,EAAE,2BAA2B,CAAC;SACrD,MAAM,CAAC,eAAe,EAAE,qBAAqB,CAAC;SAC9C,MAAM,CAAC,gBAAgB,EAAE,iCAAiC,CAAC;SAC3D,MAAM,CAAC,OAAO,EAAE,4CAA4C,CAAC;SAC7D,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,wBAAwB;QACxB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QAED,2BAA2B;QAC3B,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACzC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,CAAC,KAAK,CAAC,0BAA0B,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC3D,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAClB,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC;gBAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,uCAAuC;YACvC,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;gBACvD,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;gBAC7E,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAClB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,gFAAgF,CAAC,CAAC;gBAChG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAID,kEAAkE;QAClE,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,KAAK,OAAO,EAAE,CAAC;YAC1E,OAAO,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;YACjD,MAAM,aAAa,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;YACjD,OAAO;QACT,CAAC;QAED,qDAAqD;QACrD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;QACpD,CAAC;QACD,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;QAC7D,CAAC;QACD,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC;QACzD,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;QACpD,CAAC;QACD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/D,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,GAAG,MAAM,CAAC;QAC7C,CAAC;QACD,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,GAAG,MAAM,CAAC;QAClD,CAAC;QACD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,GAAG,MAAM,CAAC;QAC7C,CAAC;QAED,MAAM,QAAQ,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEL,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["/**\n * Setup command\n *\n * Runs the interactive setup wizard to sandbox a target application.\n * Supports presets (openclaw, custom) and configurable naming.\n * With --ui flag, launches a web-based setup wizard.\n */\n\nimport { Command } from 'commander';\nimport React from 'react';\nimport { render } from 'ink';\nimport { WizardApp } from '../wizard/index.js';\nimport { formatPresetList, getPreset } from '@agenshield/sandbox';\nimport { createWizardEngine } from '../wizard/engine.js';\nimport type { WizardOptions } from '../wizard/types.js';\n\n/**\n * Run the setup wizard (CLI/Ink mode)\n */\nasync function runSetup(): Promise<void> {\n const { waitUntilExit } = render(React.createElement(WizardApp));\n await waitUntilExit();\n}\n\n/**\n * Run the setup wizard in web UI mode\n */\nasync function runSetupWebUI(wizardOptions: WizardOptions): Promise<void> {\n const { createSetupServer } = await import('../setup-server/index.js');\n\n console.log('');\n console.log(' Starting Web UI Setup Wizard...');\n console.log('');\n\n // Create wizard engine and run detection phase BEFORE server starts\n const engine = createWizardEngine(wizardOptions);\n const detectionResult = await engine.runDetectionPhase();\n\n if (!detectionResult.success) {\n console.error(` Detection failed: ${detectionResult.error}`);\n process.exit(1);\n }\n\n if (engine.context.presetDetection?.found) {\n console.log(` Detected: ${engine.context.preset?.name ?? 'Unknown target'}`);\n } else if (engine.context.targetInstallable) {\n console.log(` No target found — Web UI will offer installation.`);\n } else {\n console.error(' No supported target found. Use --target custom --entry-point <path> for custom applications.');\n process.exit(1);\n }\n console.log('');\n\n // Acquire sudo credentials now (in the terminal) before opening the browser,\n // so the setup phase can use cached credentials without a TTY prompt.\n if (!wizardOptions.dryRun) {\n const { ensureSudoAccess } = await import('../utils/privileges.js');\n ensureSudoAccess();\n }\n\n // Create and start the setup server on a different port than daemon (5200)\n const server = createSetupServer(engine);\n const port = 5200; // Setup wizard uses 5200, daemon uses 5200\n const url = await server.start(port);\n\n console.log(` Setup wizard is running at: ${url}`);\n console.log('');\n console.log(' Opening browser...');\n console.log(' (If the browser does not open, visit the URL above manually)');\n console.log('');\n\n // Open browser (macOS)\n try {\n const { exec } = await import('node:child_process');\n exec(`open \"${url}\"`);\n } catch {\n // Non-fatal — user can open the URL manually\n }\n\n // Wait for setup to complete or be cancelled (SIGINT/SIGTERM)\n const completionOrSignal = Promise.race([\n server.waitForCompletion(),\n new Promise<void>((resolve) => {\n process.on('SIGINT', resolve);\n process.on('SIGTERM', resolve);\n }),\n ]);\n\n await completionOrSignal;\n console.log(' Setup complete! Shutting down server...');\n await server.stop();\n\n // Stop any existing daemon first\n console.log(' Stopping any existing daemon...');\n const { startDaemon, stopDaemon } = await import('../utils/daemon.js');\n await stopDaemon();\n\n // Kill any process on port 5200 (daemon port)\n try {\n const { execSync } = await import('node:child_process');\n execSync('lsof -i :5200 -t 2>/dev/null | xargs kill -9 2>/dev/null || true', { encoding: 'utf-8' });\n await new Promise(r => setTimeout(r, 500));\n } catch { /* ignore */ }\n\n // Start the daemon on port 5200\n console.log(' Starting daemon...');\n const daemonResult = await startDaemon();\n if (daemonResult.success) {\n console.log(` Daemon started (PID: ${daemonResult.pid})`);\n console.log(` Dashboard available at: http://localhost:5200`);\n } else {\n console.warn(` Warning: ${daemonResult.message}`);\n }\n\n // Force exit after grace period\n setTimeout(() => process.exit(0), 500).unref();\n}\n\n/**\n * Build WizardOptions from CLI options\n */\nfunction buildWizardOptions(options: Record<string, unknown>): WizardOptions {\n const wizardOptions: WizardOptions = {};\n if (options['target']) wizardOptions.targetPreset = options['target'] as string;\n if (options['entryPoint']) wizardOptions.entryPoint = options['entryPoint'] as string;\n if (options['baseName']) wizardOptions.baseName = options['baseName'] as string;\n if (options['prefix']) wizardOptions.prefix = options['prefix'] as string;\n if (options['baseUid']) wizardOptions.baseUid = options['baseUid'] as number;\n if (options['dryRun']) wizardOptions.dryRun = true;\n if (options['skipConfirm']) wizardOptions.skipConfirm = true;\n if (options['verbose']) wizardOptions.verbose = true;\n return wizardOptions;\n}\n\n/**\n * Create the setup command\n */\nexport function createSetupCommand(): Command {\n const cmd = new Command('setup')\n .description('Run the setup wizard to sandbox a target application')\n .option('--target <preset>', 'Target preset to use: openclaw, custom (default: auto-detect)')\n .option('--entry-point <path>', 'Entry point for custom target (Node.js file)')\n .option('--base-name <name>', 'Base name for users/groups (default: agenshield)')\n .option('--prefix <prefix>', 'Use a custom prefix for users/groups (for testing)')\n .option('--base-uid <uid>', 'Base UID for created users', parseInt)\n .option('--dry-run', 'Show what would be done without making changes')\n .option('--skip-confirm', 'Skip confirmation prompts')\n .option('-v, --verbose', 'Show verbose output')\n .option('--list-presets', 'List available presets and exit')\n .option('--cli', 'Use terminal/Ink UI instead of web browser')\n .action(async (options) => {\n // Handle --list-presets\n if (options.listPresets) {\n console.log(formatPresetList());\n return;\n }\n\n // Validate --target option\n if (options.target) {\n const preset = getPreset(options.target);\n if (!preset) {\n console.error(`Error: Unknown preset '${options.target}'`);\n console.error('');\n console.error(formatPresetList());\n process.exit(1);\n }\n\n // Custom preset requires --entry-point\n if (options.target === 'custom' && !options.entryPoint) {\n console.error('Error: --entry-point is required when using --target custom');\n console.error('');\n console.error('Example:');\n console.error(' agenshield setup --target custom --entry-point /path/to/my-app/dist/index.js');\n process.exit(1);\n }\n }\n\n\n\n // Default to Web UI unless --cli is specified or env var opts out\n if (!options.cli && process.env['AGENSHIELD_WEBUI_REQUESTED'] !== 'false') {\n delete process.env['AGENSHIELD_WEBUI_REQUESTED'];\n await runSetupWebUI(buildWizardOptions(options));\n return;\n }\n\n // Store options in environment for wizard to pick up\n if (options.target) {\n process.env['AGENSHIELD_TARGET'] = options.target;\n }\n if (options.entryPoint) {\n process.env['AGENSHIELD_ENTRY_POINT'] = options.entryPoint;\n }\n if (options.baseName) {\n process.env['AGENSHIELD_BASE_NAME'] = options.baseName;\n }\n if (options.prefix) {\n process.env['AGENSHIELD_PREFIX'] = options.prefix;\n }\n if (options.baseUid) {\n process.env['AGENSHIELD_BASE_UID'] = String(options.baseUid);\n }\n if (options.dryRun) {\n process.env['AGENSHIELD_DRY_RUN'] = 'true';\n }\n if (options.skipConfirm) {\n process.env['AGENSHIELD_SKIP_CONFIRM'] = 'true';\n }\n if (options.verbose) {\n process.env['AGENSHIELD_VERBOSE'] = 'true';\n }\n\n await runSetup();\n });\n\n return cmd;\n}\n"]}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Status command
3
+ *
4
+ * Shows the current AgenShield installation and security status.
5
+ */
6
+ import { Command } from 'commander';
7
+ /**
8
+ * Create the status command
9
+ */
10
+ export declare function createStatusCommand(): Command;
11
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiDpC;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAgB7C"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Status command
3
+ *
4
+ * Shows the current AgenShield installation and security status.
5
+ */
6
+ import { Command } from 'commander';
7
+ import { getEffectiveEnvForScanning } from '../utils/sudo-env.js';
8
+ /**
9
+ * Show the current status
10
+ */
11
+ async function showStatus() {
12
+ console.log('AgenShield Status');
13
+ console.log('=================\n');
14
+ const { detectOpenClaw, checkSecurityStatus } = await import('@agenshield/sandbox');
15
+ const detection = detectOpenClaw();
16
+ const security = checkSecurityStatus({ env: getEffectiveEnvForScanning() });
17
+ // Quick status indicators
18
+ const indicators = {
19
+ openclaw: detection.installation.found ? '✓' : '✗',
20
+ sandbox: security.sandboxUserExists ? '✓' : '○',
21
+ isolated: security.isIsolated ? '✓' : '○',
22
+ secrets: security.exposedSecrets.length === 0 ? '✓' : '⚠',
23
+ };
24
+ console.log(`OpenClaw: ${indicators.openclaw} ${detection.installation.found ? `v${detection.installation.version || 'unknown'} (${detection.installation.method})` : 'Not installed'}`);
25
+ console.log(`Sandbox User: ${indicators.sandbox} ${security.sandboxUserExists ? 'Created' : 'Not created'}`);
26
+ console.log(`Isolation: ${indicators.isolated} ${security.isIsolated ? 'Active' : 'Not active'}`);
27
+ console.log(`Secrets: ${indicators.secrets} ${security.exposedSecrets.length === 0 ? 'Protected' : `${security.exposedSecrets.length} exposed`}`);
28
+ // Overall status
29
+ console.log('\n─────────────────────');
30
+ if (security.critical.length > 0) {
31
+ console.log('Status: ⛔ CRITICAL - Immediate action required');
32
+ }
33
+ else if (security.isIsolated) {
34
+ console.log('Status: ✅ SECURE');
35
+ }
36
+ else if (security.sandboxUserExists) {
37
+ console.log('Status: ⚠ PARTIAL - OpenClaw not running in sandbox');
38
+ }
39
+ else {
40
+ console.log('Status: ⚠ UNPROTECTED - Run "agenshield setup"');
41
+ }
42
+ }
43
+ /**
44
+ * Create the status command
45
+ */
46
+ export function createStatusCommand() {
47
+ const cmd = new Command('status')
48
+ .description('Show current AgenShield status')
49
+ .option('-j, --json', 'Output as JSON')
50
+ .action(async (options) => {
51
+ if (options.json) {
52
+ const { detectOpenClaw, checkSecurityStatus } = await import('@agenshield/sandbox');
53
+ const detection = detectOpenClaw();
54
+ const security = checkSecurityStatus({ env: getEffectiveEnvForScanning() });
55
+ console.log(JSON.stringify({ detection, security }, null, 2));
56
+ }
57
+ else {
58
+ await showStatus();
59
+ }
60
+ });
61
+ return cmd;
62
+ }
63
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/status.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Status command\n *\n * Shows the current AgenShield installation and security status.\n */\n\nimport { Command } from 'commander';\nimport { getEffectiveEnvForScanning } from '../utils/sudo-env.js';\n\n/**\n * Show the current status\n */\nasync function showStatus(): Promise<void> {\n console.log('AgenShield Status');\n console.log('=================\\n');\n\n const { detectOpenClaw, checkSecurityStatus } = await import('@agenshield/sandbox');\n\n const detection = detectOpenClaw();\n const security = checkSecurityStatus({ env: getEffectiveEnvForScanning() });\n\n // Quick status indicators\n const indicators = {\n openclaw: detection.installation.found ? '✓' : '✗',\n sandbox: security.sandboxUserExists ? '✓' : '○',\n isolated: security.isIsolated ? '✓' : '○',\n secrets: security.exposedSecrets.length === 0 ? '✓' : '⚠',\n };\n\n console.log(\n `OpenClaw: ${indicators.openclaw} ${detection.installation.found ? `v${detection.installation.version || 'unknown'} (${detection.installation.method})` : 'Not installed'}`\n );\n console.log(\n `Sandbox User: ${indicators.sandbox} ${security.sandboxUserExists ? 'Created' : 'Not created'}`\n );\n console.log(\n `Isolation: ${indicators.isolated} ${security.isIsolated ? 'Active' : 'Not active'}`\n );\n console.log(\n `Secrets: ${indicators.secrets} ${security.exposedSecrets.length === 0 ? 'Protected' : `${security.exposedSecrets.length} exposed`}`\n );\n\n // Overall status\n console.log('\\n─────────────────────');\n if (security.critical.length > 0) {\n console.log('Status: ⛔ CRITICAL - Immediate action required');\n } else if (security.isIsolated) {\n console.log('Status: ✅ SECURE');\n } else if (security.sandboxUserExists) {\n console.log('Status: ⚠ PARTIAL - OpenClaw not running in sandbox');\n } else {\n console.log('Status: ⚠ UNPROTECTED - Run \"agenshield setup\"');\n }\n}\n\n/**\n * Create the status command\n */\nexport function createStatusCommand(): Command {\n const cmd = new Command('status')\n .description('Show current AgenShield status')\n .option('-j, --json', 'Output as JSON')\n .action(async (options) => {\n if (options.json) {\n const { detectOpenClaw, checkSecurityStatus } = await import('@agenshield/sandbox');\n const detection = detectOpenClaw();\n const security = checkSecurityStatus({ env: getEffectiveEnvForScanning() });\n console.log(JSON.stringify({ detection, security }, null, 2));\n } else {\n await showStatus();\n }\n });\n\n return cmd;\n}\n"]}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Uninstall command
3
+ *
4
+ * Reverses the AgenShield installation and restores OpenClaw to its original state.
5
+ */
6
+ import { Command } from 'commander';
7
+ /**
8
+ * Create the uninstall command
9
+ */
10
+ export declare function createUninstallCommand(): Command;
11
+ //# sourceMappingURL=uninstall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../../src/commands/uninstall.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyKpC;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAWhD"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Uninstall command
3
+ *
4
+ * Reverses the AgenShield installation and restores OpenClaw to its original state.
5
+ */
6
+ import { Command } from 'commander';
7
+ import * as fs from 'node:fs';
8
+ import * as os from 'node:os';
9
+ import * as path from 'node:path';
10
+ import * as readline from 'node:readline';
11
+ import { ensureSudoAccess } from '../utils/privileges.js';
12
+ import { stopDaemon } from '../utils/daemon.js';
13
+ /**
14
+ * Run the uninstall process
15
+ */
16
+ async function runUninstall(options) {
17
+ ensureSudoAccess();
18
+ const { canUninstall, restoreInstallation, forceUninstall } = await import('@agenshield/sandbox');
19
+ // Check if backup exists
20
+ const check = canUninstall();
21
+ // Handle --skip-backup flag for force uninstall without backup
22
+ if (options.skipBackup) {
23
+ console.log('\x1b[33mForce Uninstall (No Backup)\x1b[0m');
24
+ console.log('============================\n');
25
+ console.log('This will:');
26
+ console.log(' \x1b[33m->\x1b[0m Stop and remove agenshield daemon');
27
+ console.log(' \x1b[33m->\x1b[0m Delete any discovered sandbox users (ash_*)');
28
+ console.log(' \x1b[33m->\x1b[0m Delete any discovered workspace groups (ash_*_workspace)');
29
+ console.log(' \x1b[33m->\x1b[0m Remove guarded shell');
30
+ console.log(' \x1b[33m->\x1b[0m Delete /etc/agenshield configuration');
31
+ console.log('');
32
+ console.log('\x1b[31mWARNING: This will NOT restore OpenClaw to its original state!\x1b[0m');
33
+ console.log('');
34
+ if (!options.force) {
35
+ const rl = readline.createInterface({
36
+ input: process.stdin,
37
+ output: process.stdout,
38
+ });
39
+ const answer = await new Promise((resolve) => {
40
+ rl.question('Type FORCE to confirm: ', (answer) => {
41
+ rl.close();
42
+ resolve(answer);
43
+ });
44
+ });
45
+ if (answer !== 'FORCE') {
46
+ console.log('\nUninstall cancelled.');
47
+ process.exit(0);
48
+ }
49
+ }
50
+ console.log('\nForce uninstalling...\n');
51
+ const result = forceUninstall((progress) => {
52
+ const icon = progress.success ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
53
+ console.log(`${icon} ${progress.step}: ${progress.message || progress.error || ''}`);
54
+ });
55
+ console.log('');
56
+ if (result.success) {
57
+ console.log('\x1b[32mForce uninstall complete!\x1b[0m');
58
+ console.log('AgenShield artifacts have been removed.');
59
+ }
60
+ else {
61
+ console.log('\x1b[31mForce uninstall failed!\x1b[0m');
62
+ console.log(result.error || 'Unknown error');
63
+ process.exit(1);
64
+ }
65
+ return;
66
+ }
67
+ if (!check.canUninstall || !check.backup) {
68
+ console.log('\x1b[31mNo backup found.\x1b[0m');
69
+ console.log('Cannot safely uninstall without a backup.');
70
+ console.log('The backup is created during "agenshield setup".');
71
+ console.log('');
72
+ console.log('To force uninstall without a backup, use:');
73
+ console.log(' \x1b[36msudo agenshield uninstall --skip-backup\x1b[0m');
74
+ process.exit(1);
75
+ }
76
+ const backup = check.backup;
77
+ // Show warning
78
+ console.log('\x1b[31mAgenShield Uninstall\x1b[0m');
79
+ console.log('====================\n');
80
+ console.log('This will:');
81
+ console.log(' \x1b[33m->\x1b[0m Stop and remove agenshield daemon');
82
+ console.log(' \x1b[33m->\x1b[0m Restore OpenClaw to original location');
83
+ console.log(` \x1b[33m->\x1b[0m Delete sandbox user "${backup.sandboxUser.username}"`);
84
+ console.log(' \x1b[33m->\x1b[0m Remove guarded shell');
85
+ console.log(' \x1b[33m->\x1b[0m Delete /etc/agenshield configuration');
86
+ console.log('');
87
+ console.log(`Backup found: ${backup.timestamp}`);
88
+ console.log('');
89
+ console.log('\x1b[31mWARNING: This action cannot be undone!\x1b[0m');
90
+ console.log('');
91
+ // Skip confirmation if --force
92
+ if (!options.force) {
93
+ // Prompt for confirmation
94
+ const rl = readline.createInterface({
95
+ input: process.stdin,
96
+ output: process.stdout,
97
+ });
98
+ const answer = await new Promise((resolve) => {
99
+ rl.question('Type UNINSTALL to confirm: ', (answer) => {
100
+ rl.close();
101
+ resolve(answer);
102
+ });
103
+ });
104
+ if (answer !== 'UNINSTALL') {
105
+ console.log('\nUninstall cancelled.');
106
+ process.exit(0);
107
+ }
108
+ }
109
+ console.log('\nUninstalling...\n');
110
+ // Stop daemon first (handles launchctl, PID, port fallback)
111
+ console.log('Stopping daemon...');
112
+ const stopResult = await stopDaemon();
113
+ const stopIcon = stopResult.success ? '\x1b[32m✓\x1b[0m' : '\x1b[33m!\x1b[0m';
114
+ console.log(`${stopIcon} stop-daemon: ${stopResult.message}`);
115
+ console.log('');
116
+ // Run the uninstall process
117
+ const result = restoreInstallation(backup, (progress) => {
118
+ const icon = progress.success ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
119
+ console.log(`${icon} ${progress.step}: ${progress.message || progress.error || ''}`);
120
+ });
121
+ console.log('');
122
+ if (result.success) {
123
+ console.log('\x1b[32mUninstall complete!\x1b[0m');
124
+ console.log('OpenClaw has been restored to its original location.');
125
+ console.log('Run "openclaw --version" to verify.');
126
+ // Offer to delete ~/.agenshield data directory
127
+ const agenshieldDir = path.join(os.homedir(), '.agenshield');
128
+ if (!options.force && fs.existsSync(agenshieldDir)) {
129
+ console.log('');
130
+ const rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });
131
+ const deleteData = await new Promise((resolve) => {
132
+ rl2.question(`Delete ${agenshieldDir} to remove all data (config, vault, logs)? [y/N] `, (answer) => { rl2.close(); resolve(answer); });
133
+ });
134
+ if (deleteData.toLowerCase() === 'y' || deleteData.toLowerCase() === 'yes') {
135
+ fs.rmSync(agenshieldDir, { recursive: true, force: true });
136
+ console.log(`\x1b[32m✓\x1b[0m Deleted ${agenshieldDir}`);
137
+ }
138
+ else {
139
+ console.log(`Kept ${agenshieldDir} (contains config, vault, activity logs)`);
140
+ }
141
+ }
142
+ }
143
+ else {
144
+ console.log('\x1b[31mUninstall failed!\x1b[0m');
145
+ console.log(result.error || 'Unknown error');
146
+ console.log('Please check the errors above and try again.');
147
+ process.exit(1);
148
+ }
149
+ }
150
+ /**
151
+ * Create the uninstall command
152
+ */
153
+ export function createUninstallCommand() {
154
+ const cmd = new Command('uninstall')
155
+ .description('Reverse isolation and restore OpenClaw')
156
+ .option('-f, --force', 'Skip confirmation prompt')
157
+ .option('--prefix <prefix>', 'Uninstall a specific prefixed installation')
158
+ .option('--skip-backup', 'Force uninstall without a backup (will not restore OpenClaw)')
159
+ .action(async (options) => {
160
+ await runUninstall(options);
161
+ });
162
+ return cmd;
163
+ }
164
+ //# sourceMappingURL=uninstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../../src/commands/uninstall.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Uninstall command\n *\n * Reverses the AgenShield installation and restores OpenClaw to its original state.\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport * as readline from 'node:readline';\nimport { ensureSudoAccess } from '../utils/privileges.js';\nimport { stopDaemon } from '../utils/daemon.js';\n\n/**\n * Run the uninstall process\n */\nasync function runUninstall(options: { force?: boolean; prefix?: string; skipBackup?: boolean }): Promise<void> {\n ensureSudoAccess();\n\n const { canUninstall, restoreInstallation, forceUninstall } = await import('@agenshield/sandbox');\n\n // Check if backup exists\n const check = canUninstall();\n\n // Handle --skip-backup flag for force uninstall without backup\n if (options.skipBackup) {\n console.log('\\x1b[33mForce Uninstall (No Backup)\\x1b[0m');\n console.log('============================\\n');\n console.log('This will:');\n console.log(' \\x1b[33m->\\x1b[0m Stop and remove agenshield daemon');\n console.log(' \\x1b[33m->\\x1b[0m Delete any discovered sandbox users (ash_*)');\n console.log(' \\x1b[33m->\\x1b[0m Delete any discovered workspace groups (ash_*_workspace)');\n console.log(' \\x1b[33m->\\x1b[0m Remove guarded shell');\n console.log(' \\x1b[33m->\\x1b[0m Delete /etc/agenshield configuration');\n console.log('');\n console.log('\\x1b[31mWARNING: This will NOT restore OpenClaw to its original state!\\x1b[0m');\n console.log('');\n\n if (!options.force) {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const answer = await new Promise<string>((resolve) => {\n rl.question('Type FORCE to confirm: ', (answer) => {\n rl.close();\n resolve(answer);\n });\n });\n\n if (answer !== 'FORCE') {\n console.log('\\nUninstall cancelled.');\n process.exit(0);\n }\n }\n\n console.log('\\nForce uninstalling...\\n');\n\n const result = forceUninstall((progress) => {\n const icon = progress.success ? '\\x1b[32m✓\\x1b[0m' : '\\x1b[31m✗\\x1b[0m';\n console.log(`${icon} ${progress.step}: ${progress.message || progress.error || ''}`);\n });\n\n console.log('');\n\n if (result.success) {\n console.log('\\x1b[32mForce uninstall complete!\\x1b[0m');\n console.log('AgenShield artifacts have been removed.');\n } else {\n console.log('\\x1b[31mForce uninstall failed!\\x1b[0m');\n console.log(result.error || 'Unknown error');\n process.exit(1);\n }\n return;\n }\n\n if (!check.canUninstall || !check.backup) {\n console.log('\\x1b[31mNo backup found.\\x1b[0m');\n console.log('Cannot safely uninstall without a backup.');\n console.log('The backup is created during \"agenshield setup\".');\n console.log('');\n console.log('To force uninstall without a backup, use:');\n console.log(' \\x1b[36msudo agenshield uninstall --skip-backup\\x1b[0m');\n process.exit(1);\n }\n\n const backup = check.backup;\n\n // Show warning\n console.log('\\x1b[31mAgenShield Uninstall\\x1b[0m');\n console.log('====================\\n');\n console.log('This will:');\n console.log(' \\x1b[33m->\\x1b[0m Stop and remove agenshield daemon');\n console.log(' \\x1b[33m->\\x1b[0m Restore OpenClaw to original location');\n console.log(` \\x1b[33m->\\x1b[0m Delete sandbox user \"${backup.sandboxUser.username}\"`);\n console.log(' \\x1b[33m->\\x1b[0m Remove guarded shell');\n console.log(' \\x1b[33m->\\x1b[0m Delete /etc/agenshield configuration');\n console.log('');\n console.log(`Backup found: ${backup.timestamp}`);\n console.log('');\n console.log('\\x1b[31mWARNING: This action cannot be undone!\\x1b[0m');\n console.log('');\n\n // Skip confirmation if --force\n if (!options.force) {\n // Prompt for confirmation\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const answer = await new Promise<string>((resolve) => {\n rl.question('Type UNINSTALL to confirm: ', (answer) => {\n rl.close();\n resolve(answer);\n });\n });\n\n if (answer !== 'UNINSTALL') {\n console.log('\\nUninstall cancelled.');\n process.exit(0);\n }\n }\n\n console.log('\\nUninstalling...\\n');\n\n // Stop daemon first (handles launchctl, PID, port fallback)\n console.log('Stopping daemon...');\n const stopResult = await stopDaemon();\n const stopIcon = stopResult.success ? '\\x1b[32m✓\\x1b[0m' : '\\x1b[33m!\\x1b[0m';\n console.log(`${stopIcon} stop-daemon: ${stopResult.message}`);\n console.log('');\n\n // Run the uninstall process\n const result = restoreInstallation(backup, (progress) => {\n const icon = progress.success ? '\\x1b[32m✓\\x1b[0m' : '\\x1b[31m✗\\x1b[0m';\n console.log(`${icon} ${progress.step}: ${progress.message || progress.error || ''}`);\n });\n\n console.log('');\n\n if (result.success) {\n console.log('\\x1b[32mUninstall complete!\\x1b[0m');\n console.log('OpenClaw has been restored to its original location.');\n console.log('Run \"openclaw --version\" to verify.');\n\n // Offer to delete ~/.agenshield data directory\n const agenshieldDir = path.join(os.homedir(), '.agenshield');\n if (!options.force && fs.existsSync(agenshieldDir)) {\n console.log('');\n const rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });\n const deleteData = await new Promise<string>((resolve) => {\n rl2.question(\n `Delete ${agenshieldDir} to remove all data (config, vault, logs)? [y/N] `,\n (answer) => { rl2.close(); resolve(answer); }\n );\n });\n\n if (deleteData.toLowerCase() === 'y' || deleteData.toLowerCase() === 'yes') {\n fs.rmSync(agenshieldDir, { recursive: true, force: true });\n console.log(`\\x1b[32m✓\\x1b[0m Deleted ${agenshieldDir}`);\n } else {\n console.log(`Kept ${agenshieldDir} (contains config, vault, activity logs)`);\n }\n }\n } else {\n console.log('\\x1b[31mUninstall failed!\\x1b[0m');\n console.log(result.error || 'Unknown error');\n console.log('Please check the errors above and try again.');\n process.exit(1);\n }\n}\n\n/**\n * Create the uninstall command\n */\nexport function createUninstallCommand(): Command {\n const cmd = new Command('uninstall')\n .description('Reverse isolation and restore OpenClaw')\n .option('-f, --force', 'Skip confirmation prompt')\n .option('--prefix <prefix>', 'Uninstall a specific prefixed installation')\n .option('--skip-backup', 'Force uninstall without a backup (will not restore OpenClaw)')\n .action(async (options) => {\n await runUninstall(options);\n });\n\n return cmd;\n}\n"]}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * OpenClaw detection module
3
+ *
4
+ * Re-exports from @agenshield/sandbox for backwards compatibility.
5
+ * The detection logic has been moved to shield-sandbox so it can
6
+ * be shared between the CLI and daemon.
7
+ */
8
+ export { type InstallMethod, type OpenClawInstallation, type DetectionResult, type PrerequisitesResult, type SecurityStatus, detectOpenClaw, checkPrerequisites, checkSecurityStatus, } from '@agenshield/sandbox';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/detect/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,cAAc,EACd,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * OpenClaw detection module
3
+ *
4
+ * Re-exports from @agenshield/sandbox for backwards compatibility.
5
+ * The detection logic has been moved to shield-sandbox so it can
6
+ * be shared between the CLI and daemon.
7
+ */
8
+ export { detectOpenClaw, checkPrerequisites, checkSecurityStatus, } from '@agenshield/sandbox';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/detect/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAML,cAAc,EACd,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC","sourcesContent":["/**\n * OpenClaw detection module\n *\n * Re-exports from @agenshield/sandbox for backwards compatibility.\n * The detection logic has been moved to shield-sandbox so it can\n * be shared between the CLI and daemon.\n */\n\nexport {\n type InstallMethod,\n type OpenClawInstallation,\n type DetectionResult,\n type PrerequisitesResult,\n type SecurityStatus,\n detectOpenClaw,\n checkPrerequisites,\n checkSecurityStatus,\n} from '@agenshield/sandbox';\n"]}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * DevApp - Root TUI component for dev mode.
3
+ *
4
+ * Manages phase-driven rendering: ready → prompting → running_action → viewing_logs.
5
+ */
6
+ import React from 'react';
7
+ import type { DevState } from './state.js';
8
+ interface DevAppProps {
9
+ devState: DevState;
10
+ }
11
+ export declare function DevApp({ devState }: DevAppProps): React.JSX.Element;
12
+ export {};
13
+ //# sourceMappingURL=DevApp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DevApp.d.ts","sourceRoot":"","sources":["../../../src/dev-tui/DevApp.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAA2C,MAAM,OAAO,CAAC;AAUhE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAM3C,UAAU,WAAW;IACnB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW,qBA8I/C"}