windows-development-sandbox 0.0.0-stage → 1.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.
Files changed (231) hide show
  1. package/.sandbox-config.example.json +14 -0
  2. package/README.md +78 -2
  3. package/config.example.json +332 -0
  4. package/dist/api.d.ts +31 -0
  5. package/dist/api.js +30 -0
  6. package/dist/bin/agent-sandbox.d.ts +2 -0
  7. package/dist/bin/agent-sandbox.js +3 -0
  8. package/dist/bin/claude-host.d.ts +2 -0
  9. package/dist/bin/claude-host.js +5 -0
  10. package/dist/bin/claude-sbx.d.ts +2 -0
  11. package/dist/bin/claude-sbx.js +3 -0
  12. package/dist/bin/codex-sbx.d.ts +2 -0
  13. package/dist/bin/codex-sbx.js +3 -0
  14. package/dist/bin/gemini-sbx.d.ts +2 -0
  15. package/dist/bin/gemini-sbx.js +3 -0
  16. package/dist/bin/sandbox.d.ts +2 -0
  17. package/dist/bin/sandbox.js +4 -0
  18. package/dist/bin/sbx-hide.d.ts +2 -0
  19. package/dist/bin/sbx-hide.js +3 -0
  20. package/dist/bin/sbx-show.d.ts +2 -0
  21. package/dist/bin/sbx-show.js +3 -0
  22. package/dist/cli/args.d.ts +32 -0
  23. package/dist/cli/args.js +111 -0
  24. package/dist/cli/commands/accounts.d.ts +2 -0
  25. package/dist/cli/commands/accounts.js +52 -0
  26. package/dist/cli/commands/context.d.ts +21 -0
  27. package/dist/cli/commands/context.js +54 -0
  28. package/dist/cli/commands/data.d.ts +46 -0
  29. package/dist/cli/commands/data.js +249 -0
  30. package/dist/cli/commands/index.d.ts +8 -0
  31. package/dist/cli/commands/index.js +8 -0
  32. package/dist/cli/commands/launch.d.ts +5 -0
  33. package/dist/cli/commands/launch.js +152 -0
  34. package/dist/cli/commands/maintenance.d.ts +8 -0
  35. package/dist/cli/commands/maintenance.js +125 -0
  36. package/dist/cli/commands/repair.d.ts +59 -0
  37. package/dist/cli/commands/repair.js +332 -0
  38. package/dist/cli/commands/sessions.d.ts +11 -0
  39. package/dist/cli/commands/sessions.js +113 -0
  40. package/dist/cli/commands/setup.d.ts +45 -0
  41. package/dist/cli/commands/setup.js +152 -0
  42. package/dist/cli/index.d.ts +14 -0
  43. package/dist/cli/index.js +96 -0
  44. package/dist/cli/manifest.d.ts +95 -0
  45. package/dist/cli/manifest.js +87 -0
  46. package/dist/cli/menu.d.ts +22 -0
  47. package/dist/cli/menu.js +187 -0
  48. package/dist/cli/settings.d.ts +11 -0
  49. package/dist/cli/settings.js +156 -0
  50. package/dist/core/config.d.ts +17 -0
  51. package/dist/core/config.js +103 -0
  52. package/dist/core/detect-databases.d.ts +15 -0
  53. package/dist/core/detect-databases.js +147 -0
  54. package/dist/core/detect-pwsh.d.ts +18 -0
  55. package/dist/core/detect-pwsh.js +111 -0
  56. package/dist/core/detect-toolchains.d.ts +30 -0
  57. package/dist/core/detect-toolchains.js +58 -0
  58. package/dist/core/local-config.d.ts +12 -0
  59. package/dist/core/local-config.js +64 -0
  60. package/dist/core/schema.d.ts +604 -0
  61. package/dist/core/schema.js +264 -0
  62. package/dist/core/types.d.ts +162 -0
  63. package/dist/core/types.js +1 -0
  64. package/dist/core/util.d.ts +53 -0
  65. package/dist/core/util.js +145 -0
  66. package/dist/core/workspace.d.ts +23 -0
  67. package/dist/core/workspace.js +162 -0
  68. package/dist/guest/daemon.d.ts +1 -0
  69. package/dist/guest/daemon.js +186 -0
  70. package/dist/guest/db.d.ts +1 -0
  71. package/dist/guest/db.js +60 -0
  72. package/dist/guest/env.d.ts +49 -0
  73. package/dist/guest/env.js +99 -0
  74. package/dist/guest/gitguard.d.ts +7 -0
  75. package/dist/guest/gitguard.js +60 -0
  76. package/dist/guest/gitrules.d.ts +2 -0
  77. package/dist/guest/gitrules.js +11 -0
  78. package/dist/guest/guide.d.ts +12 -0
  79. package/dist/guest/guide.js +68 -0
  80. package/dist/guest/main.d.ts +1 -0
  81. package/dist/guest/main.js +120 -0
  82. package/dist/guest/ptyhost.d.ts +40 -0
  83. package/dist/guest/ptyhost.js +94 -0
  84. package/dist/guest/setup/agents.d.ts +8 -0
  85. package/dist/guest/setup/agents.js +73 -0
  86. package/dist/guest/setup/claude.d.ts +21 -0
  87. package/dist/guest/setup/claude.js +138 -0
  88. package/dist/guest/setup/environment.d.ts +6 -0
  89. package/dist/guest/setup/environment.js +65 -0
  90. package/dist/guest/setup/hooks.d.ts +1 -0
  91. package/dist/guest/setup/hooks.js +36 -0
  92. package/dist/guest/setup/network.d.ts +10 -0
  93. package/dist/guest/setup/network.js +99 -0
  94. package/dist/guest/setup/policy.d.ts +3 -0
  95. package/dist/guest/setup/policy.js +18 -0
  96. package/dist/guest/setup/user.d.ts +7 -0
  97. package/dist/guest/setup/user.js +47 -0
  98. package/dist/guest/toolchains/binstall.d.ts +7 -0
  99. package/dist/guest/toolchains/binstall.js +55 -0
  100. package/dist/guest/toolchains/catalogue.d.ts +51 -0
  101. package/dist/guest/toolchains/catalogue.js +31 -0
  102. package/dist/guest/toolchains/cli.d.ts +10 -0
  103. package/dist/guest/toolchains/cli.js +64 -0
  104. package/dist/guest/toolchains/common.d.ts +37 -0
  105. package/dist/guest/toolchains/common.js +124 -0
  106. package/dist/guest/toolchains/databases.d.ts +7 -0
  107. package/dist/guest/toolchains/databases.js +226 -0
  108. package/dist/guest/toolchains/git.d.ts +3 -0
  109. package/dist/guest/toolchains/git.js +112 -0
  110. package/dist/guest/toolchains/go.d.ts +3 -0
  111. package/dist/guest/toolchains/go.js +33 -0
  112. package/dist/guest/toolchains/index.d.ts +13 -0
  113. package/dist/guest/toolchains/index.js +122 -0
  114. package/dist/guest/toolchains/java.d.ts +8 -0
  115. package/dist/guest/toolchains/java.js +96 -0
  116. package/dist/guest/toolchains/managers.d.ts +16 -0
  117. package/dist/guest/toolchains/managers.js +82 -0
  118. package/dist/guest/toolchains/msvc.d.ts +10 -0
  119. package/dist/guest/toolchains/msvc.js +216 -0
  120. package/dist/guest/toolchains/native.d.ts +12 -0
  121. package/dist/guest/toolchains/native.js +220 -0
  122. package/dist/guest/toolchains/node.d.ts +3 -0
  123. package/dist/guest/toolchains/node.js +132 -0
  124. package/dist/guest/toolchains/pwsh.d.ts +4 -0
  125. package/dist/guest/toolchains/pwsh.js +14 -0
  126. package/dist/guest/toolchains/python.d.ts +3 -0
  127. package/dist/guest/toolchains/python.js +47 -0
  128. package/dist/guest/toolchains/runtimes.d.ts +17 -0
  129. package/dist/guest/toolchains/runtimes.js +40 -0
  130. package/dist/guest/toolchains/scripting.d.ts +10 -0
  131. package/dist/guest/toolchains/scripting.js +137 -0
  132. package/dist/guest/toolchains/versions.d.ts +47 -0
  133. package/dist/guest/toolchains/versions.js +77 -0
  134. package/dist/guest/toolchains/vscode.d.ts +2 -0
  135. package/dist/guest/toolchains/vscode.js +53 -0
  136. package/dist/guest/view.d.ts +1 -0
  137. package/dist/guest/view.js +22 -0
  138. package/dist/host/accounts.d.ts +32 -0
  139. package/dist/host/accounts.js +119 -0
  140. package/dist/host/channel.d.ts +37 -0
  141. package/dist/host/channel.js +180 -0
  142. package/dist/host/claude-profile.d.ts +15 -0
  143. package/dist/host/claude-profile.js +103 -0
  144. package/dist/host/cleanup.d.ts +23 -0
  145. package/dist/host/cleanup.js +66 -0
  146. package/dist/host/generate.d.ts +15 -0
  147. package/dist/host/generate.js +185 -0
  148. package/dist/host/personalize.d.ts +10 -0
  149. package/dist/host/personalize.js +97 -0
  150. package/dist/host/platform.d.ts +17 -0
  151. package/dist/host/platform.js +114 -0
  152. package/dist/host/project-scan.d.ts +23 -0
  153. package/dist/host/project-scan.js +173 -0
  154. package/dist/host/repo-guard.d.ts +23 -0
  155. package/dist/host/repo-guard.js +128 -0
  156. package/dist/host/secrets.d.ts +14 -0
  157. package/dist/host/secrets.js +133 -0
  158. package/dist/host/terminal.d.ts +32 -0
  159. package/dist/host/terminal.js +127 -0
  160. package/dist/host/window.d.ts +4 -0
  161. package/dist/host/window.js +68 -0
  162. package/dist/runtime/daemon.js +20291 -0
  163. package/dist/runtime/db.js +20423 -0
  164. package/dist/runtime/gitguard.js +84 -0
  165. package/dist/runtime/main.js +22398 -0
  166. package/dist/runtime/view.js +19966 -0
  167. package/dist/selftest/cli.test.d.ts +2 -0
  168. package/dist/selftest/cli.test.js +30 -0
  169. package/dist/selftest/config.test.d.ts +3 -0
  170. package/dist/selftest/config.test.js +74 -0
  171. package/dist/selftest/data.test.d.ts +2 -0
  172. package/dist/selftest/data.test.js +73 -0
  173. package/dist/selftest/detect.test.d.ts +2 -0
  174. package/dist/selftest/detect.test.js +42 -0
  175. package/dist/selftest/fixtures.d.ts +232 -0
  176. package/dist/selftest/fixtures.js +63 -0
  177. package/dist/selftest/guest.test.d.ts +3 -0
  178. package/dist/selftest/guest.test.js +61 -0
  179. package/dist/selftest/harness.d.ts +14 -0
  180. package/dist/selftest/harness.js +36 -0
  181. package/dist/selftest/helpers.test.d.ts +2 -0
  182. package/dist/selftest/helpers.test.js +125 -0
  183. package/dist/selftest/host.test.d.ts +2 -0
  184. package/dist/selftest/host.test.js +71 -0
  185. package/dist/selftest/index.d.ts +1 -0
  186. package/dist/selftest/index.js +56 -0
  187. package/dist/selftest/live.test.d.ts +7 -0
  188. package/dist/selftest/live.test.js +127 -0
  189. package/dist/selftest/mirror.test.d.ts +3 -0
  190. package/dist/selftest/mirror.test.js +74 -0
  191. package/dist/selftest/security.test.d.ts +3 -0
  192. package/dist/selftest/security.test.js +143 -0
  193. package/dist/selftest/setup.test.d.ts +2 -0
  194. package/dist/selftest/setup.test.js +23 -0
  195. package/dist/selftest/sync.test.d.ts +3 -0
  196. package/dist/selftest/sync.test.js +82 -0
  197. package/dist/shared/download.d.ts +58 -0
  198. package/dist/shared/download.js +200 -0
  199. package/dist/shared/guest-paths.d.ts +30 -0
  200. package/dist/shared/guest-paths.js +61 -0
  201. package/dist/shared/netrules.d.ts +18 -0
  202. package/dist/shared/netrules.js +98 -0
  203. package/dist/shared/paths.d.ts +9 -0
  204. package/dist/shared/paths.js +22 -0
  205. package/dist/shared/pty-client.d.ts +86 -0
  206. package/dist/shared/pty-client.js +227 -0
  207. package/dist/shared/rundir.d.ts +30 -0
  208. package/dist/shared/rundir.js +86 -0
  209. package/dist/shared/safe-remove.d.ts +10 -0
  210. package/dist/shared/safe-remove.js +55 -0
  211. package/dist/shared/schema.d.ts +84 -0
  212. package/dist/shared/schema.js +51 -0
  213. package/dist/shared/system.d.ts +15 -0
  214. package/dist/shared/system.js +19 -0
  215. package/dist/sync/claude-mem.d.ts +8 -0
  216. package/dist/sync/claude-mem.js +77 -0
  217. package/dist/sync/history.d.ts +30 -0
  218. package/dist/sync/history.js +129 -0
  219. package/dist/sync/watcher.d.ts +13 -0
  220. package/dist/sync/watcher.js +116 -0
  221. package/hooks/post-agent/README.txt +1 -0
  222. package/hooks/pre-provision/README.txt +1 -0
  223. package/package.json +91 -4
  224. package/sandbox/bootstrap.ps1 +258 -0
  225. package/sandbox/gitshim.cs +35 -0
  226. package/sandbox/logon.cmd +16 -0
  227. package/sandbox/ptyhost.cs +603 -0
  228. package/sandbox/trust.cmd +35 -0
  229. package/sandbox/vswhere.cs +83 -0
  230. package/schemas/config.schema.json +1062 -0
  231. package/schemas/sandbox-config.schema.json +952 -0
@@ -0,0 +1,58 @@
1
+ import { projectUses } from '../guest/toolchains/versions.js';
2
+ /** Files that show a project uses a language (looked for in the workspace and one folder down). */
3
+ export const MARKERS = {
4
+ python: ['pyproject.toml', 'requirements.txt', 'setup.py', 'setup.cfg', 'Pipfile', 'uv.lock', 'poetry.lock', '.python-version', '*.py', '*.ipynb'],
5
+ rust: ['Cargo.toml', 'rust-toolchain', 'rust-toolchain.toml'],
6
+ msvc: ['*.vcxproj', 'CMakePresets.json', 'CMakeUserPresets.json'],
7
+ cpp: ['CMakeLists.txt', 'Makefile', 'meson.build', 'premake5.lua', 'Cargo.toml', '*.vcxproj', '*.c', '*.cpp', '*.cc', '*.h', '*.hpp'],
8
+ dotnet: ['*.sln', '*.slnx', '*.csproj', '*.fsproj', '*.vbproj', 'global.json', '*.cs'],
9
+ go: ['go.mod', 'go.work', '*.go'],
10
+ java: ['pom.xml', 'build.gradle', 'build.gradle.kts', 'settings.gradle', 'settings.gradle.kts', 'mvnw', 'gradlew', '.java-version', '.sdkmanrc', '*.java'],
11
+ ruby: ['Gemfile', '*.gemspec', '.ruby-version', '*.rb'],
12
+ php: ['composer.json', 'artisan', '.php-version', '*.php'],
13
+ deno: ['deno.json', 'deno.jsonc', 'deno.lock'],
14
+ // Windows PowerShell 5.1 runs any .ps1: PowerShell 7 is decided from script contents (hints.pwsh) or this PC.
15
+ pwsh: [],
16
+ };
17
+ export const AUTO_TOOLCHAINS = Object.keys(MARKERS);
18
+ /** Files of any ecosystem: a folder with none of them is no project yet. */
19
+ const PROJECT_FILES = [...new Set([...Object.values(MARKERS).flat(), 'package.json', 'deno.json', '*.ts', '*.js'])];
20
+ /**
21
+ * The decision per toolchain. true/false are kept; "auto" is on when the project has one of its marker files, or, in
22
+ * a folder that is no project yet, when this PC has the language installed. Rust needs a linker (MSVC or C/C++).
23
+ * hints: reasons found by reading files (a script that calls vcvars/vswhere) or about this PC ("builds Rust with MSVC"),
24
+ * which turn an "auto" toolchain on like a marker file does.
25
+ */
26
+ export const decideToolchains = (settings, entries, pcHas, hints = {}) => {
27
+ const fresh = !projectUses(entries, PROJECT_FILES);
28
+ const decide = (name) => {
29
+ const setting = settings[name].enabled;
30
+ if (setting !== 'auto')
31
+ return { on: setting, reason: setting ? 'enabled in config' : 'disabled in config' };
32
+ const marker = MARKERS[name].map((m) => entries.find((e) => projectUses([e], [m]))).find(Boolean);
33
+ if (marker)
34
+ return { on: true, reason: marker };
35
+ if (hints[name])
36
+ return { on: true, reason: hints[name] };
37
+ if (fresh && pcHas.includes(name))
38
+ return { on: true, reason: 'installed on this PC (new folder)' };
39
+ return { on: false, reason: 'not used by this project' };
40
+ };
41
+ const result = Object.fromEntries(AUTO_TOOLCHAINS.map((name) => [name, decide(name)]));
42
+ // Rust links with MSVC when this PC does (its rustup host is *-msvc), otherwise with MinGW's gcc.
43
+ if (result.rust.on && settings.msvc.enabled === 'auto' && !result.msvc.on && pcHas.includes('msvc'))
44
+ result.msvc = { on: true, reason: 'Rust on this PC builds with MSVC' };
45
+ // MSVC is a 1-2 GB licensed download: "auto" only installs it once its licence is accepted.
46
+ if (settings.msvc.enabled === 'auto' && result.msvc.on && !settings.msvc.acceptLicense)
47
+ result.msvc = { on: false, reason: 'would be used (' + result.msvc.reason + '); set toolchains.msvc.acceptLicense to install it' };
48
+ if (result.rust.on && !result.msvc.on && !result.cpp.on && settings.cpp.enabled !== false)
49
+ result.cpp = { on: true, reason: 'the linker for Rust' };
50
+ return result;
51
+ };
52
+ /** The settings with every "auto" replaced by the decision (what the sandbox receives). */
53
+ export const resolveToolchains = (settings, decisions) => {
54
+ const out = structuredClone(settings);
55
+ for (const name of AUTO_TOOLCHAINS)
56
+ out[name].enabled = decisions[name].on;
57
+ return out;
58
+ };
@@ -0,0 +1,12 @@
1
+ import type { Config, LocalConfigFile, Overrides } from './types.js';
2
+ export declare const LOCAL_CONFIG_NAME = ".sandbox-config.json";
3
+ /** Validates a folder's settings and resolves its relative paths against that folder. */
4
+ export declare const normalizeOverrides: (data: unknown, dir: string, source: string) => Overrides;
5
+ /** Applies validated overrides. Mappings with the same guest folder replace the configured ones. */
6
+ export declare const applyOverrides: (config: Config, ov: Overrides) => Config;
7
+ /** Human-readable list of what a local config changes, with risky items flagged. */
8
+ export declare const describeOverrides: (ov: Overrides) => string[];
9
+ export declare const readLocalConfig: (dir: string) => LocalConfigFile | null;
10
+ export declare const trustStorePath: (storageRoot: string) => string;
11
+ export declare const isTrusted: (store: string, file: string, hash: string) => boolean;
12
+ export declare const saveTrust: (store: string, file: string, hash: string) => void;
@@ -0,0 +1,64 @@
1
+ // A project's .sandbox-config.json: validated against the LocalOverrides schema (a safe subset of settings), applied
2
+ // over the user config, and only used once you have approved this exact version of the file.
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import crypto from 'node:crypto';
6
+ import _ from 'lodash';
7
+ import { mergeConfig } from './config.js';
8
+ import { describeIssues, LocalOverrides } from './schema.js';
9
+ import { expandPath, fail, fileExists, parseJsonc, tryReadJson, writeJson } from './util.js';
10
+ export const LOCAL_CONFIG_NAME = '.sandbox-config.json';
11
+ /** Validates a folder's settings and resolves its relative paths against that folder. */
12
+ export const normalizeOverrides = (data, dir, source) => {
13
+ const parsed = LocalOverrides.safeParse(data);
14
+ if (!parsed.success)
15
+ fail(source + ' is not valid:\n - ' + describeIssues(parsed.error).join('\n - '));
16
+ const overrides = parsed.data;
17
+ const scripts = overrides.scripts?.map((s) => expandPath(s, dir));
18
+ const missing = scripts?.filter((s) => !fileExists(s)) ?? [];
19
+ if (missing.length)
20
+ fail(source + ' is not valid:\n - scripts: file not found: ' + missing.join(', '));
21
+ return { ...overrides, scripts, mappings: overrides.mappings?.map((m) => ({ ...m, host: expandPath(m.host, dir) })) };
22
+ };
23
+ /** Applies validated overrides. Mappings with the same guest folder replace the configured ones. */
24
+ export const applyOverrides = (config, ov) => {
25
+ const { harness, mappings, scripts: _scripts, $schema: _schema, ...rest } = ov;
26
+ const next = mergeConfig(config, rest);
27
+ if (harness)
28
+ next.defaultHarness = harness;
29
+ if (mappings)
30
+ next.mappings = [..._.reject(config.mappings, (m) => mappings.some((o) => o.guest.toLowerCase() === m.guest.toLowerCase())), ...mappings];
31
+ return next;
32
+ };
33
+ const flatten = (value, prefix = '') => _.isPlainObject(value) ? Object.entries(value).flatMap(([k, v]) => flatten(v, prefix ? prefix + '.' + k : k)) : [prefix + ' = ' + JSON.stringify(value)];
34
+ /** Human-readable list of what a local config changes, with risky items flagged. */
35
+ export const describeOverrides = (ov) => {
36
+ const { harness, mappings = [], scripts = [], $schema: _schema, ...sections } = ov;
37
+ const lines = [
38
+ ...(harness ? ['agent = ' + harness] : []),
39
+ ...mappings.map((m) => (m.readOnly ? 'read-only' : 'READ/WRITE') + ' folder ' + m.host + ' -> ' + m.guest),
40
+ ...scripts.map((s) => 'runs inside the sandbox: ' + s),
41
+ ...flatten(sections),
42
+ ];
43
+ const risky = _.compact([
44
+ ov.claudeProfile?.copyCredentials === true && 'claudeProfile.copyCredentials = true copies your Claude LOGIN into the sandbox',
45
+ ov.network?.blockPrivateRanges === false && 'network.blockPrivateRanges = false turns OFF the LAN block',
46
+ mappings.some((m) => !m.readOnly) && 'a READ/WRITE mapping lets the agent change files outside your workspace',
47
+ ov.provisioning?.git?.access === 'full' && 'provisioning.git.access = full lets the agent commit and push',
48
+ ov.sandbox?.vGpu === true && 'sandbox.vGpu = true widens the sandbox attack surface',
49
+ ]);
50
+ return [...lines, ...risky.map((r) => '!! ' + r)];
51
+ };
52
+ export const readLocalConfig = (dir) => {
53
+ const file = path.join(dir, LOCAL_CONFIG_NAME);
54
+ if (!fileExists(file))
55
+ return null;
56
+ const raw = fs.readFileSync(file);
57
+ return { path: file, hash: crypto.createHash('sha256').update(raw).digest('hex'), data: parseJsonc(raw.toString('utf8'), file) };
58
+ };
59
+ // ---- approvals (host-only: <storage>\trusted-configs.json) ----------------------------------------------------------
60
+ export const trustStorePath = (storageRoot) => path.join(storageRoot, 'trusted-configs.json');
61
+ const loadTrust = (store) => tryReadJson(store) ?? {};
62
+ const key = (file) => path.resolve(file).toLowerCase();
63
+ export const isTrusted = (store, file, hash) => loadTrust(store)[key(file)] === hash;
64
+ export const saveTrust = (store, file, hash) => writeJson(store, { ...loadTrust(store), [key(file)]: hash });